32 | * This method does nothing if the propagator is already enqueued. 33 | *
34 | * 35 | * @param propagator the propagator to be scheduled for propagation. 36 | */ 37 | public void enqueue(Propagator propagator) { 38 | if (!propagator.enqueued) { 39 | queue.addLast(propagator); 40 | propagator.enqueued = true; 41 | } 42 | } 43 | 44 | /** 45 | * Propagates the pending propagators. 46 | * 47 | *48 | * Propagate all the propagators contained in the propagation queue. 49 | * Propagation is likely to enqueue additional propagators while it is 50 | * running. The propagation stops either when the queue is empty, or if a 51 | * propagator failed (meaning that the problem is infeasible). 52 | *
53 | * 54 | *55 | * The method returns true if the propagation succeeded or false if a 56 | * propagator failed. The queue is empty at the end of the propagation and all 57 | * propagators contained in the queue have their enqueued boolean set to 58 | * false. 59 | *
60 | * 61 | * @return true if propagation succeeded, false otherwise. 62 | */ 63 | public boolean propagate() { 64 | boolean feasible = true; 65 | while (!queue.isEmpty()) { 66 | Propagator propagator = queue.removeFirst(); 67 | // Dequeue the propagator only if it is not idempotent. This allows the 68 | // propagator to enqueue itself back in the propagation queue if it 69 | // changed the domain of at least one of its variable. 70 | propagator.enqueued = propagator.idempotent; 71 | // Propagate only if the problem is still feasible. 72 | feasible = feasible && propagator.propagate(); 73 | // Dequeue the propagator no matter what. 74 | propagator.enqueued = false; 75 | } 76 | return feasible; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/kiwi/propagation/Propagator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiwi.propagation; 17 | 18 | /** 19 | * Superclass to be instantiated by any propagator. 20 | */ 21 | public abstract class Propagator { 22 | 23 | /** 24 | * Indicates if the propagator is contained in the propagation queue. 25 | */ 26 | protected boolean enqueued; 27 | 28 | /** 29 | * Indicates if the propagator might need to be called again just after 30 | * propagation. 31 | */ 32 | protected boolean idempotent; 33 | 34 | /** 35 | * Initializes the propagator and performs its initial propagation 36 | * 37 | * @return false if the propagation failed. 38 | */ 39 | public abstract boolean setup(); 40 | 41 | /** 42 | * Propagates the last domain changes 43 | * 44 | * @return false if the propagation failed. 45 | */ 46 | public abstract boolean propagate(); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/kiwi/search/BinaryVarVal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiwi.search; 17 | 18 | import java.util.function.IntUnaryOperator; 19 | 20 | import kiwi.trail.TrailedInt; 21 | import kiwi.util.Array; 22 | import kiwi.util.Stack; 23 | import kiwi.variable.IntVar; 24 | 25 | public class BinaryVarVal implements Heuristic { 26 | 27 | private final IntVar[] variables; 28 | 29 | private final int[] unassigned; 30 | private final TrailedInt nUnassignedT; 31 | private final IntUnaryOperator varCost; 32 | private final IntUnaryOperator valSelector; 33 | 34 | public BinaryVarVal(IntVar[] variables, IntUnaryOperator varCost, IntUnaryOperator valSelector) { 35 | this.variables = variables; 36 | this.unassigned = Array.makeInt(variables.length, i -> i); 37 | this.nUnassignedT = new TrailedInt(variables[0].trail(), variables.length); 38 | this.varCost = varCost; 39 | this.valSelector = valSelector; 40 | } 41 | 42 | public boolean pushNextDecisions(Stack22 | * A {@code Decision} is taken by the search heuristic to drive the tree search 23 | * on specific directions. A {@code Decision} typically impacts directly the 24 | * domain of an {@code IntVar} by removing values from its domain. 25 | *
26 | */ 27 | public interface Decision { 28 | /** 29 | * Applies the decision. 30 | * 31 | * @return {@code true} if and only if the decision did not failed directly. 32 | */ 33 | public boolean apply(); 34 | } -------------------------------------------------------------------------------- /src/main/java/kiwi/search/Heuristic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiwi.search; 17 | 18 | import kiwi.util.Stack; 19 | 20 | /** 21 | * Superclass to be instantiated by any search heuristic. 22 | */ 23 | public interface Heuristic { 24 | 25 | /** 26 | * Pushes the next decisions to be taken on top of the decisions stack. 27 | * First check that the current state of the problem is a leaf. If not, it 28 | * adds the next decisions to applyon top of decisions stack. The last pushed 29 | * decision will be the first to be applied. 30 | * 31 | * Note that the behavior of the solver is not determined if the content of 32 | * the decisions stack is changed. 33 | * 34 | * @param decisions 35 | * The stack of decisions to be taken. The new decisions must be 36 | * pushed on top of the stack. The method should not remove any 37 | * decision contained in the stack. 38 | * 39 | * @return true if the decision stack is unchanged; false otherwise. 40 | */ 41 | public boolean pushNextDecisions(Stack22 | * A {@code Change} represents any kind of undoable operation that affects the 23 | * state of the solver, its variables, or its propagators. A {@code Change} is 24 | * typically trailed and undone when a backtrack occurs. 25 | *
26 | */ 27 | public interface Change { 28 | /** Undoes the change */ 29 | public void undo(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/kiwi/trail/README.md: -------------------------------------------------------------------------------- 1 | # Trail and state restoration 2 | 3 | This package contains the system responsible for storing and restoring the state of the solver. 4 | 5 | Trailing is the prominent approach used to implement such restoration mechanism. It basically consists to maintain the sequence of changes -- the trail -- that occurred on each object. The previous state of an object can thus be restored by undoing the changes in anti-chronological order. 6 | 7 | ## Changes 8 | 9 | Each time a state changing operation is performed, the necessary information to undo this operation is stored on the trail. 10 | In Kiwi, we chose to directly store the functions responsible of undoing state changes as first class objects, i.e., as closures. 11 | Each stateful object thus relies on its own restoration mechanism which is handled by the closure itself. 12 | 13 | ## The Trail 14 | 15 | Our trailing system is implemented with two stacks: 16 | 17 | - The first is a stack of Change objects that represents the trail. It is sorted chronologically such that the most recent change is on top of the stack (the root node being the empty stack). 18 | - The second stack maps each node of the current branch to its corresponding prefix in the trail. Thanks to the incrementality of the trail, only the position of the last change that lead to a node needs to be stored to characterize the whole sequence of changes that lead to this node. 19 | -------------------------------------------------------------------------------- /src/main/java/kiwi/trail/Trail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiwi.trail; 17 | 18 | import kiwi.util.Stack; 19 | import kiwi.util.StackInt; 20 | 21 | /** 22 | * {@code Trail} contains the chronological sequences of changes to undo. 23 | */ 24 | public class Trail { 25 | 26 | private long timestamp = 0L; 27 | 28 | private final Stack28 | * An {@code IntVar} basically represents the set of integer values that can be 29 | * assigned to the variable. A variable is assigned when its domain becomes a 30 | * singleton, i.e, it contains a single value. The variable cannot be empty. 31 | * Operation that directly impact the domain of the variable must return false 32 | * if the operation would have lead to an empty domain. 33 | *
34 | * 35 | *36 | * An {@code IntVar} must be able to restore its state when a backtrack occurs. 37 | *
38 | */ 39 | public abstract class IntVar { 40 | 41 | /** 42 | * A constant holding the minimum value an {@code IntVar} can be assigned to. 43 | */ 44 | public static final int MIN_VALUE = -1000000000; 45 | 46 | /** 47 | * A constant holding the maximum value an {@code IntVar} can be assigned to. 48 | */ 49 | public static final int MAX_VALUE = 1000000000; 50 | 51 | /** 52 | * Returns the {@code PropagationQueue} associated to this variable. 53 | * 54 | * @return the {@code PropagationQueue} of this {@code IntVar}. 55 | */ 56 | public abstract PropagationQueue propagQueue(); 57 | 58 | /** 59 | * Returns the {@code Trail} associated to this {@code IntVar}. 60 | * 61 | * @return the {@code Trail} of this {@code IntVar}. 62 | */ 63 | public abstract Trail trail(); 64 | 65 | /** 66 | * Returns the minimum value contained in the domain of this variable. 67 | * 68 | * @return the minimum {@code int} contained in this {@code IntVar}. 69 | */ 70 | public abstract int min(); 71 | 72 | /** 73 | * Returns the maximum value contained in the domain of this variable. 74 | * 75 | * @return the maximum {@code int} contained in this {@code IntVar}. 76 | */ 77 | public abstract int max(); 78 | 79 | /** 80 | * Returns the number of values contained in the domain of this variable. 81 | * 82 | * @return the number of values contained in this {@code IntVar}. 83 | */ 84 | public abstract int size(); 85 | 86 | /** 87 | * Returns {@code true} if this {@code IntVar} is assigned. An {@code IntVar} 88 | * is assigned if its domain contains a single value. 89 | * 90 | * @return {@code true} if the variable is assigned; {@code false} otherwise. 91 | */ 92 | public abstract boolean isAssigned(); 93 | 94 | /** 95 | * Returns {@code true} if and only if this {@code IntVar} contains the 96 | * specified value. 97 | * 98 | * @param value the value to be check for containment in this 99 | * {@code IntVar}. 100 | * @return {@code true} if the variable contains the value; {@code false} 101 | * otherwise. 102 | */ 103 | public abstract boolean contains(int value); 104 | 105 | /** 106 | * Tries to assign this variable to the specified value. 107 | * 108 | *109 | * If this {@code IntVar} is not assigned and contains {@code value} then all 110 | * the propagators registered on this {@code IntVar} are scheduled for 111 | * propagation as specified in {@link #watchAssign watchAssign}, 112 | * {@link #watchBounds watchBounds}, and {@link #watchChange watchChange}. 113 | * This method does nothing if this {@code IntVar} is already assigned to 114 | * {@code value}. 115 | *
116 | * 117 | * @param value the value to which this {@code IntVar} must be assigned 118 | * @return {@code true} if and only if the {@code value} is contained 119 | * in the domain of this {@code IntVar} 120 | * @see PropagationQueue#enqueue enqueue 121 | * @see #watchAssign watchAssign 122 | * @see #watchBounds watchBounds 123 | * @see #watchChange watchChange 124 | */ 125 | public abstract boolean assign(int value); 126 | 127 | /** 128 | * Tries to remove the specified value from the domain of this variable. 129 | * 130 | *131 | * If this {@code IntVar} is not assigned and contains {@code value} then all 132 | * the propagators registered on this {@code IntVar} are scheduled for 133 | * propagation as specified in {@link #watchAssign watchAssign}, 134 | * {@link #watchBounds watchBounds}, and {@link #watchChange watchChange}. 135 | * This method does nothing if {@code value} is not contained in the domain 136 | * of this {@code IntVar}. 137 | *
138 | * 139 | * @param value the value to remove from the domain of this {@code IntVar} 140 | * @return {@code true} if and only if this {@code IntVar} is not 141 | * assigned to {@code value} 142 | * @see PropagationQueue#enqueue enqueue 143 | * @see #watchAssign watchAssign 144 | * @see #watchBounds watchBounds 145 | * @see #watchChange watchChange 146 | */ 147 | public abstract boolean remove(int value); 148 | 149 | /** 150 | * Tries to remove all the values that are smaller than the specified value. 151 | * 152 | *153 | * If {@code value} is greater than {@link #min} and smaller or equal to 154 | * {@link #max} then all the propagators registered on this {@code IntVar} 155 | * are scheduled for propagation as specified in 156 | * {@link #watchAssign watchAssign}, {@link #watchBounds watchBounds}, and 157 | * {@link #watchChange watchChange}. This method does nothing if 158 | * {@code value} is smaller or equal to {@link #min}. 159 | *
160 | * 161 | * @param value the value such that all the smaller values contained in the 162 | * domain of this {@code IntVar} must be removed 163 | * @return {@code true} if and only if {@code value} is lower or equal 164 | * to {@link #max} 165 | * @see PropagationQueue#enqueue enqueue 166 | * @see #watchAssign watchAssign 167 | * @see #watchBounds watchBounds 168 | * @see #watchChange watchChange 169 | */ 170 | public abstract boolean updateMin(int value); 171 | 172 | /** 173 | * Tries to remove all the values that are greater than the specified value. 174 | * 175 | *176 | * If {@code value} is lower than {@link #max} and greater or equal to 177 | * {@link #min} then all the propagators registered on this {@code IntVar} 178 | * are scheduled for propagation as specified in 179 | * {@link #watchAssign watchAssign}, {@link #watchBounds watchBounds}, and 180 | * {@link #watchChange watchChange}. This method does nothing if 181 | * {@code value} is greater or equal to {@link #max}. 182 | *
183 | * 184 | * @param value the value such that all the greater values contained in the 185 | * domain of this {@code IntVar} must be removed 186 | * @return {@code true} if and only if {@code value} is greater or 187 | * equal to {@link #min} 188 | * @see PropagationQueue#enqueue enqueue 189 | * @see #watchAssign watchAssign 190 | * @see #watchBounds watchBounds 191 | * @see #watchChange watchChange 192 | */ 193 | public abstract boolean updateMax(int value); 194 | 195 | /** 196 | * Registers the propagator on domain assignations. 197 | * 198 | *199 | * The propagator will be scheduled for propagation using the 200 | * {@link PropagationQueue#enqueue enqueue} method each time this 201 | * {@code IntVar} is assigned to a value. 202 | *
203 | * 204 | * @param propagator propagator to be registered on this {@code IntVar} 205 | * @see #assign assign 206 | * @see #remove remove 207 | * @see #updateMin updateMin 208 | * @see #updateMax updateMax 209 | */ 210 | public abstract void watchAssign(Propagator propagator); 211 | 212 | /** 213 | * Registers the propagator on bound changes. 214 | * 215 | *216 | * The propagator will be scheduled for propagation using the 217 | * {@link PropagationQueue#enqueue enqueue} method each time the value of 218 | * {@link #min} or {@link #max} is removed from the domain of this 219 | * {@code IntVar}. 220 | *
221 | * 222 | * @param propagator propagator to be registered on this {@code IntVar} 223 | * @see #assign assign 224 | * @see #remove remove 225 | * @see #updateMin updateMin 226 | * @see #updateMax updateMax 227 | */ 228 | public abstract void watchBounds(Propagator propagator); 229 | 230 | /** 231 | * Registers the propagator on the domain changes. 232 | * 233 | *234 | * The propagator will be scheduled for propagation using the 235 | * {@link PropagationQueue#enqueue enqueue} method each time a value is 236 | * removed from the domain of this {@code IntVar}. 237 | *
238 | * 239 | * @param propagator propagator to be registered on this {@code IntVar} 240 | * @see #assign assign 241 | * @see #remove remove 242 | * @see #updateMin updateMin 243 | * @see #updateMax updateMax 244 | */ 245 | public abstract void watchChange(Propagator propagator); 246 | 247 | 248 | /** 249 | * Copies the values contained in the domain of this {@code IntVar} in the 250 | * specified array. 251 | * 252 | *253 | * This function gives no guarantee on the order of the copied values. 254 | *
255 | * 256 | * @return the size of the domain 257 | */ 258 | public abstract int copyDomain(int[] array); 259 | 260 | @Override 261 | public String toString() { 262 | int[] domain = new int[size()]; 263 | copyDomain(domain); 264 | Arrays.sort(domain); 265 | StringBuffer bf = new StringBuffer("{"); 266 | for (int i = 0; i < domain.length - 1; i++) { 267 | bf.append(domain[i] + ", "); 268 | } 269 | bf.append(domain[domain.length - 1] + "}"); 270 | return bf.toString(); 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /src/main/java/kiwi/variable/IntVarImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016, Google Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package kiwi.variable; 17 | 18 | import kiwi.propagation.PropagationQueue; 19 | import kiwi.propagation.Propagator; 20 | import kiwi.trail.Trail; 21 | import kiwi.trail.TrailedInt; 22 | import kiwi.util.Array; 23 | import kiwi.util.Stack; 24 | 25 | /** 26 | * A sparse set based implementation of IntVar 27 | * 28 | *29 | * This class implements {@code IntVar} with a sparse set representation. 30 | * 31 | * Reference: 32 | * - 33 | * - 34 | *
35 | * 36 | * 37 | * 38 | */ 39 | public class IntVarImpl extends IntVar { 40 | 41 | private final PropagationQueue pQueue; 42 | private final Trail trail; 43 | 44 | private final int initMin; 45 | private final int initMax; 46 | 47 | private final TrailedInt minT; 48 | private final TrailedInt maxT; 49 | private final TrailedInt sizeT; 50 | 51 | private final int[] values; 52 | private final int[] positions; 53 | 54 | private final Stack