1 /*
2  * XmulYeqC.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.*;
34 
35 import java.util.concurrent.atomic.AtomicInteger;
36 
37 /**
38  * Constraint X * Y #= C
39  * <p>
40  * Boundary consistency is used.
41  *
42  * @author Radoslaw Szymanek and Krzysztof Kuchcinski
43  * @version 4.8
44  */
45 
46 public class XmulYeqC extends PrimitiveConstraint {
47 
48     final static AtomicInteger idNumber = new AtomicInteger(0);
49 
50     /**
51      * It specifies variable x in constraint x * y = c.
52      */
53     final public IntVar x;
54 
55     /**
56      * It specifies variable y in constraint x * y = c.
57      */
58     final public IntVar y;
59 
60     /**
61      * It specifies constant c in constraint x * y = c.
62      */
63     final public int c;
64 
65     /**
66      * It specifies if the constraint is actually, x^2 = c.
67      */
68     private final boolean xSquare;
69 
70     /**
71      * It constructs constraint X * Y = C.
72      *
73      * @param x variable x.
74      * @param y variable y.
75      * @param c constant c.
76      */
XmulYeqC(IntVar x, IntVar y, int c)77     public XmulYeqC(IntVar x, IntVar y, int c) {
78 
79         checkInputForNullness(new String[] {"x", "y"}, new Object[] {x, y});
80 
81         numberId = idNumber.incrementAndGet();
82 
83         xSquare = x == y;
84 
85         this.x = x;
86         this.y = y;
87         this.c = c;
88 
89         setScope(x, y);
90 
91     }
92 
consistency(final Store store)93     @Override public void consistency(final Store store) {
94 
95         if (xSquare)  // x^2 = c
96             do {
97 
98                 store.propagationHasOccurred = false;
99 
100                 if (c < 0)
101                     throw Store.failException;
102 
103                 double sqrtOfC = Math.sqrt((double) c);
104 
105                 if (Math.ceil(sqrtOfC) != Math.floor(sqrtOfC))
106                     throw Store.failException;
107 
108                 int value = (int) sqrtOfC;
109 
110                 IntDomain dom = new IntervalDomain(-value, -value);
111                 dom.unionAdapt(value, value);
112 
113                 x.domain.in(store.level, x, dom);
114 
115             } while (store.propagationHasOccurred);
116         else    // X*Y=C
117             do {
118 
119                 store.propagationHasOccurred = false;
120 
121                 // Bounds for X
122                 Interval xBounds = IntDomain.divIntBounds(c, c, y.min(), y.max());
123 
124                 x.domain.in(store.level, x, xBounds.min(), xBounds.max());
125 
126                 // Bounds for Y
127                 Interval yBounds = IntDomain.divIntBounds(c, c, x.min(), x.max());
128 
129                 y.domain.in(store.level, y, yBounds.min(), yBounds.max());
130 
131                 // check bounds, if C is covered.
132                 Interval cBounds = IntDomain.mulBounds(x.min(), x.max(), y.min(), y.max());
133 
134                 if (c < cBounds.min() || c > cBounds.max())
135                     throw Store.failException;
136 
137             } while (store.propagationHasOccurred);
138 
139     }
140 
getDefaultNestedNotConsistencyPruningEvent()141     @Override protected int getDefaultNestedNotConsistencyPruningEvent() {
142         return IntDomain.BOUND;
143     }
144 
getDefaultNestedConsistencyPruningEvent()145     @Override protected int getDefaultNestedConsistencyPruningEvent() {
146         return IntDomain.GROUND;
147     }
148 
getDefaultNotConsistencyPruningEvent()149     @Override protected int getDefaultNotConsistencyPruningEvent() {
150         return IntDomain.GROUND;
151     }
152 
getDefaultConsistencyPruningEvent()153     @Override public int getDefaultConsistencyPruningEvent() {
154         return IntDomain.ANY;
155     }
156 
notConsistency(final Store store)157     @Override public void notConsistency(final Store store) {
158 
159         do {
160 
161             store.propagationHasOccurred = false;
162 
163             if (x.singleton()) {
164                 if (c % x.value() == 0)
165                     y.domain.inComplement(store.level, y, c / x.value());
166             } else if (y.singleton()) {
167                 if (c % y.value() == 0)
168                     x.domain.inComplement(store.level, x, c / y.value());
169             }
170 
171         } while (store.propagationHasOccurred);
172 
173     }
174 
notSatisfied()175     @Override public boolean notSatisfied() {
176         IntDomain Xdom = x.dom(), Ydom = y.dom();
177         return (Xdom.max() * Ydom.max() < c || Xdom.min() * Ydom.min() > c);
178     }
179 
satisfied()180     @Override public boolean satisfied() {
181         return (grounded() && (x.min() * y.min() == c));
182     }
183 
toString()184     @Override public String toString() {
185 
186         return id() + " : XmulYeqC(" + x + ", " + y + ", " + c + " )";
187     }
188 
189 }
190