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