001package org.clafer.choco.constraint; 002 003import java.util.ArrayList; 004import java.util.List; 005import org.clafer.choco.constraint.propagator.PropAcyclic; 006import org.clafer.choco.constraint.propagator.PropAnd; 007import org.clafer.choco.constraint.propagator.PropArrayToSet; 008import org.clafer.choco.constraint.propagator.PropArrayToSetCard; 009import org.clafer.choco.constraint.propagator.PropFilterString; 010import org.clafer.choco.constraint.propagator.PropIfThenElse; 011import org.clafer.choco.constraint.propagator.PropIntChannel; 012import org.clafer.choco.constraint.propagator.PropIntNotMemberSet; 013import org.clafer.choco.constraint.propagator.PropJoinFunction; 014import org.clafer.choco.constraint.propagator.PropJoinFunctionCard; 015import org.clafer.choco.constraint.propagator.PropJoinInjectiveRelationCard; 016import org.clafer.choco.constraint.propagator.PropJoinRelation; 017import org.clafer.choco.constraint.propagator.PropLexChainChannel; 018import org.clafer.choco.constraint.propagator.PropLone; 019import org.clafer.choco.constraint.propagator.PropMask; 020import org.clafer.choco.constraint.propagator.PropOne; 021import org.clafer.choco.constraint.propagator.PropOr; 022import org.clafer.choco.constraint.propagator.PropSelectN; 023import org.clafer.choco.constraint.propagator.PropSetDifference; 024import org.clafer.choco.constraint.propagator.PropSetNotEqualC; 025import org.clafer.choco.constraint.propagator.PropSetSum; 026import org.clafer.choco.constraint.propagator.PropSetUnion; 027import org.clafer.choco.constraint.propagator.PropSetUnionCard; 028import org.clafer.choco.constraint.propagator.PropSingleton; 029import org.clafer.choco.constraint.propagator.PropSortedSets; 030import org.clafer.choco.constraint.propagator.PropSortedSetsCard; 031import org.clafer.choco.constraint.propagator.PropUnreachable; 032import org.clafer.common.Util; 033import solver.constraints.Constraint; 034import solver.constraints.Propagator; 035import solver.constraints.binary.PropEqualXY_C; 036import solver.constraints.binary.PropEqualX_Y; 037import solver.constraints.binary.PropEqualX_YC; 038import solver.constraints.binary.PropGreaterOrEqualX_Y; 039import solver.constraints.nary.sum.PropSumEq; 040import solver.constraints.set.PropIntersection; 041import solver.constraints.set.PropSubsetEq; 042import solver.constraints.unary.PropEqualXC; 043import solver.constraints.unary.PropGreaterOrEqualXC; 044import solver.constraints.unary.PropLessOrEqualXC; 045import solver.variables.BoolVar; 046import solver.variables.IntVar; 047import solver.variables.SetVar; 048import solver.variables.VF; 049import solver.variables.Variable; 050 051/** 052 * Custom Choco constraints. Designed for Clafer. Note that these constraints 053 * requires that the envelope and kernel to be in sorted order from lowest to 054 * highest, which is not explicitly enforced by Choco. 055 * 056 * @author jimmy 057 */ 058public class Constraints { 059 060 private Constraints() { 061 } 062 063 private static Propagator<IntVar> lessThanEq(IntVar l, IntVar g) { 064 if (l.instantiated()) { 065 return new PropGreaterOrEqualXC(g, l.getValue()); 066 } 067 if (g.instantiated()) { 068 return new PropLessOrEqualXC(l, g.getValue()); 069 } 070 return new PropGreaterOrEqualX_Y(new IntVar[]{g, l}); 071 } 072 073 private static Propagator<IntVar> greaterThanEq(IntVar g, IntVar l) { 074 return lessThanEq(l, g); 075 } 076 077 private static Propagator<IntVar> sumEq(IntVar[] ints, IntVar sum) { 078 List<IntVar> filter = new ArrayList<>(ints.length); 079 int constant = 0; 080 for (IntVar var : ints) { 081 if (var.instantiated()) { 082 constant += var.getValue(); 083 } else { 084 filter.add(var); 085 } 086 } 087 IntVar[] filtered = 088 filter.size() == ints.length 089 ? ints 090 : filter.toArray(new IntVar[filter.size()]); 091 switch (filtered.length) { 092 case 0: 093 return new PropEqualXC(sum, constant); 094 case 1: 095 if (sum.instantiated()) { 096 return new PropEqualXC(filtered[0], sum.getValue() - constant); 097 } 098 return constant == 0 099 ? new PropEqualX_Y(filtered[0], sum) 100 : new PropEqualX_YC(new IntVar[]{filtered[0], sum}, -constant); 101 case 2: 102 if (sum.instantiated()) { 103 return new PropEqualXY_C(filtered, sum.getValue() - constant); 104 } 105 // fallthrough 106 default: 107 return new PropSumEq(Util.cons(VF.fixed(constant, sum.getSolver()), filtered), sum); 108 } 109 } 110 111 /** 112 ******************* 113 * 114 * Boolean. When using boolean constraints, beware of the cases where the 115 * documentation states that certain cardinality constraints are to be 116 * enforced elsewhere. The only reason is for efficiency. 117 * 118 ******************* 119 */ 120 /** 121 * A constraint enforcing 122 * {@code operands[0] ∧ operands[1] ∧ ... ∧ operands[n]}. 123 * 124 * @param operands the operands 125 * @return constraint {@code operands[0] ∧ operands[1] ∧ ... ∧ operands[n]} 126 */ 127 public static Constraint and(BoolVar... operands) { 128 Constraint<BoolVar, PropAnd> constraint = new Constraint<>(operands, operands[0].getSolver()); 129 constraint.setPropagators(new PropAnd(operands)); 130 return constraint; 131 } 132 133 /** 134 * A constraint enforcing 135 * {@code operands[0] + operands[1] + ... + operands[n] ≤ 1}. 136 * 137 * @param operands the operands 138 * @return constraint 139 * {@code operands[0] + operands[1] + ... + operands[n] ≤ 1} 140 */ 141 public static Constraint lone(BoolVar... operands) { 142 Constraint<BoolVar, PropLone> constraint = new Constraint<>(operands, operands[0].getSolver()); 143 constraint.setPropagators(new PropLone(operands)); 144 return constraint; 145 } 146 147 /** 148 * A constraint enforcing 149 * {@code operands[0] + operands[1] + ... + operands[n] = 1}. 150 * 151 * @param operands the operands 152 * @return constraint 153 * {@code operands[0] + operands[1] + ... + operands[n] = 1} 154 */ 155 public static Constraint one(BoolVar... operands) { 156 Constraint<BoolVar, PropOne> constraint = new Constraint<>(operands, operands[0].getSolver()); 157 constraint.setPropagators(new PropOne(operands)); 158 return constraint; 159 } 160 161 /** 162 * A constraint enforcing 163 * {@code operands[0] ∨ operands[1] ∨ ... ∨ operands[n]}. 164 * 165 * @param operands the operands 166 * @return constraint {@code operands[0] ∨ operands[1] ∨ ... ∨ operands[n]} 167 */ 168 public static Constraint or(BoolVar... operands) { 169 Constraint<BoolVar, PropOr> constraint = new Constraint<>(operands, operands[0].getSolver()); 170 constraint.setPropagators(new PropOr(operands)); 171 return constraint; 172 } 173 174 /** 175 * A constraint enforcing 176 * {@code constraints[0] ∨ constraints[1] ∨ ... ∨ constraints[n]}. The 177 * reason this constraint is useful is because it does not require 178 * introducing new reified variables to the solver thus can be added 179 * dynamically while the solver is in progress. 180 * 181 * @param constraints the constraints 182 * @return constraint 183 * {@code constraints[0] ∨ constraints[1] ∨ ... ∨ constraints[n]} 184 */ 185 public static Constraint or(Constraint... constraints) { 186 return new OrConstraint(constraints); 187 } 188 189 /** 190 * A constraint enforcing 191 * {@code antecedent => consequent && !antecedent => alternative}. 192 * 193 * @param antecedent the antecedent 194 * @param consequent the consequent 195 * @param alternative the alternative 196 * @return constraint 197 * {@code antecedent => consequent && !antecedent => alternative} 198 */ 199 public static Constraint ifThenElse(BoolVar antecedent, BoolVar consequent, BoolVar alternative) { 200 Constraint<BoolVar, PropIfThenElse> constraint = 201 new Constraint<>(new BoolVar[]{antecedent, consequent, alternative}, antecedent.getSolver()); 202 constraint.setPropagators(new PropIfThenElse(antecedent, consequent, alternative)); 203 return constraint; 204 } 205 206 /** 207 * A constraint enforcing {@code reify <=> (variable = constant)}. 208 * 209 * @param reify the reified constraint 210 * @param variable the variable 211 * @param constant the constant 212 * @return constraint {@code reify <=> (variable = constant)} 213 */ 214 public static Constraint reifyEqual(BoolVar reify, IntVar variable, int constant) { 215 return new ReifyEqualXC(reify, true, variable, constant); 216 } 217 218 /** 219 * A constraint enforcing {@code reify <=> (v1 = v2)}. 220 * 221 * @param reify the reified constraint 222 * @param v1 the first variable 223 * @param v2 the second variable 224 * @return constraint {@code reify <=> (v1 = v2)} 225 */ 226 public static Constraint reifyEqual(BoolVar reify, IntVar v1, IntVar v2) { 227 return new ReifyEqualXY(reify, true, v1, v2); 228 } 229 230 /** 231 * A constraint enforcing {@code reify <=> (variable ≠ constant)}. 232 * 233 * @param reify the reified constraint 234 * @param variable the variable 235 * @param constant the constant 236 * @return constraint {@code reify <=> (variable ≠ constant)} 237 */ 238 public static Constraint reifyNotEqual(BoolVar reify, IntVar variable, int constant) { 239 return new ReifyEqualXC(reify, false, variable, constant); 240 } 241 242 /** 243 * A constraint enforcing {@code reify <=> (v1 ≠ v2)}. 244 * 245 * @param reify the reified constraint 246 * @param v1 the first variable 247 * @param v2 the second variable 248 * @return constraint {@code reify <=> (v1 ≠ v2)} 249 */ 250 public static Constraint reifyNotEqual(BoolVar reify, IntVar v1, IntVar v2) { 251 return new ReifyEqualXY(reify, false, v1, v2); 252 } 253 254 /** 255 * A constraint enforcing {@code set1 = set2}. Does not enforce that 256 * {@code set1Card = |set1Card|} nor {@code set2Card = |set2Card|} because 257 * of how the compilation works, it is already enforced elsewhere. 258 * 259 * @param set1 the left set 260 * @param set1Card the cardinality of {@code set1} 261 * @param set2 the right set 262 * @param set2Card the cardinality of {@code set2} 263 * @return constraint {@code set1 = set2} 264 */ 265 public static Constraint equal(SetVar set1, IntVar set1Card, SetVar set2, IntVar set2Card) { 266 return new SetEquality(set1, set1Card, true, set2, set2Card); 267 } 268 269 /** 270 * A constraint enforcing {@code set1 ≠ set2}. 271 * 272 * @param set1 the left set 273 * @param set1Card the cardinality of {@code set1} 274 * @param set2 the right set 275 * @param set2Card the cardinality of {@code set2} 276 * @return constraint {@code set1 ≠ set2} 277 */ 278 public static Constraint notEqual(SetVar set1, IntVar set1Card, SetVar set2, IntVar set2Card) { 279 return new SetEquality(set1, set1Card, false, set2, set2Card); 280 } 281 282 /** 283 * A constraint enforcing {@code set ≠ {constant}}. 284 * 285 * @param set the set 286 * @param constant the constant 287 * @return constraint {@code set1 ≠ set2} 288 */ 289 public static Constraint notEqual(SetVar set, int[] constant) { 290 Constraint<SetVar, PropSetNotEqualC> constraint = 291 new Constraint<>(new SetVar[]{set}, set.getSolver()); 292 constraint.setPropagators(new PropSetNotEqualC(set, constant)); 293 return constraint; 294 } 295 296 /** 297 * A constraint enforcing {@code element ∉ set}. 298 * 299 * @param element the element 300 * @param set the set 301 * @return constraint {@code element ∉ set}. 302 */ 303 public static Constraint notMember(IntVar element, SetVar set) { 304 Constraint<Variable, PropIntNotMemberSet> constraint = 305 new Constraint<>(new Variable[]{element, set}, element.getSolver()); 306 constraint.setPropagators(new PropIntNotMemberSet(element, set)); 307 return constraint; 308 } 309 310 /** 311 * A constraint enforcing {@code sub ⊆ sup}. Does not enforce that 312 * {@code subCard = |sub|} nor {@code supCard = |sup|} because of how the 313 * compilation works, it is already enforced elsewhere. 314 * 315 * @param sub the subset 316 * @param subCard the cardinality of {@code sub} 317 * @param sup the superset 318 * @param supCard the cardinality of {@code sup} 319 * @return constraint {@code sub ⊆ sup} 320 */ 321 public static Constraint subsetEq(SetVar sub, IntVar subCard, SetVar sup, IntVar supCard) { 322 @SuppressWarnings("unchecked") 323 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 324 new Constraint(new Variable[]{sub, subCard, sup, supCard}, sub.getSolver()); 325 326 @SuppressWarnings("unchecked") 327 Propagator<? extends Variable>[] propagators = new Propagator[]{ 328 new PropSubsetEq(sub, sup), 329 // Simple cardinality propagation. 330 lessThanEq(subCard, supCard) 331 }; 332 constraint.setPropagators(propagators); 333 334 return constraint; 335 } 336 337 /** 338 * A constraint enforcing {@code x ∈ sets[i] <=> ints[x] = i}. 339 * 340 * @param sets the sets 341 * @param ints the integers 342 * @return constraint {@code x ∈ sets[i] <=> ints[x] = i} 343 */ 344 public static Constraint intChannel(SetVar[] sets, IntVar[] ints) { 345 /* 346 * TODO: Take cardinalities of the sets into account? 347 * For example if card(sets[0]) <= 3, then if at least 3 of the integers 348 * are instantiated to 0, then remove 0 from the domains of the other integers. 349 * If card(sets[0]) >= 2 and only 2 ints contain 0 in their domain, then 350 * set those ints to 0. 351 */ 352 Variable[] variables = new Variable[sets.length + ints.length]; 353 System.arraycopy(sets, 0, variables, 0, sets.length); 354 System.arraycopy(ints, 0, variables, sets.length, ints.length); 355 356 Constraint<Variable, PropIntChannel> constraint = 357 new Constraint<>(variables, sets[0].getSolver()); 358 constraint.setPropagators(new PropIntChannel(sets, ints)); 359 360 return constraint; 361 } 362 363 /** 364 * A constraint enforcing 365 * {@code array(sets[0]) ++ array(sets[1]) ++ ... ++ array(sets[n]) ∈ N} 366 * where {@code array} is the sorted array representation of the set, 367 * {@code ++} is append, and {@code N = {[0,1,...,i] | i ≥ 0}}. 368 * 369 * @param sets the sets 370 * @param setCards the cardinalities of {@code sets} 371 * @return constraint 372 * {@code array(sets[0]) ++ array(sets[1]) ++ ... ++ array(sets[n]) ∈ N} 373 */ 374 public static Constraint sortedSets(SetVar[] sets, IntVar[] setCards) { 375 if (sets.length != setCards.length) { 376 throw new IllegalArgumentException(); 377 } 378 379 Variable[] variables = new Variable[sets.length + setCards.length]; 380 System.arraycopy(sets, 0, variables, 0, sets.length); 381 System.arraycopy(setCards, 0, variables, sets.length, setCards.length); 382 383 @SuppressWarnings("unchecked") 384 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 385 new Constraint(variables, sets[0].getSolver()); 386 387 @SuppressWarnings("unchecked") 388 Propagator<? extends Variable>[] propagators = new Propagator[]{ 389 new PropSortedSets(sets), 390 new PropSortedSetsCard(sets, setCards) 391 }; 392 constraint.setPropagators(propagators); 393 394 return constraint; 395 } 396 397 /** 398 * A constraint enforcing 399 * {@code strings[i] ≤ strings[j] <=> ints[i] ≤ ints[j]} and 400 * {@code strings[i] = strings[j] <=> ints[i] = ints[j]}. 401 * 402 * @param strings the strings 403 * @param ints the integers 404 * @return constraint {@code strings[i] ≤ strings[j] <=> ints[i] ≤ ints[j]} 405 * and {@code strings[i] = strings[j] <=> ints[i] = ints[j]} 406 */ 407 public static Constraint lexChainChannel(IntVar[][] strings, IntVar[] ints) { 408 if (strings.length != ints.length) { 409 throw new IllegalArgumentException(); 410 } 411 412 IntVar[] variables = new IntVar[strings.length * strings[0].length + ints.length]; 413 System.arraycopy(ints, 0, variables, 0, ints.length); 414 int i = ints.length; 415 for (IntVar[] string : strings) { 416 System.arraycopy(string, 0, variables, i, string.length); 417 i += string.length; 418 } 419 assert i == variables.length; 420 421 Constraint<IntVar, PropLexChainChannel> constraint = 422 new Constraint<>(variables, variables[0].getSolver()); 423 constraint.setPropagators(new PropLexChainChannel(strings, ints)); 424 425 return constraint; 426 } 427 428 /** 429 * A constraint enforcing that {@code bools[i] <=> i < n}. 430 * 431 * @param bools the booleans 432 * @param n the number of true booleans 433 * @return constraint {@code bools[i] <=> i < n} 434 */ 435 public static Constraint selectN(BoolVar[] bools, IntVar n) { 436 IntVar[] variables = new IntVar[bools.length + 1]; 437 System.arraycopy(bools, 0, variables, 0, bools.length); 438 variables[bools.length] = n; 439 440 Constraint<IntVar, PropSelectN> constraint = 441 new Constraint<>(variables, n.getSolver()); 442 constraint.setPropagators(new PropSelectN(bools, n)); 443 444 return constraint; 445 } 446 447 /** 448 * A constraint enforcing no cycles. {@code edges[i] = j} implies that there 449 * is a directed edge from node i to node j. {@code edges[i] = edges.length} 450 * implies that there are no direct edges from node i. 451 * 452 * @param edges the edges of the graph 453 * @return constraint enforcing no cycles 454 */ 455 public static Constraint acyclic(IntVar... edges) { 456 Constraint<IntVar, PropAcyclic> constraint = new Constraint<>(edges, edges[0].getSolver()); 457 constraint.setPropagators(new PropAcyclic(edges)); 458 return constraint; 459 } 460 461 /** 462 * A constraint enforcing no path from one node to another. 463 * {@code edges[i] = j} implies that there is a directed edge from node i to 464 * node j. {@code edges[i] ≥ edges.length} implies that there are no direct 465 * edges from node i. 466 * 467 * @param edges the edges of the graph 468 * @return constraint enforcing no path from one node to another 469 */ 470 public static Constraint unreachable(IntVar[] edges, int from, int to) { 471 Constraint<IntVar, PropUnreachable> constraint = new Constraint<>(edges, edges[0].getSolver()); 472 constraint.setPropagators(new PropUnreachable(edges, from, to)); 473 return constraint; 474 } 475 476 /** 477 * A constraint enforcing 478 * {@code result[i] = if i \u003c array(set).length then string[array(set)[i] - offset] else -1} 479 * where {@code array} is the sorted array representation of the set. Does 480 * not enforce that {@code setCard = |setCard|} because of how the 481 * compilation works, it is already enforced elsewhere. 482 * 483 * @param set the set 484 * @param setCard the cardinality of {@code set} 485 * @param offset the offset 486 * @param string the string 487 * @param result the result 488 * @return constraint 489 * {@code result[i] = if i \u003c array(set).length then string[array(set)[i] - offset] else -1} 490 */ 491 public static Constraint filterString(SetVar set, IntVar setCard, int offset, IntVar[] string, IntVar[] result) { 492 Constraint<Variable, PropFilterString> constraint = 493 new Constraint<>(PropFilterString.buildArray(set, setCard, string, result), set.getSolver()); 494 constraint.setPropagators(new PropFilterString(set, setCard, offset, string, result)); 495 return constraint; 496 } 497 498 /** 499 ******************* 500 * 501 * Integer. When using integer constraints, beware of the cases where the 502 * documentation states that certain cardinality constraints are to be 503 * enforced elsewhere. The only reason is for efficiency. 504 * 505 ******************* 506 */ 507 /** 508 * <p> 509 * A constraint enforcing {@code Σ set= sum}. Does not enforce that 510 * {@code sumCard = |sum|} because of how the compilation works, it is 511 * already enforced elsewhere. 512 * </p> 513 * <p> 514 * More * efficient than the standard operation in the Choco library when 515 * the cardinality is bounded to be relatively small. 516 * </p> 517 * <p> 518 * For example: 519 * <pre> 520 * Animal 2 521 * Age -> integer 522 * [Animal.Age = 1000] 523 * </pre> 524 * </p> 525 * <p> {@code Animal.Age} is a set with a very large envelope. However, due 526 * to static analysis of the model, it is easy to see that the cardinality 527 * must be 2. In general, the cardinality is bounded by the scope of Age, 528 * although often times the analysis will find a tighter bound. Once the 529 * first integer x is selected for the set, the second integer 1000 - x is 530 * already determined due to cardinality = 2. Since the Choco library's 531 * setSum constraint is not given the cardinality, it cannot make this 532 * deduction. 533 * </p> 534 * 535 * @param set the set of integers 536 * @param setCard the cardinality of {@code set} 537 * @param sum the sum of the set 538 * @return constraint {@code Σ set= sum} 539 */ 540 public static Constraint setSum(SetVar set, IntVar setCard, IntVar sum) { 541 Constraint<Variable, PropSetSum> constraint = 542 new Constraint<>(new Variable[]{set, setCard, sum}, set.getSolver()); 543 constraint.setPropagators(new PropSetSum(set, setCard, sum)); 544 return constraint; 545 } 546 547 /** 548 ******************* 549 * 550 * Set. When using set constraints, beware of the cases where the 551 * documentation states that certain cardinality constraints are to be 552 * enforced elsewhere. The only reason is for efficiency. 553 * 554 ******************* 555 */ 556 /** 557 * A constraint enforcing {@code {ivar} = svar}. 558 * 559 * @param ivar the integer 560 * @param svar the singleton set 561 * @return constraint {@code {ivar} = svar} 562 */ 563 public static Constraint singleton(IntVar ivar, SetVar svar) { 564 Constraint<Variable, PropSingleton> constraint = 565 new Constraint<>(new Variable[]{ivar, svar}, ivar.getSolver()); 566 constraint.setPropagators(new PropSingleton(ivar, svar)); 567 return constraint; 568 } 569 570 /** 571 * A constraint enforcing {@code {ivar} = svar} and {@code svarCard = 1}. 572 * Does not enforce that {@code svarCard = |svarCard|} because of how the 573 * compilation works, it is already enforced elsewhere. 574 * 575 * @param ivar the integer 576 * @param svar the singleton set 577 * @param svarCard the cardinality of {@code svar} 578 * @return constraint {@code {ivar} = svar} 579 */ 580 public static Constraint singleton(IntVar ivar, SetVar svar, IntVar svarCard) { 581 @SuppressWarnings("unchecked") 582 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 583 new Constraint(new Variable[]{ivar, svar, svarCard}, ivar.getSolver()); 584 585 @SuppressWarnings("unchecked") 586 Propagator<? extends Variable>[] propagators = new Propagator[]{ 587 new PropSingleton(ivar, svar), 588 new PropEqualXC(svarCard, 1) 589 }; 590 constraint.setPropagators(propagators); 591 592 return constraint; 593 } 594 595 /** 596 * A constraint enforcing {@code {ivar[0], ivar[1], ..., ivar[n]} = svar}. 597 * 598 * @param ivars the array 599 * @param svar the set 600 * @param svarCard the cardinality of {@code svar} 601 * @return constraint {@code {ivar[0], ivar[1], ..., ivar[n]} = svar} 602 */ 603 public static Constraint arrayToSet(IntVar[] ivars, SetVar svar, IntVar svarCard) { 604 return arrayToSet(ivars, svar, svarCard, null); 605 } 606 607 /** 608 * A constraint enforcing {@code {ivar[0], ivar[1], ..., ivar[n]} = svar} 609 * and {@code for all constant k, |{i | ivar[i] = k}| ≤ globalCardinality}. 610 * Does not enforce that {@code svarCard = |svar|} because of how the 611 * compilation works, it is already enforced elsewhere. 612 * 613 * @param ivars the array 614 * @param svar the set 615 * @param svarCard the cardinality of {@code svar} 616 * @param globalCardinality the global cardinality of the array elements 617 * @return constraint {@code {ivar[0], ivar[1], ..., ivar[n]} = svar} and 618 * {@code for all constant k |{i | ivar[i] = k}| ≤ globalCardinality} 619 */ 620 public static Constraint arrayToSet(IntVar[] ivars, SetVar svar, IntVar svarCard, Integer globalCardinality) { 621 Variable[] variables = new Variable[ivars.length + 2]; 622 variables[0] = svar; 623 variables[1] = svarCard; 624 System.arraycopy(ivars, 0, variables, 2, ivars.length); 625 626 @SuppressWarnings("unchecked") 627 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 628 new Constraint(variables, svar.getSolver()); 629 630 @SuppressWarnings("unchecked") 631 Propagator<? extends Variable>[] propagators = new Propagator[]{ 632 new PropArrayToSet(ivars, svar), 633 new PropArrayToSetCard(ivars, svarCard, globalCardinality) 634 }; 635 constraint.setPropagators(propagators); 636 637 return constraint; 638 } 639 640 @Deprecated // Every join relation in Clafer is injective. 641 public static Constraint joinRelation(SetVar take, SetVar[] children, SetVar to) { 642 SetVar[] variables = new SetVar[children.length + 2]; 643 variables[0] = take; 644 variables[1] = to; 645 System.arraycopy(children, 0, variables, 2, children.length); 646 647 Constraint<SetVar, PropJoinRelation> constraint = new Constraint<>(variables, take.getSolver()); 648 constraint.setPropagators(new PropJoinRelation(take, children, to)); 649 650 return constraint; 651 } 652 653 /** 654 * A constraint enforcing {@code take.children = to} where children is an 655 * injective relation. The representation of the relation is explained in 656 * {@link PropJoinRelation}. Does not enforce that the children relation is 657 * injective nor {@code takeCard = |take|} nor 658 * {@code childrenCards[i] = |children[i]|} nor {@code toCard = |to|} 659 * because of how the compilation works, it is already enforced elsewhere. 660 * 661 * @param take the left-hand side set 662 * @param takeCard the cardinality of {@code take} 663 * @param children the set representation of a injective binary relation 664 * @param childrenCards the cardinalities of {@code children} 665 * @param to the right-hand side set 666 * @param toCard the cardinality of {@code to} 667 * @return constraint {@code take.children = to} 668 * @see PropJoinFunction 669 */ 670 public static Constraint joinInjectiveRelation(SetVar take, IntVar takeCard, SetVar[] children, IntVar[] childrenCards, SetVar to, IntVar toCard) { 671 if (children.length != childrenCards.length) { 672 throw new IllegalArgumentException(); 673 } 674 675 Variable[] variables = new Variable[children.length * 2 + 4]; 676 variables[0] = take; 677 variables[1] = takeCard; 678 variables[2] = to; 679 variables[3] = toCard; 680 System.arraycopy(children, 0, variables, 4, children.length); 681 System.arraycopy(childrenCards, 0, variables, 4 + children.length, childrenCards.length); 682 683 @SuppressWarnings("unchecked") 684 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 685 new Constraint(variables, take.getSolver()); 686 687 @SuppressWarnings("unchecked") 688 Propagator<? extends Variable>[] propagators = new Propagator[]{ 689 new PropJoinRelation(take, children, to), 690 new PropJoinInjectiveRelationCard(take, takeCard, childrenCards, toCard) 691 }; 692 constraint.setPropagators(propagators); 693 694 return constraint; 695 } 696 697 /** 698 * A constraint enforcing {@code take.refs = to} where refs is a function. 699 * The representation of the function is explained in 700 * {@link PropJoinFunction}. Does not enforce that {@code takeCard = |take|} 701 * nor {@code toCard = |to|} because of how the compilation works, it is 702 * already enforced elsewhere. 703 * 704 * @param take the left-hand side set 705 * @param takeCard the cardinality of {@code take} 706 * @param refs the integer representation of a binary function 707 * @param to the right-hand side set 708 * @param toCard the cardinality of {@code to} 709 * @return constraint {@code take.refs = to} 710 * @see PropJoinFunction 711 */ 712 public static Constraint joinFunction(SetVar take, IntVar takeCard, IntVar[] refs, SetVar to, IntVar toCard) { 713 return joinFunction(take, takeCard, refs, to, toCard, null); 714 } 715 716 /** 717 * A constraint enforcing {@code take.refs = to} where refs is a function 718 * and {@code for all k in take, |{i | refs[i] = k}| ≤ globalCardinality}. 719 * The representation of the function is explained in 720 * {@link PropJoinFunction}. Does not enforce that {@code takeCard = |take|} 721 * nor {@code toCard = |to|} because of how the compilation works, it is 722 * already enforced elsewhere. 723 * 724 * @param take the left-hand side set 725 * @param takeCard the cardinality of {@code take} 726 * @param refs the integer representation of a binary function 727 * @param to the right-hand side set 728 * @param toCard the cardinality of {@code to} 729 * @param globalCardinality the global cardinality of the {@code refs} 730 * function for the domain of {@code take} 731 * @return constraint {@code take.refs = to} and 732 * {@code for all k in take, |{i | refs[i] = k}| ≤ globalCardinality} 733 * @see PropJoinFunction 734 */ 735 public static Constraint joinFunction(SetVar take, IntVar takeCard, IntVar[] refs, SetVar to, IntVar toCard, Integer globalCardinality) { 736 Variable[] variables = new Variable[refs.length + 4]; 737 variables[0] = take; 738 variables[1] = takeCard; 739 variables[2] = to; 740 variables[3] = toCard; 741 // Assumes take card is already constrained for maximum efficiency. 742 System.arraycopy(refs, 0, variables, 4, refs.length); 743 744 @SuppressWarnings("unchecked") 745 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 746 new Constraint(variables, take.getSolver()); 747 748 @SuppressWarnings("unchecked") 749 Propagator<? extends Variable>[] propagators = new Propagator[]{ 750 new PropJoinFunction(take, refs, to), 751 new PropJoinFunctionCard(take, takeCard, refs, toCard, globalCardinality) 752 }; 753 constraint.setPropagators(propagators); 754 755 return constraint; 756 } 757 758 /** 759 * A constraint enforcing {@code minuend - subtrahend = difference}. Does 760 * not enforce that {@code minuendCard = |minuend|} nor 761 * {@code subtrahendCard = |subtrahend|} nor 762 * {@code differenceCard = |difference|} because of how the compilation 763 * works, it is already enforced elsewhere. 764 * 765 * @param minuend the minuend 766 * @param minuendCard the cardinality of {@code minuend} 767 * @param subtrahend the subtrahend 768 * @param subtrahendCard the cardinality of {@code subtrahend} 769 * @param difference the difference 770 * @param differenceCard the cardinality of {@code difference} 771 * @return constraint {@code minuend - subtrahend = difference} 772 */ 773 public static Constraint difference( 774 SetVar minuend, IntVar minuendCard, 775 SetVar subtrahend, IntVar subtrahendCard, 776 SetVar difference, IntVar differenceCard) { 777 Variable[] variables = new Variable[]{ 778 minuend, minuendCard, subtrahend, subtrahendCard, difference, differenceCard 779 }; 780 781 @SuppressWarnings("unchecked") 782 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 783 new Constraint(variables, difference.getSolver()); 784 785 @SuppressWarnings("unchecked") 786 Propagator<? extends Variable>[] propagators = new Propagator[]{ 787 new PropSetDifference(minuend, subtrahend, difference), 788 // Simple cardinality propagation. 789 greaterThanEq(minuendCard, differenceCard) 790 }; 791 constraint.setPropagators(propagators); 792 793 return constraint; 794 } 795 796 /** 797 * A constraint enforcing 798 * {@code operands[0] ∩ operands[1] ∩ ... ∩ operands[n] = intersection}. 799 * Does not enforce that {@code operandCards[i] = |operands[i]|} nor 800 * {@code intersectionCard = |intersection|} because of how the compilation 801 * works, it is already enforced elsewhere. 802 * 803 * @param operands the operands 804 * @param operandCards the cardinalities of {@code operands} 805 * @param intersection the intersection 806 * @param intersectionCard the cardinality of {@code intersection} 807 * @return constraint 808 * {@code operands[0] ∩ operands[1] ∩ ... ∩ operands[n] = intersection} 809 */ 810 public static Constraint intersection( 811 SetVar[] operands, IntVar[] operandCards, 812 SetVar intersection, IntVar intersectionCard) { 813 if (operands.length != operandCards.length) { 814 throw new IllegalArgumentException(); 815 } 816 817 Variable[] variables = new Variable[operands.length + operandCards.length + 2]; 818 System.arraycopy(operands, 0, variables, 0, operands.length); 819 System.arraycopy(operandCards, 0, variables, operands.length, operandCards.length); 820 variables[operands.length + operandCards.length] = intersection; 821 variables[operands.length + operandCards.length + 1] = intersectionCard; 822 823 @SuppressWarnings("unchecked") 824 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 825 new Constraint(variables, intersection.getSolver()); 826 827 @SuppressWarnings("unchecked") 828 Propagator<? extends Variable>[] propagators = new Propagator[operandCards.length + 2]; 829 // See SCF.intersection(operands, intersection); 830 // TODO: Needs to add the same propagator twice because the implementation 831 // is not guaranteed to be idempotent. If it ever becomes idempotent, then 832 // follow their implementation. 833 propagators[0] = new PropIntersection(operands, intersection); 834 propagators[1] = new PropIntersection(operands, intersection); 835 for (int i = 0; i < operandCards.length; i++) { 836 // Simple cardinality propagation. 837 propagators[i + 2] = greaterThanEq(operandCards[i], intersectionCard); 838 } 839 constraint.setPropagators(propagators); 840 841 return constraint; 842 } 843 844 /** 845 * A constraint enforcing 846 * {@code operands[0] ∪ operands[1] ∪ ... ∪ operands[n] = union}. Does not 847 * enforce that {@code operandCards[i] = |operands[i]|} nor 848 * {@code unionCard = |union|} because of how the compilation works, it is 849 * already enforced elsewhere. 850 * 851 * @param operands the operands 852 * @param operandCards the cardinalities of {@code operands} 853 * @param union the union 854 * @param unionCard the cardinality of {@code union} 855 * @param disjoint the sets are disjoint 856 * @return constraint 857 * {@code operands[0] ∪ operands[1] ∪ ... ∪ operands[n] = union} 858 */ 859 public static Constraint union( 860 SetVar[] operands, IntVar[] operandCards, 861 SetVar union, IntVar unionCard, 862 boolean disjoint) { 863 if (operands.length != operandCards.length) { 864 throw new IllegalArgumentException(); 865 } 866 867 Variable[] variables = new Variable[operands.length + operandCards.length + 2]; 868 System.arraycopy(operands, 0, variables, 0, operands.length); 869 System.arraycopy(operandCards, 0, variables, operands.length, operandCards.length); 870 variables[operands.length + operandCards.length] = union; 871 variables[operands.length + operandCards.length + 1] = unionCard; 872 873 @SuppressWarnings("unchecked") 874 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 875 new Constraint(variables, union.getSolver()); 876 877 @SuppressWarnings("unchecked") 878 Propagator<? extends Variable>[] propagators = new Propagator[]{ 879 new PropSetUnion(operands, union), 880 disjoint 881 ? sumEq(operandCards, unionCard) 882 : new PropSetUnionCard(operandCards, unionCard) 883 }; 884 constraint.setPropagators(propagators); 885 886 return constraint; 887 } 888 889 /** 890 * A constraint enforcing 891 * {@code {i + from | i ∈ member} = set ∩ {from, from + 1, ..., to - 1}}. 892 * Does not enforce that {@code setCard = |set|} nor 893 * {@code maskedCard = |masked|} because of how the compilation works, it is 894 * already enforced elsewhere. 895 * 896 * @param set the set 897 * @param setCard the cardinality of {@code set} 898 * @param masked the masked set 899 * @param maskedCard the cardinality of {@code masked} 900 * @param from the inclusive start of the mask 901 * @param to the exclusive end of the mask 902 * @return constraint 903 * {@code {i + from | i ∈ member} = set ∩ {from, from + 1, ..., to - 1}} 904 */ 905 public static Constraint mask( 906 SetVar set, IntVar setCard, 907 SetVar masked, IntVar maskedCard, 908 int from, int to) { 909 @SuppressWarnings("unchecked") 910 Constraint<? extends Variable, Propagator<? extends Variable>> constraint = 911 new Constraint(new Variable[]{set, setCard, masked, maskedCard}, set.getSolver()); 912 913 @SuppressWarnings("unchecked") 914 Propagator<? extends Variable>[] propagators = new Propagator[]{ 915 new PropMask(set, masked, from, to), 916 // Simple cardinality propagation. 917 greaterThanEq(setCard, maskedCard) 918 }; 919 constraint.setPropagators(propagators); 920 921 return constraint; 922 } 923}