1 /* 2 * BoolClause.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.core.IntDomain; 34 import org.jacop.core.IntVar; 35 import org.jacop.core.Store; 36 import org.jacop.core.TimeStamp; 37 38 import java.util.Arrays; 39 import java.util.List; 40 import java.util.concurrent.atomic.AtomicInteger; 41 import java.util.stream.Stream; 42 43 /** 44 * I defines a boolean clause for 0/1 variables x_i and y_i. 45 * The clause is fulfilled if at least one varibale x_i = 1 or at least one varibale y_i = 0, 46 * that is it defines (x_1 \/ x_2 \/ ... x_n) \/ (not y_1 \/ not y_2 \/ ... not y_n) 47 * It restricts the domain of all x as well as result to be between 0 and 1. 48 * 49 * @author Krzysztof Kuchcinski and Radoslaw Szymanek 50 * @version 4.8 51 */ 52 53 public class BoolClause extends PrimitiveConstraint { 54 55 final static AtomicInteger idNumber = new AtomicInteger(0); 56 57 /** 58 * It specifies lists of variables for the constraint. 59 */ 60 final public IntVar[] x; 61 final public IntVar[] y; 62 63 /** 64 * It specifies length of lists x and y respectively. 65 */ 66 private final int lx, ly; 67 68 /** 69 * Defines first position of the variable that is not ground to 0 (positionX) or 0 (positionY). 70 */ 71 private TimeStamp<Integer> positionX; 72 private TimeStamp<Integer> positionY; 73 74 /** 75 * It constructs BoolClause. 76 * 77 * @param x list of positive arguments x's. 78 * @param y list of negative arguments y's. 79 */ BoolClause(IntVar[] x, IntVar[] y)80 public BoolClause(IntVar[] x, IntVar[] y) { 81 82 checkInputForNullness(new String[] {"x", "y"}, x, y); 83 84 this.numberId = idNumber.incrementAndGet(); 85 this.lx = x.length; 86 this.ly = y.length; 87 88 this.x = Arrays.copyOf(x, x.length); 89 this.y = Arrays.copyOf(y, y.length); 90 91 assert (checkInvariants() == null) : checkInvariants(); 92 93 if (lx + ly > 4) 94 queueIndex = 1; 95 else 96 queueIndex = 0; 97 98 setScope(Stream.concat(Arrays.stream(x), Arrays.stream(y))); 99 } 100 101 /** 102 * It constructs BoolClause. 103 * 104 * @param x list of positive arguments x's. 105 * @param y list of negative arguments y's. 106 */ BoolClause(List<IntVar> x, List<IntVar> y)107 public BoolClause(List<IntVar> x, List<IntVar> y) { 108 this(x.toArray(new IntVar[x.size()]), y.toArray(new IntVar[y.size()])); 109 } 110 111 /** 112 * It checks invariants required by the constraint. Namely that 113 * boolean variables have boolean domain. 114 * 115 * @return the string describing the violation of the invariant, null otherwise. 116 */ checkInvariants()117 public String checkInvariants() { 118 119 for (IntVar var : x) 120 if (var.min() < 0 || var.max() > 1) 121 return "Variable " + var + " does not have boolean domain"; 122 123 for (IntVar var : y) 124 if (var.min() < 0 || var.max() > 1) 125 return "Variable " + var + " does not have boolean domain"; 126 127 return null; 128 } 129 getDefaultNestedConsistencyPruningEvent()130 @Override protected int getDefaultNestedConsistencyPruningEvent() { 131 return IntDomain.ANY; 132 } 133 getDefaultNestedNotConsistencyPruningEvent()134 @Override protected int getDefaultNestedNotConsistencyPruningEvent() { 135 return IntDomain.GROUND; 136 } 137 getDefaultConsistencyPruningEvent()138 @Override public int getDefaultConsistencyPruningEvent() { 139 return IntDomain.BOUND; 140 } 141 getDefaultNotConsistencyPruningEvent()142 @Override protected int getDefaultNotConsistencyPruningEvent() { 143 return IntDomain.GROUND; 144 } 145 include(Store store)146 @Override public void include(Store store) { 147 positionX = new TimeStamp<>(store, 0); 148 positionY = new TimeStamp<>(store, 0); 149 } 150 151 /** 152 * computes consistency for x_0 \/ ... \/ x_n \/ not y_0 \/ ... \/ not y_n 153 */ consistency(Store store)154 @Override public void consistency(Store store) { 155 156 int startX = positionX.value(); 157 int startY = positionY.value(); 158 159 for (int i = startX; i < lx; i++) { 160 if (x[i].max() == 0) { 161 swap(x, startX, i); 162 startX++; 163 } else if (x[i].min() == 1) { 164 removeConstraint(); 165 return; 166 } 167 } 168 positionX.update(startX); 169 170 for (int i = startY; i < ly; i++) { 171 if (y[i].min() == 1) { 172 swap(y, startY, i); 173 startY++; 174 } else if (y[i].max() == 0) { 175 removeConstraint(); 176 return; 177 } 178 } 179 positionY.update(startY); 180 181 // all x = 0 and all y = 1 => FAIL 182 if (startX == lx && startY == ly) 183 throw Store.failException; 184 // last x must be 1 185 else if (startX == lx - 1 && startY == ly) 186 x[lx - 1].domain.in(store.level, x[lx - 1], 1, 1); 187 // last y must be 0 188 else if (startX == lx && startY == ly - 1) 189 y[ly - 1].domain.in(store.level, y[ly - 1], 0, 0); 190 191 if (lx - startX + ly + startY < 5) 192 queueIndex = 0; 193 } 194 swap(IntVar[] p, int i, int j)195 private void swap(IntVar[] p, int i, int j) { 196 if (i != j) { 197 IntVar tmp = p[i]; 198 p[i] = p[j]; 199 p[j] = tmp; 200 } 201 } 202 203 204 /** 205 * computes consistency for not (x_0 \/ ... \/ x_n \/ not y_0 \/ ... \/ not y_n) 206 * implies 207 * not x_0 /\ ... /\ not x_n /\ y_0 /\ ... /\ y_n 208 * taht is all x_i = 0 /\ all y_i = 1 209 */ notConsistency(Store store)210 @Override public void notConsistency(Store store) { 211 212 for (int i = 0; i < lx; i++) 213 x[i].domain.in(store.level, x[i], 0, 0); 214 for (int i = 0; i < ly; i++) 215 y[i].domain.in(store.level, y[i], 1, 1); 216 217 removeConstraint(); 218 219 } 220 satisfied()221 @Override public boolean satisfied() { 222 223 int startX = positionX.value(); 224 int startY = positionY.value(); 225 226 for (int i = startX; i < lx; i++) 227 if (x[i].min() == 1) 228 return true; 229 else if (x[i].max() == 0) { 230 swap(x, startX, i); 231 startX++; 232 } 233 positionX.update(startX); 234 235 for (int i = startY; i < ly; i++) 236 if (y[i].max() == 0) 237 return true; 238 else if (y[i].min() == 1) { 239 swap(y, startY, i); 240 startY++; 241 } 242 positionY.update(startY); 243 244 return false; 245 246 } 247 notSatisfied()248 @Override public boolean notSatisfied() { 249 250 int startX = positionX.value(); 251 int startY = positionY.value(); 252 253 for (int i = startX; i < lx; i++) 254 if (x[i].max() == 0) { 255 swap(x, startX, i); 256 startX++; 257 } else 258 return false; 259 positionX.update(startX); 260 261 for (int i = startY; i < ly; i++) 262 if (y[i].min() == 1) { 263 swap(y, startY, i); 264 startY++; 265 } else 266 return false; 267 positionY.update(startY); 268 269 return startX == lx && startY == ly; 270 } 271 toString()272 @Override public String toString() { 273 274 StringBuilder resultString = new StringBuilder(id()); 275 276 resultString.append(" : BoolClause([ "); 277 for (int i = 0; i < lx; i++) { 278 resultString.append(x[i]); 279 if (i < lx - 1) 280 resultString.append(", "); 281 } 282 resultString.append("], ["); 283 284 for (int i = 0; i < ly; i++) { 285 resultString.append(y[i]); 286 if (i < ly - 1) 287 resultString.append(", "); 288 } 289 resultString.append("])"); 290 return resultString.toString(); 291 } 292 293 } 294