1 /* 2 * IfThenElse.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.UsesQueueVariable; 34 import org.jacop.core.Domain; 35 import org.jacop.core.Store; 36 import org.jacop.core.Var; 37 import org.jacop.util.QueueForward; 38 39 import java.util.concurrent.atomic.AtomicInteger; 40 41 /** 42 * Constraint if constraint1 then constraint2 else constraint3 43 * * 44 * 45 * @author Krzysztof Kuchcinski and Radoslaw Szymanek 46 * @version 4.8 47 */ 48 49 public class IfThenElse extends PrimitiveConstraint implements UsesQueueVariable { 50 51 static AtomicInteger idNumber = new AtomicInteger(0); 52 53 /** 54 * It specifies constraint condC in the IfThenElse constraint. 55 */ 56 public PrimitiveConstraint condC; 57 58 /** 59 * It specifies constraint condC in the IfThenElse constraint. 60 */ 61 public PrimitiveConstraint thenC; 62 63 /** 64 * It specifies constraint elseC in the IfThenElse constraint. 65 */ 66 public PrimitiveConstraint elseC; 67 68 // imposed variable to manifest that constraint has been imposed (top-level) 69 // constraint 70 boolean imposed = false; 71 72 Store store; 73 74 final public QueueForward<PrimitiveConstraint> queueForward; 75 76 /** 77 * It creates ifthenelse constraint. 78 * 79 * @param condC the condition of the constraint. 80 * @param thenC the condition which must be true if the constraint condition is true. 81 * @param elseC the condition which must be true if the constraint condition is not true. 82 */ 83 // Constructors IfThenElse(PrimitiveConstraint condC, PrimitiveConstraint thenC, PrimitiveConstraint elseC)84 public IfThenElse(PrimitiveConstraint condC, PrimitiveConstraint thenC, PrimitiveConstraint elseC) { 85 86 PrimitiveConstraint[] scope = new PrimitiveConstraint[] {condC, thenC, elseC}; 87 checkInputForNullness(new String[] {"condC", "thenC", "elseC"}, scope); 88 89 numberId = idNumber.incrementAndGet(); 90 91 this.condC = condC; 92 this.thenC = thenC; 93 this.elseC = elseC; 94 95 setScope(scope); 96 setConstraintScope(scope); 97 queueForward = new QueueForward<PrimitiveConstraint>(new PrimitiveConstraint[] {condC, thenC, elseC}, arguments()); 98 this.queueIndex = Integer.max(Integer.max(condC.queueIndex, thenC.queueIndex), elseC.queueIndex); 99 } 100 consistency(Store store)101 @Override public void consistency(Store store) { 102 103 if (condC.satisfied()) 104 thenC.consistency(store); 105 else if (condC.notSatisfied()) 106 elseC.consistency(store); 107 108 if (imposed) { 109 110 if (thenC.notSatisfied()) { 111 condC.notConsistency(store); 112 elseC.consistency(store); 113 } 114 115 if (elseC.notSatisfied()) { 116 condC.consistency(store); 117 thenC.consistency(store); 118 } 119 } 120 121 } 122 notSatisfied()123 @Override public boolean notSatisfied() { 124 return (condC.satisfied() && thenC.notSatisfied()) || (condC.notSatisfied() && elseC.notSatisfied()); 125 } 126 notConsistency(Store store)127 @Override public void notConsistency(Store store) { 128 129 if (condC.notSatisfied()) 130 elseC.notConsistency(store); 131 132 if (condC.satisfied()) 133 thenC.notConsistency(store); 134 135 } 136 getNestedPruningEvent(Var var, boolean mode)137 @Override public int getNestedPruningEvent(Var var, boolean mode) { 138 139 // If consistency function mode 140 if (mode) { 141 if (consistencyPruningEvents != null) { 142 Integer possibleEvent = consistencyPruningEvents.get(var); 143 if (possibleEvent != null) 144 return possibleEvent; 145 } 146 } 147 // If notConsistency function mode 148 else { 149 if (notConsistencyPruningEvents != null) { 150 Integer possibleEvent = notConsistencyPruningEvents.get(var); 151 if (possibleEvent != null) 152 return possibleEvent; 153 } 154 } 155 156 int eventAcross = -1; 157 158 if (condC.arguments().contains(var)) { 159 int event = condC.getNestedPruningEvent(var, true); 160 if (event > eventAcross) 161 eventAcross = event; 162 } 163 164 if (condC.arguments().contains(var)) { 165 int event = condC.getNestedPruningEvent(var, false); 166 if (event > eventAcross) 167 eventAcross = event; 168 } 169 170 if (thenC.arguments().contains(var)) { 171 int event = thenC.getNestedPruningEvent(var, true); 172 if (event > eventAcross) 173 eventAcross = event; 174 } 175 176 if (thenC.arguments().contains(var)) { 177 int event = thenC.getNestedPruningEvent(var, false); 178 if (event > eventAcross) 179 eventAcross = event; 180 } 181 182 if (elseC.arguments().contains(var)) { 183 int event = elseC.getNestedPruningEvent(var, true); 184 if (event > eventAcross) 185 eventAcross = event; 186 } 187 188 if (elseC.arguments().contains(var)) { 189 int event = elseC.getNestedPruningEvent(var, false); 190 if (event > eventAcross) 191 eventAcross = event; 192 } 193 194 if (eventAcross == -1) 195 return Domain.NONE; 196 else 197 return eventAcross; 198 199 } 200 getDefaultNotConsistencyPruningEvent()201 @Override protected int getDefaultNotConsistencyPruningEvent() { 202 throw new IllegalStateException("Not implemented as more precise method exists."); 203 } 204 getConsistencyPruningEvent(Var var)205 @Override public int getConsistencyPruningEvent(Var var) { 206 207 // If consistency function mode 208 if (consistencyPruningEvents != null) { 209 Integer possibleEvent = consistencyPruningEvents.get(var); 210 if (possibleEvent != null) 211 return possibleEvent; 212 } 213 214 int eventAcross = -1; 215 216 if (condC.arguments().contains(var)) { 217 int event = condC.getNestedPruningEvent(var, true); 218 if (event > eventAcross) 219 eventAcross = event; 220 } 221 222 if (condC.arguments().contains(var)) { 223 int event = condC.getNestedPruningEvent(var, false); 224 if (event > eventAcross) 225 eventAcross = event; 226 } 227 228 if (thenC.arguments().contains(var)) { 229 int event = thenC.getNestedPruningEvent(var, true); 230 if (event > eventAcross) 231 eventAcross = event; 232 } 233 234 if (thenC.arguments().contains(var)) { 235 int event = thenC.getNestedPruningEvent(var, false); 236 if (event > eventAcross) 237 eventAcross = event; 238 } 239 240 if (elseC.arguments().contains(var)) { 241 int event = elseC.getNestedPruningEvent(var, true); 242 if (event > eventAcross) 243 eventAcross = event; 244 } 245 246 if (elseC.arguments().contains(var)) { 247 int event = elseC.getNestedPruningEvent(var, false); 248 if (event > eventAcross) 249 eventAcross = event; 250 } 251 252 if (eventAcross == -1) 253 return Domain.NONE; 254 else 255 return eventAcross; 256 257 258 } 259 getDefaultConsistencyPruningEvent()260 @Override public int getDefaultConsistencyPruningEvent() { 261 throw new IllegalStateException("Not implemented as more precise method exists."); 262 } 263 getNotConsistencyPruningEvent(Var var)264 @Override public int getNotConsistencyPruningEvent(Var var) { 265 266 // If notConsistency function mode 267 if (notConsistencyPruningEvents != null) { 268 Integer possibleEvent = notConsistencyPruningEvents.get(var); 269 if (possibleEvent != null) 270 return possibleEvent; 271 } 272 273 int eventAcross = -1; 274 275 if (condC.arguments().contains(var)) { 276 int event = condC.getNestedPruningEvent(var, true); 277 if (event > eventAcross) 278 eventAcross = event; 279 } 280 281 if (condC.arguments().contains(var)) { 282 int event = condC.getNestedPruningEvent(var, false); 283 if (event > eventAcross) 284 eventAcross = event; 285 } 286 287 if (thenC.arguments().contains(var)) { 288 int event = thenC.getNestedPruningEvent(var, true); 289 if (event > eventAcross) 290 eventAcross = event; 291 } 292 293 if (thenC.arguments().contains(var)) { 294 int event = thenC.getNestedPruningEvent(var, false); 295 if (event > eventAcross) 296 eventAcross = event; 297 } 298 299 if (elseC.arguments().contains(var)) { 300 int event = elseC.getNestedPruningEvent(var, true); 301 if (event > eventAcross) 302 eventAcross = event; 303 } 304 305 if (elseC.arguments().contains(var)) { 306 int event = elseC.getNestedPruningEvent(var, false); 307 if (event > eventAcross) 308 eventAcross = event; 309 } 310 311 if (eventAcross == -1) 312 return Domain.NONE; 313 else 314 return eventAcross; 315 316 } 317 impose(Store store)318 @Override public void impose(Store store) { 319 320 super.impose(store); 321 322 this.store = store; 323 imposed = true; 324 } 325 include(Store store)326 @Override public void include(Store store) { 327 this.store = store; 328 } 329 satisfied()330 @Override public boolean satisfied() { 331 332 if (imposed) { 333 334 if (condC.satisfied()) { 335 this.removeConstraint(); 336 store.impose(thenC); 337 return false; 338 } 339 340 if (condC.notSatisfied()) { 341 this.removeConstraint(); 342 store.impose(elseC); 343 return false; 344 } 345 346 } 347 348 return (condC.satisfied() && thenC.satisfied()) || (condC.notSatisfied() && elseC.satisfied()); 349 350 } 351 toString()352 @Override public String toString() { 353 354 StringBuffer result = new StringBuffer(id()); 355 result.append(" : IfThenElse(").append(condC).append(", "); 356 result.append(thenC).append(", ").append(elseC).append(" )"); 357 358 return result.toString(); 359 360 } 361 queueVariable(int level, Var variable)362 @Override public void queueVariable(int level, Var variable) { 363 364 queueForward.queueForward(level, variable); 365 366 } 367 368 } 369