this repo has no description
at develop 9.0 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Mikael Lagerkvist <lagerkvist@gecode.org> 5 * 6 * Copyright: 7 * Mikael Lagerkvist, 2005 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34#include "test/int.hh" 35 36#include <gecode/minimodel.hh> 37#include <gecode/search.hh> 38 39#include <vector> 40#include <algorithm> 41#include <string> 42#include <sstream> 43 44namespace Test { namespace Int { 45 46 /// %Tests for scheduling constraints 47 namespace Cumulatives { 48 49 /** 50 * \defgroup TaskTestIntCumulatives Cumnulatives scheduling constraint 51 * \ingroup TaskTestInt 52 */ 53 //@{ 54 /** 55 * \brief Script for generating assignments. 56 * 57 * We are only interested in assignments that represent tasks (s_i, 58 * d_i, e_i, h_i) such that the following hold: 59 * - The task starts at a positive time and has some extension. 60 * - The equation s_i + d_i = e_i holds. 61 * - The tasks are ordered to remove some symmetries, i.e., 62 * s_i <= s_{i+1} 63 */ 64 class Ass : public Gecode::Space { 65 public: 66 /// Store task information 67 Gecode::IntVarArray x; 68 /// Initialize model for assignments 69 Ass(int n, const Gecode::IntSet& d) : x(*this, n, d) { 70 using namespace Gecode; 71 for (int i = 0; i < n; i += 4) { 72 rel(*this, x[i+0] >= 0); 73 rel(*this, x[i+1] >= 0); 74 rel(*this, x[i+2] >= 0); 75 rel(*this, x[i] + x[i+1] == x[i+2]); 76 branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN()); 77 } 78 } 79 /// Constructor for cloning \a s 80 Ass(Ass& s) : Gecode::Space(s) { 81 x.update(*this, s.x); 82 } 83 /// Create copy during cloning 84 virtual Gecode::Space* copy(void) { 85 return new Ass(*this); 86 } 87 }; 88 89 /// Class for generating reasonable assignments 90 class CumulativeAssignment : public Assignment { 91 /// Current assignment 92 Ass* cur; 93 /// Next assignment 94 Ass* nxt; 95 /// Search engine to find assignments 96 Gecode::DFS<Ass>* e; 97 public: 98 /// Initialize assignments for \a n0 variables and values \a d0 99 CumulativeAssignment(int n, const Gecode::IntSet& d) : Assignment(n,d) { 100 Ass* a = new Ass(n, d); 101 e = new Gecode::DFS<Ass>(a); 102 delete a; 103 nxt = cur = e->next(); 104 if (cur != nullptr) 105 nxt = e->next(); 106 } 107 /// %Test whether all assignments have been iterated 108 virtual bool has_more(void) const { 109 return nxt != nullptr; 110 } 111 /// Move to next assignment 112 virtual void next(Gecode::Support::RandomGenerator&) { 113 delete cur; 114 cur = nxt; 115 if (cur != nullptr) nxt = e->next(); 116 } 117 /// Return value for variable \a i 118 virtual int operator[](int i) const { 119 assert((i>=0) && (i<n) && (cur != nullptr)); 120 return cur->x[i].val(); 121 } 122 /// Destructor 123 virtual ~CumulativeAssignment(void) { 124 delete cur; delete nxt; delete e; 125 } 126 }; 127 128 /// %Event to be scheduled 129 class Event { 130 public: 131 int p, h; ///< Position and height of event 132 bool start; ///< Whether event has just started 133 /// Initialize event 134 Event(int pos, int height, bool s) : p(pos), h(height), start(s) {} 135 /// %Test whether this event is before event \a e 136 bool operator<(const Event& e) const { 137 return p<e.p; 138 } 139 }; 140 141 /// Describe that event is below a certain limit 142 class Below { 143 public: 144 int limit; ///< limit 145 /// Initialize 146 Below(int l) : limit(l) {} 147 /// %Test whether \a val is below limit 148 bool operator()(int val) { 149 return val <= limit; 150 } 151 }; 152 /// Describe that event is above a certain limit 153 class Above { 154 public: 155 int limit; ///< limit 156 /// Initialize 157 Above(int l) : limit(l) {} 158 /// %Test whether \a val is above limit 159 bool operator()(int val) { 160 return val >= limit; 161 } 162 }; 163 164 /// Check whether event \a e is valid 165 template<class C> 166 bool valid(std::vector<Event> e, C comp) { 167 std::sort(e.begin(), e.end()); 168 unsigned int i = 0; 169 int p = 0; 170 int h = 0; 171 int n = 0; 172 while (i < e.size()) { 173 p = e[i].p; 174 while (i < e.size() && e[i].p == p) { 175 h += e[i].h; 176 n += (e[i].start ? +1 : -1); 177 ++i; 178 } 179 if (n && !comp(h)) 180 return false; 181 } 182 return true; 183 } 184 185 /// %Test for cumulatives constraint 186 class Cumulatives : public Test { 187 protected: 188 int ntasks; ///< Number of tasks 189 bool at_most; ///< Whether to use atmost reasoning 190 int limit; ///< Limit 191 public: 192 /// Create and register test 193 Cumulatives(const std::string& s, int nt, bool am, int l) 194 : Test("Cumulatives::"+s,nt*4,-1,2), ntasks(nt), at_most(am), limit(l) { 195 testsearch = false; 196 } 197 /// Create first assignment 198 virtual Assignment* assignment(void) const { 199 assert(arity == 4*ntasks); 200 return new CumulativeAssignment(arity, dom); 201 } 202 /// %Test whether \a x is solution 203 virtual bool solution(const Assignment& x) const { 204 std::vector<Event> e; 205 for (int i = 0; i < ntasks; ++i) { 206 int p = i*4; 207 // Positive start, duration and end 208 if (x[p+0] < 0 || x[p+1] < 1 || x[p+2] < 1) return false; 209 // Start + Duration == End 210 if (x[p+0] + x[p+1] != x[p+2]) { 211 return false; 212 } 213 } 214 for (int i = 0; i < ntasks; ++i) { 215 int p = i*4; 216 // Up at start, down at end. 217 e.push_back(Event(x[p+0], +x[p+3], true)); 218 e.push_back(Event(x[p+2], -x[p+3], false)); 219 } 220 if (at_most) { 221 return valid(e, Below(limit)); 222 } else { 223 return valid(e, Above(limit)); 224 } 225 } 226 /// Post constraint on \a x 227 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) { 228 using namespace Gecode; 229 IntArgs m(ntasks), l({limit}); 230 IntVarArgs s(ntasks), d(ntasks), e(ntasks), h(ntasks); 231 for (int i = 0; i < ntasks; ++i) { 232 int p = i*4; 233 m[i] = 0; 234 s[i] = x[p+0]; rel(home, x[p+0], Gecode::IRT_GQ, 0); 235 d[i] = x[p+1]; rel(home, x[p+1], Gecode::IRT_GQ, 1); 236 e[i] = x[p+2]; rel(home, x[p+2], Gecode::IRT_GQ, 1); 237 h[i] = x[p+3]; 238 } 239 cumulatives(home, m, s, d, e, h, l, at_most); 240 } 241 }; 242 243 Cumulatives c1t1("1t1", 1, true, 1); 244 Cumulatives c1f1("1f1", 1, false, 1); 245 Cumulatives c1t2("1t2", 1, true, 2); 246 Cumulatives c1f2("1f2", 1, false, 2); 247 Cumulatives c1t3("1t3", 1, true, 3); 248 Cumulatives c1f3("1f3", 1, false, 3); 249 Cumulatives c2t1("2t1", 2, true, 1); 250 Cumulatives c2f1("2f1", 2, false, 1); 251 Cumulatives c2t2("2t2", 2, true, 2); 252 Cumulatives c2f2("2f2", 2, false, 2); 253 Cumulatives c2t3("2t3", 2, true, 3); 254 Cumulatives c2f3("2f3", 2, false, 3); 255 Cumulatives c3t1("3t1", 3, true, 1); 256 Cumulatives c3f1("3f1", 3, false, 1); 257 Cumulatives c3t2("3t2", 3, true, 2); 258 Cumulatives c3f2("3f2", 3, false, 2); 259 Cumulatives c3t3("3t3", 3, true, 3); 260 Cumulatives c3f3("3f3", 3, false, 3); 261 Cumulatives c3t_1("3t-1", 3, true, -1); 262 Cumulatives c3f_1("3f-1", 3, false, -1); 263 Cumulatives c3t_2("3t-2", 3, true, -2); 264 Cumulatives c3f_2("3f-2", 3, false, -2); 265 Cumulatives c3t_3("3t-3", 3, true, -3); 266 Cumulatives c3f_3("3f-3", 3, false, -3); 267 //@} 268 269 } 270}} 271 272// STATISTICS: test-int