this repo has no description
at develop 21 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Copyright: 7 * Christian Schulte, 2009 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 38namespace Test { namespace Int { 39 40 /// Tests for cumulative scheduling constraints 41 namespace Cumulative { 42 43 /** 44 * \defgroup TaskTestIntCumulative Cumulative scheduling constraints 45 * \ingroup TaskTestInt 46 */ 47 //@{ 48 /// Test for cumulative constraint with mandatory tasks 49 class ManFixPCumulative : public Test { 50 protected: 51 /// Capacity of resource 52 int c; 53 /// The processing times 54 Gecode::IntArgs p; 55 /// The resource usage 56 Gecode::IntArgs u; 57 /// Get a reasonable maximal start time 58 static int st(int c, 59 const Gecode::IntArgs& p, const Gecode::IntArgs& u) { 60 double e = 0; 61 for (int i=p.size(); i--; ) 62 e += static_cast<double>(p[i])*u[i]; 63 return e / std::max(1,std::abs(c)); 64 } 65 /// Offset 66 int o; 67 public: 68 /// Create and register test 69 ManFixPCumulative(int c0, 70 const Gecode::IntArgs& p0, 71 const Gecode::IntArgs& u0, 72 int o0, 73 Gecode::IntPropLevel ipl0) 74 : Test("Cumulative::Man::Fix::"+str(o0)+"::"+ 75 str(c0)+"::"+str(p0)+"::"+str(u0)+"::"+str(ipl0), 76 (c0 >= 0) ? p0.size():p0.size()+1,0,st(c0,p0,u0),false,ipl0), 77 c(c0), p(p0), u(u0), o(o0) { 78 testsearch = false; 79 testfix = false; 80 contest = CTL_NONE; 81 } 82 /// Create and register initial assignment 83 virtual Assignment* assignment(void) const { 84 return new RandomAssignment(arity, dom, 500, _rand); 85 } 86 /// Test whether \a x is solution 87 virtual bool solution(const Assignment& x) const { 88 int cmax = (c >= 0) ? c : x[x.size()-1]; 89 int n = (c >= 0) ? x.size() : x.size()-1; 90 91 if (c < 0 && x[n] > -c) 92 return false; 93 94 // Compute maximal time 95 int t = 0; 96 for (int i=0; i<n; i++) 97 t = std::max(t,x[i]+std::max(1,p[i])); 98 // Compute resource usage (including at start times) 99 int* used = new int[t]; 100 for (int i=0; i<t; i++) 101 used[i] = 0; 102 for (int i=0; i<n; i++) 103 for (int t=0; t<p[i]; t++) 104 used[x[i]+t] += u[i]; 105 // Check resource usage 106 for (int i=0; i<t; i++) 107 if (used[i] > cmax) { 108 delete [] used; 109 return false; 110 } 111 // Compute resource usage (only internal) 112 for (int i=0; i<t; i++) 113 used[i] = 0; 114 for (int i=0; i<n; i++) { 115 for (int t=1; t<p[i]; t++) { 116 used[x[i]+t] += u[i]; 117 } 118 } 119 // Check resource usage at start times 120 for (int i=0; i<n; i++) 121 if (used[x[i]]+u[i] > cmax) { 122 delete [] used; 123 return false; 124 } 125 delete [] used; 126 return true; 127 } 128 /// Post constraint on \a x 129 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) { 130 int n = (c >= 0) ? x.size() : x.size()-1; 131 Gecode::IntVarArgs xx; 132 if (o==0) { 133 xx=x.slice(0,1,n); 134 } else { 135 xx=Gecode::IntVarArgs(n); 136 for (int i=n; i--;) 137 xx[i]=Gecode::expr(home,x[i]+o,Gecode::IPL_DOM); 138 } 139 if (c >= 0) { 140 Gecode::cumulative(home, c, xx, p, u, ipl); 141 } else { 142 Gecode::rel(home, x[n] <= -c); 143 Gecode::cumulative(home, x[n], xx, p, u, ipl); 144 } 145 } 146 }; 147 148 149 /// Test for cumulative constraint with optional tasks 150 class OptFixPCumulative : public Test { 151 protected: 152 /// Capacity of resource 153 int c; 154 /// The processing times 155 Gecode::IntArgs p; 156 /// The resource usage 157 Gecode::IntArgs u; 158 /// Limit for optional tasks 159 int l; 160 /// Offset 161 int o; 162 /// Get a reasonable maximal start time 163 static int st(int c, 164 const Gecode::IntArgs& p, const Gecode::IntArgs& u) { 165 double e = 0; 166 for (int i=p.size(); i--; ) 167 e += static_cast<double>(p[i])*u[i]; 168 return e / std::max(1,std::abs(c)); 169 } 170 public: 171 /// Create and register test 172 OptFixPCumulative(int c0, 173 const Gecode::IntArgs& p0, 174 const Gecode::IntArgs& u0, 175 int o0, 176 Gecode::IntPropLevel ipl0) 177 : Test("Cumulative::Opt::Fix::"+str(o0)+"::"+ 178 str(c0)+"::"+str(p0)+"::"+str(u0)+"::"+str(ipl0), 179 (c0 >= 0) ? 2*p0.size() : 2*p0.size()+1,0,st(c0,p0,u0), 180 false,ipl0), 181 c(c0), p(p0), u(u0), l(st(c,p,u)/2), o(o0) { 182 testsearch = false; 183 testfix = false; 184 contest = CTL_NONE; 185 } 186 /// Create and register initial assignment 187 virtual Assignment* assignment(void) const { 188 return new RandomAssignment(arity, dom, 500, _rand); 189 } 190 /// Test whether \a x is solution 191 virtual bool solution(const Assignment& x) const { 192 int nn = (c >= 0) ? x.size() : x.size()-1; 193 int cmax = (c >= 0) ? c : x[nn]; 194 195 if (c < 0 && x[nn] > -c) 196 return false; 197 198 int n = nn / 2; 199 // Compute maximal time 200 int t = 0; 201 for (int i=0; i<n; i++) 202 t = std::max(t,x[i]+std::max(1,p[i])); 203 // Compute resource usage (including at start times) 204 int* used = new int[t]; 205 for (int i=0; i<t; i++) 206 used[i] = 0; 207 for (int i=0; i<n; i++) 208 if (x[n+i] > l) 209 for (int t=0; t<p[i]; t++) 210 used[x[i]+t] += u[i]; 211 // Check resource usage 212 for (int i=0; i<t; i++) { 213 if (used[i] > cmax) { 214 delete [] used; 215 return false; 216 } 217 } 218 // Compute resource usage (only internal) 219 for (int i=0; i<t; i++) 220 used[i] = 0; 221 for (int i=0; i<n; i++) 222 if (x[n+i] > l) { 223 for (int t=1; t<p[i]; t++) 224 used[x[i]+t] += u[i]; 225 } 226 // Check resource usage at start times 227 for (int i=0; i<n; i++) 228 if (x[n+i] > l) 229 if (used[x[i]]+u[i] > cmax) { 230 delete [] used; 231 return false; 232 } 233 delete [] used; 234 return true; 235 } 236 /// Post constraint on \a x 237 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) { 238 int nn=(c >= 0) ? x.size() : x.size()-1; 239 int n=nn / 2; 240 Gecode::IntVarArgs s(n); 241 Gecode::BoolVarArgs m(n); 242 243 for (int i=0; i<n; i++) { 244 s[i]=(c >= 0) ? x[i] : Gecode::expr(home,x[i]+o,Gecode::IPL_DOM); 245 m[i]=Gecode::expr(home, x[n+i] > l); 246 } 247 248 if (c >= 0) { 249 Gecode::cumulative(home, c, s, p, u, m, ipl); 250 } else { 251 Gecode::rel(home, x[nn] <= -c); 252 Gecode::cumulative(home, x[nn], s, p, u, m, ipl); 253 } 254 } 255 }; 256 257 /// Test for cumulative constraint with flexible mandatory tasks 258 class ManFlexCumulative : public Test { 259 protected: 260 /// Capacity of resource 261 int c; 262 /// Minimum processing time 263 int _minP; 264 /// Maximum processing time 265 int _maxP; 266 /// The resource usage 267 Gecode::IntArgs u; 268 /// Get a reasonable maximal start time 269 static int st(int c, int maxP, const Gecode::IntArgs& u) { 270 double e = 0; 271 for (int i=u.size(); i--; ) 272 e += static_cast<double>(maxP)*u[i]; 273 return e / std::max(1,std::abs(c)); 274 } 275 /// Offset 276 int o; 277 public: 278 /// Create and register test 279 ManFlexCumulative(int c0, int minP, int maxP, 280 const Gecode::IntArgs& u0, 281 int o0, 282 Gecode::IntPropLevel ipl0) 283 : Test("Cumulative::Man::Flex::"+str(o0)+"::"+ 284 str(c0)+"::"+str(minP)+"::"+str(maxP)+"::"+str(u0)+ 285 "::"+str(ipl0), 286 (c0 >= 0) ? 2*u0.size() : 2*u0.size()+1, 287 0,std::max(maxP,st(c0,maxP,u0)),false,ipl0), 288 c(c0), _minP(minP), _maxP(maxP), u(u0), o(o0) { 289 testsearch = false; 290 testfix = false; 291 contest = CTL_NONE; 292 } 293 /// Create and register initial assignment 294 virtual Assignment* assignment(void) const { 295 return new RandomMixAssignment((c >= 0) ? arity / 2 : arity / 2 + 1, 296 dom, arity / 2, 297 Gecode::IntSet(_minP, _maxP), 500, _rand); 298 } 299 /// Test whether \a x is solution 300 virtual bool solution(const Assignment& x) const { 301 int nn = (c >= 0) ? x.size() : x.size()-1; 302 int n = nn/2; 303 int cmax = (c >= 0) ? c : x[n]; 304 int pstart = (c >= 0) ? n : n+1; 305 306 if (c < 0 && cmax > -c) 307 return false; 308 309 // Compute maximal time 310 int t = 0; 311 for (int i=0; i<n; i++) { 312 t = std::max(t,x[i]+std::max(1,x[pstart+i])); 313 } 314 // Compute resource usage (including at start times) 315 int* used = new int[t]; 316 for (int i=0; i<t; i++) 317 used[i] = 0; 318 for (int i=0; i<n; i++) 319 for (int t=0; t<x[pstart+i]; t++) 320 used[x[i]+t] += u[i]; 321 // Check resource usage 322 for (int i=0; i<t; i++) 323 if (used[i] > cmax) { 324 delete [] used; 325 return false; 326 } 327 // Compute resource usage (only internal) 328 for (int i=0; i<t; i++) 329 used[i] = 0; 330 for (int i=0; i<n; i++) { 331 for (int t=1; t<x[pstart+i]; t++) 332 used[x[i]+t] += u[i]; 333 } 334 // Check resource usage at start times 335 for (int i=0; i<n; i++) 336 if (used[x[i]]+u[i] > cmax) { 337 delete [] used; 338 return false; 339 } 340 delete [] used; 341 return true; 342 } 343 /// Post constraint on \a x 344 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) { 345 int nn = (c >= 0) ? x.size() : x.size()-1; 346 int n = nn/2; 347 int pstart = (c >= 0) ? n : n+1; 348 Gecode::IntVarArgs s(n); 349 Gecode::IntVarArgs px(x.slice(pstart,1,n)); 350 Gecode::IntVarArgs e(home,n, 351 Gecode::Int::Limits::min, 352 Gecode::Int::Limits::max); 353 for (int i=s.size(); i--;) { 354 s[i] = expr(home, o+x[i], Gecode::IPL_DOM); 355 rel(home, s[i]+px[i] == e[i]); 356 rel(home, _minP <= px[i]); 357 rel(home, _maxP >= px[i]); 358 } 359 if (c >= 0) { 360 Gecode::cumulative(home, c, s, px, e, u, ipl); 361 } else { 362 rel(home, x[n] <= -c); 363 Gecode::cumulative(home, x[n], s, px, e, u, ipl); 364 } 365 } 366 }; 367 368 /// Test for cumulative constraint with optional flexible tasks 369 class OptFlexCumulative : public Test { 370 protected: 371 /// Capacity of resource 372 int c; 373 /// Minimum processing time 374 int _minP; 375 /// Maximum processing time 376 int _maxP; 377 /// The resource usage 378 Gecode::IntArgs u; 379 /// Limit for optional tasks 380 int l; 381 /// Offset 382 int o; 383 /// Get a reasonable maximal start time 384 static int st(int c, int maxP, const Gecode::IntArgs& u) { 385 double e = 0; 386 for (int i=u.size(); i--; ) 387 e += static_cast<double>(maxP)*u[i]; 388 return e / std::max(1,std::abs(c)); 389 } 390 public: 391 /// Create and register test 392 OptFlexCumulative(int c0, int minP, int maxP, 393 const Gecode::IntArgs& u0, 394 int o0, 395 Gecode::IntPropLevel ipl0) 396 : Test("Cumulative::Opt::Flex::"+str(o0)+"::"+ 397 str(c0)+"::"+str(minP)+"::"+str(maxP)+"::"+str(u0)+ 398 "::"+str(ipl0), 399 (c0 >= 0) ? 3*u0.size() : 3*u0.size()+1, 400 0,std::max(maxP,st(c0,maxP,u0)), false,ipl0), 401 c(c0), _minP(minP), _maxP(maxP), u(u0), 402 l(std::max(maxP,st(c0,maxP,u0))/2), o(o0) { 403 testsearch = false; 404 testfix = false; 405 contest = CTL_NONE; 406 } 407 /// Create and register initial assignment 408 virtual Assignment* assignment(void) const { 409 return new RandomMixAssignment((c >= 0) ? 2 * (arity / 3) : 2 * (arity / 3) + 1, 410 dom, arity / 3, 411 Gecode::IntSet(_minP, _maxP), 500, _rand); 412 } 413 /// Test whether \a x is solution 414 virtual bool solution(const Assignment& x) const { 415 int nn = (c >= 0) ? x.size() : x.size()-1; 416 int n = nn / 3; 417 int cmax = (c >= 0) ? c : x[2*n]; 418 int pstart = (c >= 0) ? 2*n : 2*n+1; 419 420 if (c < 0 && cmax > -c) 421 return false; 422 423 // Compute maximal time 424 int t = 0; 425 for (int i=0; i<n; i++) 426 t = std::max(t,x[i]+std::max(1,x[pstart+i])); 427 // Compute resource usage (including at start times) 428 int* used = new int[t]; 429 for (int i=0; i<t; i++) 430 used[i] = 0; 431 for (int i=0; i<n; i++) 432 if (x[n+i] > l) 433 for (int t=0; t<x[pstart+i]; t++) 434 used[x[i]+t] += u[i]; 435 // Check resource usage 436 for (int i=0; i<t; i++) 437 if (used[i] > cmax) { 438 delete [] used; 439 return false; 440 } 441 // Compute resource usage (only internal) 442 for (int i=0; i<t; i++) 443 used[i] = 0; 444 for (int i=0; i<n; i++) 445 if (x[n+i] > l) 446 for (int t=1; t<x[pstart+i]; t++) 447 used[x[i]+t] += u[i]; 448 // Check resource usage at start times 449 for (int i=0; i<n; i++) 450 if (x[n+i] > l && used[x[i]]+u[i] > cmax) { 451 delete [] used; 452 return false; 453 } 454 delete [] used; 455 return true; 456 } 457 /// Post constraint on \a x 458 virtual void post(Gecode::Space& home, Gecode::IntVarArray& x) { 459 int nn = (c >= 0) ? x.size() : x.size()-1; 460 int n=nn / 3; 461 int pstart= (c >= 0) ? 2*n : 2*n+1; 462 463 Gecode::IntVarArgs s(n); 464 Gecode::IntVarArgs px(n); 465 Gecode::IntVarArgs e(home,n, 466 Gecode::Int::Limits::min, 467 Gecode::Int::Limits::max); 468 for (int i=n; i--;) { 469 s[i] = expr(home, o+x[i]); 470 px[i] = x[pstart+i]; 471 rel(home, s[i]+px[i] == e[i]); 472 rel(home, _minP <= px[i]); 473 rel(home, _maxP >= px[i]); 474 } 475 Gecode::BoolVarArgs m(n); 476 for (int i=0; i<n; i++) 477 m[i]=Gecode::expr(home, (x[n+i] > l)); 478 if (c >= 0) { 479 Gecode::cumulative(home, c, s, px, e, u, m, ipl); 480 } else { 481 Gecode::rel(home, x[2*n] <= -c); 482 Gecode::cumulative(home, x[2*n], s, px, e, u, m, ipl); 483 } 484 } 485 }; 486 487 /// Help class to create and register tests 488 class Create { 489 public: 490 /// Perform creation and registration 491 Create(void) { 492 using namespace Gecode; 493 IntArgs p1({1,1,1,1}); 494 IntArgs p2({2,2,2,2}); 495 IntArgs p3({4,3,3,5}); 496 IntArgs p4({4,0,3,5}); 497 IntArgs p5({1,1,1}); 498 499 IntArgs u1({1,1,1,1}); 500 IntArgs u2({2,2,2,2}); 501 IntArgs u3({2,3,4,5}); 502 IntArgs u4({2,3,0,5}); 503 IntArgs u5({1,3,2}); 504 505 for (IntPropBasicAdvanced ipba; ipba(); ++ipba) { 506 // Regression test: check correct detection of disjunctive case 507 (void) new ManFixPCumulative(3,p5,u5,0,ipba.ipl()); 508 509 for (int c=-7; c<8; c++) { 510 int off = 0; 511 for (int coff=0; coff<2; coff++) { 512 (void) new ManFixPCumulative(c,p1,u1,off,ipba.ipl()); 513 (void) new ManFixPCumulative(c,p1,u2,off,ipba.ipl()); 514 (void) new ManFixPCumulative(c,p1,u3,off,ipba.ipl()); 515 (void) new ManFixPCumulative(c,p1,u4,off,ipba.ipl()); 516 (void) new ManFixPCumulative(c,p2,u1,off,ipba.ipl()); 517 (void) new ManFixPCumulative(c,p2,u2,off,ipba.ipl()); 518 (void) new ManFixPCumulative(c,p2,u3,off,ipba.ipl()); 519 (void) new ManFixPCumulative(c,p2,u4,off,ipba.ipl()); 520 (void) new ManFixPCumulative(c,p3,u1,off,ipba.ipl()); 521 (void) new ManFixPCumulative(c,p3,u2,off,ipba.ipl()); 522 (void) new ManFixPCumulative(c,p3,u3,off,ipba.ipl()); 523 (void) new ManFixPCumulative(c,p3,u4,off,ipba.ipl()); 524 (void) new ManFixPCumulative(c,p4,u1,off,ipba.ipl()); 525 (void) new ManFixPCumulative(c,p4,u2,off,ipba.ipl()); 526 (void) new ManFixPCumulative(c,p4,u3,off,ipba.ipl()); 527 (void) new ManFixPCumulative(c,p4,u4,off,ipba.ipl()); 528 529 (void) new ManFlexCumulative(c,0,1,u1,off,ipba.ipl()); 530 (void) new ManFlexCumulative(c,0,1,u2,off,ipba.ipl()); 531 (void) new ManFlexCumulative(c,0,1,u3,off,ipba.ipl()); 532 (void) new ManFlexCumulative(c,0,1,u4,off,ipba.ipl()); 533 (void) new ManFlexCumulative(c,0,2,u1,off,ipba.ipl()); 534 (void) new ManFlexCumulative(c,0,2,u2,off,ipba.ipl()); 535 (void) new ManFlexCumulative(c,0,2,u3,off,ipba.ipl()); 536 (void) new ManFlexCumulative(c,0,2,u4,off,ipba.ipl()); 537 (void) new ManFlexCumulative(c,3,5,u1,off,ipba.ipl()); 538 (void) new ManFlexCumulative(c,3,5,u2,off,ipba.ipl()); 539 (void) new ManFlexCumulative(c,3,5,u3,off,ipba.ipl()); 540 (void) new ManFlexCumulative(c,3,5,u4,off,ipba.ipl()); 541 542 (void) new OptFixPCumulative(c,p1,u1,off,ipba.ipl()); 543 (void) new OptFixPCumulative(c,p1,u2,off,ipba.ipl()); 544 (void) new OptFixPCumulative(c,p1,u3,off,ipba.ipl()); 545 (void) new OptFixPCumulative(c,p1,u4,off,ipba.ipl()); 546 (void) new OptFixPCumulative(c,p2,u1,off,ipba.ipl()); 547 (void) new OptFixPCumulative(c,p2,u2,off,ipba.ipl()); 548 (void) new OptFixPCumulative(c,p2,u3,off,ipba.ipl()); 549 (void) new OptFixPCumulative(c,p2,u4,off,ipba.ipl()); 550 (void) new OptFixPCumulative(c,p3,u1,off,ipba.ipl()); 551 (void) new OptFixPCumulative(c,p3,u2,off,ipba.ipl()); 552 (void) new OptFixPCumulative(c,p3,u3,off,ipba.ipl()); 553 (void) new OptFixPCumulative(c,p3,u4,off,ipba.ipl()); 554 (void) new OptFixPCumulative(c,p4,u1,off,ipba.ipl()); 555 (void) new OptFixPCumulative(c,p4,u2,off,ipba.ipl()); 556 (void) new OptFixPCumulative(c,p4,u3,off,ipba.ipl()); 557 (void) new OptFixPCumulative(c,p4,u4,off,ipba.ipl()); 558 559 (void) new OptFlexCumulative(c,0,1,u1,off,ipba.ipl()); 560 (void) new OptFlexCumulative(c,0,1,u2,off,ipba.ipl()); 561 (void) new OptFlexCumulative(c,0,1,u3,off,ipba.ipl()); 562 (void) new OptFlexCumulative(c,0,1,u4,off,ipba.ipl()); 563 (void) new OptFlexCumulative(c,0,2,u1,off,ipba.ipl()); 564 (void) new OptFlexCumulative(c,0,2,u2,off,ipba.ipl()); 565 (void) new OptFlexCumulative(c,0,2,u3,off,ipba.ipl()); 566 (void) new OptFlexCumulative(c,0,2,u4,off,ipba.ipl()); 567 (void) new OptFlexCumulative(c,3,5,u1,off,ipba.ipl()); 568 (void) new OptFlexCumulative(c,3,5,u2,off,ipba.ipl()); 569 (void) new OptFlexCumulative(c,3,5,u3,off,ipba.ipl()); 570 (void) new OptFlexCumulative(c,3,5,u4,off,ipba.ipl()); 571 572 off = Gecode::Int::Limits::min; 573 } 574 } 575 } 576 } 577 }; 578 579 Create c; 580 //@} 581 582 } 583}} 584 585// STATISTICS: test-int