1 /* 2 * Conditional.java 3 * This file is part of JaCoP. 4 * <p> 5 * JaCoP is a Java Constraint Programming solver. 6 * <p> 7 * Copyright (C) 2000-2008 Krzysztof Kuchcinski and Radoslaw Szymanek 8 * <p> 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU Affero General Public License as published by 11 * the Free Software Foundation, either version 3 of the License, or 12 * (at your option) any later version. 13 * <p> 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Affero General Public License for more details. 18 * <p> 19 * Notwithstanding any other provision of this License, the copyright 20 * owners of this work supplement the terms of this License with terms 21 * prohibiting misrepresentation of the origin of this work and requiring 22 * that modified versions of this work be marked in reasonable ways as 23 * different from the original version. This supplement of the license 24 * terms is in accordance with Section 7 of GNU Affero General Public 25 * License version 3. 26 * <p> 27 * You should have received a copy of the GNU Affero General Public License 28 * along with this program. If not, see <http://www.gnu.org/licenses/>. 29 */ 30 31 package org.jacop.constraints; 32 33 import org.jacop.api.SatisfiedPresent; 34 import org.jacop.core.IntDomain; 35 import org.jacop.core.IntVar; 36 import org.jacop.core.Var; 37 import org.jacop.core.Store; 38 39 import java.util.Arrays; 40 import java.util.List; 41 import java.util.ArrayList; 42 import java.util.Set; 43 import java.util.concurrent.atomic.AtomicInteger; 44 import java.util.stream.Stream; 45 46 /** 47 * Conditional constraint implements conditional constraint 48 * satisfiability. It enforces consistency of constraint c[k] where 49 * b[k] = 1 (true) and all b[i] for i {@literal <} k are 0 (false). 50 * 51 * @author Krzysztof Kuchcinski 52 * @version 4.8 53 */ 54 55 public class Conditional extends Constraint implements SatisfiedPresent { 56 57 final static AtomicInteger idNumber = new AtomicInteger(0); 58 59 /** 60 * The list of 0/1 (Boolean) variables for assignment decision. 61 */ 62 final public IntVar[] b; 63 64 /** 65 * The list of constraints that are to be selected. 66 */ 67 final public PrimitiveConstraint[] c; 68 69 /** 70 * It constructs a Conditional constraint. 71 * 72 * @param b 0/1 variables for selection of constraint 73 * @param c constraints for selection. 74 */ Conditional(IntVar[] b, PrimitiveConstraint[] c)75 public Conditional(IntVar[] b, PrimitiveConstraint[] c) { 76 77 checkInputForNullness(new String[] {"b", "c"}, new Object[][] {b, c}); 78 assert (b.length == c.length) : "The length of the two lists in Conditional constraints must be equal"; 79 for (IntVar be : b) 80 assert (be.min() >= 0 && be.max() <= 1) : "The elements of condition list must be 0/1 variables"; 81 if (b[b.length-1].min() != 1) 82 throw new IllegalArgumentException("Conditional constraint: the last element of conditions list must be 1 (true)"); 83 84 this.queueIndex = 0; 85 this.numberId = idNumber.incrementAndGet(); 86 87 this.b = Arrays.copyOf(b, b.length); 88 this.c = Arrays.copyOf(c, c.length); 89 90 // collect variables of all constraints 91 List<Var> vs = new ArrayList<>(); 92 for (int i = 0; i < c.length; i++) { 93 Set<Var> cvs = c[i].arguments(); 94 for (Var v : cvs) 95 vs.add(v); 96 } 97 98 setScope(Stream.concat(Arrays.stream(b), vs.stream())); 99 100 } 101 102 /** 103 * It constructs a Conditional constraint. 104 * 105 * @param b 0/1 variables for selection of constraint 106 * @param c constraints for selection. 107 */ Conditional(List<? extends IntVar> b, List<? extends PrimitiveConstraint> c)108 public Conditional(List<? extends IntVar> b, List<? extends PrimitiveConstraint> c) { 109 this(b.toArray(new IntVar[b.size()]), c.toArray(new PrimitiveConstraint[c.size()])); 110 } 111 getDefaultConsistencyPruningEvent()112 @Override public int getDefaultConsistencyPruningEvent() { 113 return IntDomain.ANY; 114 } 115 consistency(final Store store)116 @Override public void consistency(final Store store) { 117 118 boolean prune = true; 119 120 while (prune) { 121 int i = 0; 122 LOOP: while (i < b.length) { 123 if (b[i].max() == 0) { 124 i++; 125 continue; 126 } else 127 break LOOP; 128 } 129 prune = false; 130 131 if (b[i].min() == 1) { 132 c[i].consistency(store); 133 134 if (c[i].satisfied()) 135 removeConstraint(); 136 } else if (c[i].notSatisfied()) { 137 b[i].domain.in(store.level, b[i], 0, 0); 138 prune = true; 139 } else if (b.length == 2 && c[i].satisfied()) { 140 b[i].domain.in(store.level, b[i], 1, 1); 141 prune = true; 142 } 143 } 144 } 145 146 /** 147 * Informs wheter the constraint is satisfied 148 * @return true if constraint is satisfied 149 */ satisfied()150 @Override public boolean satisfied() { 151 152 int i = 0; 153 LOOP: while (i < b.length) { 154 if (b[i].max() == 0) { 155 i++; 156 continue; 157 } else 158 break LOOP; 159 } 160 if (b[i].min() == 1 && c[i].satisfied()) 161 return true; 162 163 return false; 164 } 165 toString()166 @Override public String toString() { 167 168 StringBuilder result = new StringBuilder(id()); 169 170 result.append(" : Conditional(").append("["); 171 172 for (int i = 0; i < b.length; i++) { 173 result.append(b[i]); 174 if (i < b.length - 1) 175 result.append(", "); 176 } 177 result.append("], "); 178 179 for (int i = 0; i < c.length; i++) { 180 result.append(c[i]); 181 if (i < c.length - 1) 182 result.append(", "); 183 } 184 185 result.append("]").append(" )"); 186 187 return result.toString(); 188 189 } 190 191 } 192