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