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