Proceedings of the Twenty-Second International Joint Conference on Artificial Intelligence Exploiting Short Supports for Generalised Arc Consistency for Arbitrary Constraints Peter Nightingale, Ian P. Gent, Chris Jefferson, Ian Miguel School of Computer Science, University of St Andrews, St Andrews, Fife KY16 9SX, UK {pn,ipg,caj,ianm}@cs.st-andrews.ac.uk Abstract typically more expensive than specialised propagators but are an important tool when no specialised propagator is available. A support for a domain value of a variable is an explanation as to why that value cannot yet be removed from consideration in the search for a solution. It is usually given in terms of a set of literals: variable-value pairs corresponding to possible assignments to the other variables in the constraint. One of the efficiencies typically found in specialised propagators is the (typically implicit) use of short supports: by examining a subset of the variables, they can infer support for all other variables and values and save substantial work. For example, consider the element([x0 , x1 , x2 ], y, z) constraint, with x0 , x1 , x2 , y ∈ {0 . . . 2}, z ∈ {0 . . . 3}. The constraint is satisfied iff xy = z (i.e. the element in position y of vector X equals z). Consider the set of literals S1 = {x0 → 1, y → 0, z → 1}. This set clearly satisfies the definition of the constraint xy = z, but it does not contain a literal for each variable. Any extension of S with valid literals for variables x1 and x2 is a support. We call S a short support. As a second example, the watched literal propagation algorithm in SAT exploits short supports containing one variable, requiring only two such supports for a constraint of any length. To date, general-purpose propagation algorithms rely upon supports involving all variables. In this paper, we demonstrate how to employ short supports in a new general-purpose propagation algorithm called S HORT GAC. As we will demonstrate, the use of short supports significantly improves the performance of S HORT GAC versus existing general-purpose propagation algorithms. In some cases, S HORT GAC even approaches the performance of special-purpose propagators. Special-purpose constraint propagation algorithms (such as those for the element constraint) frequently make implicit use of short supports — by examining a subset of the variables, they can infer support for all other variables and values and save substantial work. However, to date general purpose propagation algorithms (such as GAC-Schema) rely upon supports involving all variables. We demonstrate how to employ short supports in a new general purpose propagation algorithm called S HORT GAC. This works when provided with either an explicit list of allowed short tuples, or a function to calculate the next supporting short tuple. Empirical analyses demonstrate the efficiency of S HORT GAC compared to other general-purpose propagation algorithms. In some cases S HORT GAC even exhibits similar performance to special-purpose propagators. 1 Introduction Constraint solving of a given problem proceeds in two phases. First, the problem is modelled as a set of decision variables and a set of constraints on those variables that a solution must satisfy. A decision variable represents a choice that must be made in order to solve the problem, and its associated domain of potential values corresponds to the options for that choice. In the second phase, a constraint solver searches for a solution or solutions automatically. Typically, constraint solvers employ a systematic backtracking search, interleaving the choice of an instantiation of a decision variable with the propagation of the constraints to determine the consequences of the choice made. In order to facilitate this process, each constraint supported by the solver has an associated propagation algorithm. Propagation algorithms can broadly be divided into two types. The first are specialised to reason very efficiently about constraint patterns that occur very frequently in models. Examples include the global cardinality constraint [Régin, 1996] and the element constraint [Gent et al., 2006b]. It is not feasible to support every possible constraint expression with a specialised propagator in this way, in which case general-purpose constraint propagators, such as GAC-Schema [Bessière and Régin, 1997] or GAC2001 [Bessière et al., 2005], are used. These are 2 Supports, Short Supports and GAC A literal x → v is valid if v is in the current domain of x. The scope of a constraint c is the subset of variables that it constrains. A valid tuple for constraint c is a set of literals that contains a valid literal for each variable in the scope of c and satisfies c. With respect to a constraint c, a support for a literal l is a valid tuple for c that contains l. Each short support is a set of literals that contains a valid literal for each of some subset of variables in the scope of c, and such that every superset of this containing one valid literal for each variable in c is a support. For example, even the empty set is a possible short support, if every remaining tuple of valid literals satisfies c (in which case c is ‘entailed’.) 623 S1 = {x0 → 1, y → 0, z → 1}. The counters are as follows. (X indicates that a literal is not valid.) The property commonly established by constraint propagation algorithms is generalised arc consistency (GAC) [Mackworth, 1977]. A constraint c is GAC if and only if there exists a support for every valid literal of every variable in the scope of c. GAC is established by identifying all literals x → v for which no support exists and removing v from the domain of x. A GAC propagation algorithm is usually situated in a systematic search. Hence, it must operate in three contexts: initialisation (at the root node), where support is established from scratch; following the deletion of one or more domain values (as a result of a branching decision and/or the propagation of other constraints), where support must be re-established selectively; and upon backtracking, where data structures must be restored to the correct state for this point in search. Our primary focus will be on the second context, operation following value deletion, although we will discuss the other two briefly. A GAC propagation algorithm would typically be called for each deleted domain value in turn. Once the algorithm has been called for each such domain value, the constraint will be GAC. However, the propagation algorithm proposed here need not be called for every deleted domain value to establish GAC. In this paper we say that propagators attach and remove triggers on literals. When a domain value v for variable x is deleted, the propagator is called if and only if it has a trigger attached to the literal x → v. 3 supportsPerLit: Value 0 1 2 3 supportsPerVar: numSupports: x0 0 1 0 X 1 Variable x1 x2 0 0 0 0 0 0 X X 0 0 1 y 1 0 0 X 1 z 0 1 0 0 1 All values of x1 and x2 have support, since their supportsPerVar counters are both less than numSupports. Therefore the S HORT GAC algorithm can ignore x1 and x2 and only look for new supports of x0 , y and z. Consider finding a new support for literals in z. S HORT GAC can ignore the literals with at least one support – in this case z → 1. The algorithm looks for literals z → a where supportsPerLit[z, a] = 0. Here, z → 0 is such a literal, so S HORT GAC seeks a new support for it. A possible new support is S2 = {x1 → 0, y → 1, z → 0}, with which the counters are updated: supportsPerLit: Value 0 1 2 3 supportsPerVar: numSupports: S HORT GAC: An Overview This section summarises the key ideas of the S HORT GAC propagation algorithm, along with an illustrative example. S HORT GAC maintains a set of short supports sufficient to support all valid literals of the variables in the scope of the constraint it is propagating. We refer to these as the active supports. The major contribution of the algorithm is the efficient storage and update of the set of active supports. This efficiency rests on exploiting the observation that, using short supports, support can be established for a literal in two ways. First, as usual, a short support that contains a literal supports that literal. Second, a literal x → v is supported by a short support that contains no literal of variable x. Hence, the only short supports that do not support x → v are those which contain a literal x → w for some other value w = v. The following counters are central to the operation of the S HORT GAC algorithm: x0 0 1 0 X 1 Variable x1 x2 1 0 0 0 0 0 X X 1 0 2 y 1 1 0 X 2 z 1 1 0 0 2 Now variable x0 is also fully supported, since However, we supportsPerVar[x0 ] < numSupports. retain the values of supportsPerLit for x0 in case numSupports falls back to 1 subsequently. There remain three literals for which support has not been established: y → 2, z → 2 and z → 3. For the first two S HORT GAC finds supports such as S3 = {x0 → 2, y → 0, z → 2}, S4 = {x2 → 0, y → 2, z → 0}. No support exists for z → 3, so this literal is invalid and 3 will be deleted, giving: supportsPerLit: Value 0 1 2 3 supportsPerVar: numSupports: numSupports is the total number of active supports. supportsPerVar[x] is an array indicating the number of supports containing each variable x. supportsPerLit[x, v] is a 2-dimensional array indicating the number of supports containing each literal x → v. x0 0 1 1 X 2 Variable x1 x2 1 1 0 0 0 0 X X 1 1 4 y 2 1 1 X 4 z 2 1 1 X 4 All valid literals are now supported. Nothing further need be done until a change in state, such as the removal of a value by propagation, or a change in state following backtracking. 4 If the number of supports containing some variable x is less than the total number of supports then there exists a support s that does not contain x. Therefore, as noted, s supports all literals of x. The algorithm spends no time processing variables all of whose literals are known to be supported in this way. Only for variables involved in all supporting tuples do we have to seek support for literals with no current supports. To illustrate, we consider the element example. Suppose in the current state S HORT GAC is storing just one support: S HORT GAC: Details The key tasks are: counter update; iteration over variables where supportsPerVar equals numSupports; and iteration over the unsupported values of a variable. The following data structures allow us to do each of these tasks efficiently. A short support is represented by a struct. It may be contained in multiple doubly-linked lists simultaneously (one for each literal x → v in the support). Hence, it has multiple previous and next pointers. The support struct contains: 624 Algorithm 1 Add Support: addSupport(sup) Require: sup: a support struct 1: for all (xi → a) in sup.literals do 2: Add sup to supportListPerLit[xi , a] 3: supportsPerVar[xi ]← supportsPerVar[xi ]+1 4: supportsPerLit[xi ,a]← supportsPerLit[xi ,a]+1 5: sPV←supportsPerVar[xi ] 6: cellend ←supportNumPtrs[sPV]−1 7: swap(xi , varsPerSupport[cellend]) 8: supportNumPtrs[sPV]←supportNumPtrs[sPV]−1 9: if supportsPerLit[xi ,a]=1 then 10: attachTrigger(xi ,a) 11: numSupports←numSupports+1 prev[x] An array of previous pointers, indexed by variable. next[x] An array of next pointers, indexed by variable. literals An array of literals The doubly-linked lists are accessed via supportListPerLit[x, v], an array of pointers to supports. If an active support S contains a literal x → v, then S is contained in the doublylinked list supportListPerLit[x, v]. Hence, it is possible to iterate through all supports containing any particular literal. The algorithm iterates over all variables x where supportsPerVar[x] equals numSupports. The following data structure represents a partition of the variables by the number of supports. It allows constant time size checking and linear-time iteration of each cell in the partition, and allows any variable to be moved into an adjacent cell (ie if the number of supports increases or decreases by 1) in constant time. It is inspired by the indexed dependency array in [Schulte and Tack, 2010]. On line 2, sup is removed from the list (in constant time). Lines 6-8 are altered to move xi into the lower adjacent cell in varsPerSupport. Line 6 finds the start of the cell that xi is in (supportNumPtrs[sPV+1]), line 7 remains the same and line 8 increments the lower boundary (supportNumPtrs[sPV+1]) so that xi is now in the adjacent cell. Lines 9-10 call removeTrigger if supportsPerLit[xi ,a]=0. Between lines 8 and 9, a new section is added: if supportsPerLit[xi ,a]=0, then value a is added to zeroVals[xi ] if not already present. All changes to data structures (except where noted above) are stored on a stack; addSupport and deleteSupport are used to revert changes upon backtracking. varsPerSupport is an array containing a permutation of the variables. Variables are ordered by their number of supports (supportsPerVar[x]) in ascending order. varsPerSupInv is the inverse mapping of varsPerSupport. supportNumPtrs is an array of integers such that supportNumPtrs[i] is the smallest index in varsPerTherefore Support with i or more supports. varsPerSupport[supportNumPtrs[i]..supportNumPtrs[i + 1]-1] contains exactly the set of variables with i supports. Procedure swap(xi , xj ) (used later) locates and swaps the two variables in varsPerSupport, also updating varsPerSupInv. For a variable x with supportsPerVar[x] = numSupports, S HORT GAC iterates over the values with zero supports. To avoid iterating over all values, we use a set data structure: 4.2 The S HORT GAC propagator (Algorithm 2) is only invoked when a literal contained in one or more active supports is pruned. It first calls deleteSupport for all active supports containing the pruned literal. Then it iterates through all variables xj where supportsPerVar[xj ]=numSupports (lines 3-4). xj may have unsupported values. S HORT GAC iterates through zeroVals[xj ], discarding values with support (lines 6-7), and seeking a new support for those without (lines 10-16). A new support is sought by calling findNewSupport(xj , a). This returns a support for the literal if one exists. If there is no support, the literal is pruned. If there exists a support (sup) it is added on line 14. sup must support xj → a, but it does not have to contain xj → a. a is removed from zeroVals[xj ] only if sup contains xj → a. At this point, numSupports and supportNumPtrs have changed, so the loop (lines 3-17) is restarted (line 17) using a goto statement. The aim is to process all variables where supportsPerVar[xj ]=numSupports; adding a new support changes this set of variables, therefore the loop is restarted. Complexity analysis of the algorithm is left for future work, and we do not claim optimality. In particular the algorithm can process variables where each value is supported. To initialise the propagation process, lines 3-17 of Algorithm 2 are invoked. zeroVals[x] is a stack containing the zero values for x in no particular order. inZeroVals[x, v] is a Boolean indicating whether value v is on the stack. When supportsPerLit[x,v] is reduced to 0, if inZeroVals[x,v] is false then v is pushed onto zeroVals[x]. As an optimisation, values are not eagerly removed from the set; they are only removed when the set is iterated. Also, the set is not backtracked. During iteration, a non-zero value is removed by swapping it to the top of the stack, and popping. 4.1 The Propagation Algorithm Adding and Deleting Supports When a support is added or deleted, all the data structures described above are updated. This is done by the addSupport and deleteSupport procedures. AddSupport is given in Algorithm 1. For each literal in the support sup, sup is added to the appropriate supportListPerLit, and the two counters supportsPerVar and supportsPerLit are incremented. xi must also be moved to the next cell in varsPerSupport. Line 6 finds the end of the cell that xi is in. Line 7 swaps xi to the end of its cell, and line 8 moves a cell boundary such that xi is now in the higher cell. Lines 9-10 add a trigger to xi → a if sup is the only active support to contain that literal (otherwise xi → a will already have a trigger). The procedure deleteSupport is similar with the following changes. On lines 3, 4 and 11, counters are decremented. 4.3 Instantiation of findNewSupport Similarly to GAC-Schema [Bessière and Régin, 1997], S HORT GAC must be instantiated with a findNewSupport function. The function takes a valid literal, and returns a support if one exists, otherwise returns null. A findNewSupport function 625 Algorithm 2 S HORT GAC-Propagate: propagate(var, val) Require: var, val (where val has been pruned from var) 1: while supportListPerLit[var, val] = null do 2: deleteSupport(supportListPerLit[var, val]) 3: for all i ∈ {supportNumPtrs[numSupports]. . . supportNumPtrs[numSupports+1]-1} do 4: xj ← varsPerSupport[i] 5: for all a ∈ zeroVals[xj ] do 6: if supportsPerLit[xj , a] > 0 then 7: Remove a from zeroVals[xj ] 8: else 9: if a ∈ Dom(xj ) then 10: sup←findNewSupport(xj , a) 11: if sup=null then 12: prune(xj ,a) 13: else 14: addSupport(sup) 15: if supportsPerLit[xj , a] > 0 then 16: Remove a from zeroVals[xj ] 17: Goto 3 ble. We compare S HORT GAC against the special-purpose propagator (when available). We also compare against S HORT GAC-longsupport (S HORT GAC with full length supports), and against GAC-Schema [Bessière and Régin, 1997] as the closest equivalent algorithm without short supports. Our implementation of GAC-Schema is very similar to S HORT GAC, using the same data structures where possible. GAC-Schema and S HORT GAC-longsupport use the same (constraint-specific) findNewSupport as S HORT GAC, and subsequently extend the short support to full length using the minimum value for each extra variable. In each case, the constraint can be compactly represented as a disjunction. Therefore we compare S HORT GAC against Constructive Disjunction. The algorithm used is based upon [Lagerkvist and Schulte, 2009], without entailment detection. We do not compare to table constraints (eg [Gent et al., 2007]) because the constraints are too large. For example, the smallest element constraints reported below have 638 valid tuples, making it impossible even to generate and store the list of allowed tuples. 6 We use the quasigroup existence problem QG3 [Colton and Miguel, 2001] to evaluate S HORT GAC on the element constraint. The problem class has one parameter n, specifying the size of an n × n table (qg) of variables with domains {0 . . . n}. Rows, columns and one diagonal have GAC allDifferent constraints, following Colton and Miguel’s model. The element constraints represent the QG3 property that (i ∗ j) ∗ (j ∗ i) = i. This translates as ∀i, j : element(qg, aux[i, j], i), and aux[i, j]= n × qg[i, j] + qg[j, i], where aux[i, j] has domain {0 . . . n × n − 1}. For the constraint element(X, y, z), the findNewSupport method for S HORT GAC returns tuples of the form xi → j, y → i, z → j , where i is an index into the vector X and j is a common value of z and xi . S HORT GAC-list has all supports of this form. For Constructive Or, we used (x0 = z ∧ y = 0) ∨ · · · ∨ (xn = z ∧ y = n). We searched for all solutions, with limits of 100,000 nodes, 1,800 seconds, and 12GB of virtual memory. Table 1 shows our results on QG3. Of the general purpose methods, using short supports in either functional or list form is dramatically better than any alternative. For example at n = 10, even the may be written for a particular constraint. In the case studies below we briefly summarise what this function does. Alternatively, we provide a generic instantiation named findNewSupport-List (Algorithm 3) that takes a list of short supports for each literal (supportList). This is analogous to the Positive instantiation of GAC-Schema [Bessière and Régin, 1997]. FindNewSupport-List has persistent state: listPos, an array of integers indexed by variable and value, initially 0. This indicates the current position in the supportList. ListPos is not backtracked. The algorithm simply iterates through the list of supports, seeking one where all literals are valid. Using listPos stops the algorithm repeatedly iterating through the first section of the list when called repeatedly. Note that a constraintspecific findNewSupport can sometimes find shorter supports than findNewSupport-list. This is because a specific findNewSupport can take advantage of current domains whereas the supportList may only contain supports given the initial domains. For example, if the constraint becomes entailed, the specific findNewSupport can return the empty support. We exploit this fact in case study 3 below. As an optimisation, we omit literals from sup for assigned variables. This is applied to all findNewSupport functions (except for S HORT GAC-longsupport, described below). 5 Case Study 1: Element Algorithm 3 findNewSupport-list: findNewSupport(xi , a) Require: xi , a, supportList 1: for all j ∈ {listPos[xi , a]. . .(supportList[xi , a].size-1)} do 2: sup ←supportList[xi , a, j] 3: if all literals in sup are valid then 4: listPos[xi , a]← j 5: return sup 6: for all j ∈ {0 . . .listPos[xi , a]−1} do 7: sup ←supportList[xi , a, j] 8: if all literals in sup are valid then 9: listPos[xi , a]← j 10: return sup 11: return null Experimental Setup The Minion solver 0.10 [Gent et al., 2006a] was used for experiments, with our own additions. We used an 8-core machine with 2.27GHz Intel Xeon E5520 CPUs and 12GB memory. All times are a median of 5 runs. We report complete run times, i.e. we have not attempted to measure the time attributable to the given propagator. This both simplifies our experiments and has the advantage that we automatically take account of all factors affecting runtime. For each case study, we implemented a findNewSupport method for S HORT GAC specific to the constraint. We also used the generic list instantiation for comparison where possi- 626 n 6 7 8 9 10 WatchElt 22260 22731 16287 16129 18939 SG 4839 3736 2238 1961 2149 SG-L 2100 2539 1388 1115 1088 GAC-S 25.2 8.83 3.78 2.18 mem SG-Ls 11.0 3.29 1.26 0.756 0.373 n 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 Or 68.1 34.2 13.1 8.27 5.45 Table 1: Nodes searched per second for quasigroup existence problems. ‘mem’ indicates running out of memory. Columns are special purpose Watched Element propagator (WatchElt), S HORT GAC (SG), S HORT GAC-list (SG-L), GAC-Schema (GAC-S), S HORT GAC-longsupport (SG-Ls), and Constructive Or (Or) slower, list based method is 200 times faster than Constructive Or, the best of the other methods. Functional S HORT GAC is about twice as fast as S HORT GAC-list, but cannot compete with the special purpose element propagator in Minion [Gent et al., 2006b] which is about 5-9 times faster. It remains clear that exploiting short supports is very beneficial compared to other general purpose methods. 7 Lex 104955 113379 97371 81301 71276 66756 62854 56657 48426 37341 31949 24564 19342 15354 12228 SG 71156 88731 82645 70671 62617 48497 43764 36232 29070 21409 16795 13208 10453 8078 6046 GAC-S 3540 3555 3077 1766 1438 783 510 315 143 78.1 57.5 34.8 17.7 11.2 8.74 SG-Ls 3103 2644 2297 1413 1015 650 383 304 130 69.9 47.7 28.6 12.3 9.51 7.06 Or 10265 7243 6035 3276 2251 1197 504 281 145 97.0 mem mem mem mem mem Table 2: Results for BIBDs. We report nodes searched per second, with a limit of the first of either 1,000,000 nodes or 1,800s. Lex indicates GACLex, and other titles as in Table 1. n-w-h 18-31-69 19-47-53 20-34-85 21-38-88 22-39-98 23-64-68 24-56-88 25-43-129 26-70-89 27-47-148 Case Study 2: Lex-ordering We use BIBD problems to evaluate S HORT GAC on the lexicographic ordering constraint. The lex constraint is placed on both the rows and columns, to perform the “Double Lex” symmetry breaking method. We use the BIBD model and GACLex propagator given by [Frisch et al., 2002]. We use BIBDs with the parameter values (4n + 3, 4n + 3, 2n + 1, 2n + 1, n) and we impose a 2GB limit on runs. All methods explore identical search spaces. We searched for all solutions up to a node limit of 1,000,000 or time limit of 1800s (whichever was first). This limits all instances except n = 3 which required 41,982 nodes. For the constraint lexleq(X, Y ), we define mxi = min(Dom(xi )) and myi = max(Dom(yi )). The findNewSupport method for S HORT GAC finds the lowest index i ∈ {0 . . . n} such that mxi < myi , or i = n. The case i = n arises when X cannot be lex-less than Y , so a support is sought for X = Y . If i < n, the support contains xi → mxi , yi → myi . For each index j < i, if mxj = myj , then the short support contains xj → mxj , yj → myj otherwise there is no valid support and null is returned. The lex constraint on two arrays of length n and domain size d has more than dn short supports since all assignments where the two arrays are equal satisfy the constraint and cannot be reduced. S HORT GAC-list is not practical for any substantial constraint. Constructive Or uses the following representation: (x0 < y0 ) ∨ (x0 = y0 ∧ x1 < y1 ) ∨ · · · , including the case where all pairs are equal. Table 2 shows the results of our experiments on non-list based methods with values of n from 3 to 24. It is clear that the best method is the special purpose Lex propagator, up to twice as fast as S HORT GAC. The speedup of Lex over S HORT GAC increases only very slowly, from 1.47 at n = 3 to 2.02 at n = 24. S HORT GAC is by far the best general purpose method. At n = 3 S HORT GAC is 6.9 times better than the best alternative general-purpose method, and by n = 24 S HORT GAC is 692 times faster. SG 5.00 1.77 6.72 8.45 9.32 1.93 8.20 16.98 2.33 25.41 SG-L 23.96 20.72 41.98 43.63 58.85 46.80 76.83 mem mem mem GAC-S 35.58 33.52 50.31 56.54 66.91 57.52 74.51 101.10 84.95 128.22 SG-Ls 119.44 74.30 209.59 222.84 276.69 121.38 232.56 519.73 231.02 764.74 Or 121.01 109.86 206.22 208.17 284.70 145.22 352.77 526.88 197.51 699.66 Table 3: Times (seconds) for rectangle packing. Column titles as in Table 1. 8 Case Study 3: Rectangle Packing The rectangle packing problem [Simonis and O’Sullivan, 2008] (with parameters n, width and height) consists of packing all squares from size 1 × 1 to n × n into the rectangle of size width × height. This is modelled as follows: we have variables x1 . . . xn and y1 . . . yn , where (xi , yi ) represents the cartesian coordinates of the lower-left corner of the i × i square. Domains of xi variables are {0 . . . width − i}, and for yi variables are {0 . . . height − i}. Variables are branched in decreasing order of i, with xi before yi , smallest value first. The only type of constraint is non-overlap of squares i and j: (xi + i ≤ xj ) ∨ (xj + j ≤ xi ) ∨ (yi + i ≤ yj ) ∨ (yj + j ≤ yi ) Minion does not have the special-purpose non-overlap constraint [Simonis and O’Sullivan, 2008], so we only report a comparison of general purpose methods. The domains of xn and yn are reduced to break flip symmetries as described in [Simonis and O’Sullivan, 2008]. Our focus is performance of the non-overlap constraint, and so we did not implement the commonly-used implied constraints. The findNewSupport function for S HORT GAC is as follows. If any of the four disjuncts above are entailed given the current 627 domains, return the empty support (indicating entailment). Otherwise, return a support with 2 literals to satisfy one of the four disjuncts. S HORT GAC-list has all supports of size 2. For the experiment we used the optimum rectangle sizes reported by [Simonis and O’Sullivan, 2008]. Virtual memory was limited to 12GB. Times are given for the first 50,000 nodes of search in Table 3. We can see that S HORT GAC is by far the best technique. Of the other methods, GAC-Schema is second-best, but is always at least 5 times slower and can be almost 40 times slower. S HORT GAC-list is faster than GAC-Schema until it reaches larger problems, when it is first slightly slower and then runs out of memory. GAC-Schema in turn is significantly faster than either using S HORT GAC with full length tuples, or using Constructive Or. In summary, these results very clearly show the benefits of using short supports. 9 Acknowledgements We would like to thank anonymous reviewers for their comments, and EPSRC for funding this work through grants EP/H004092/1 and EP/E030394/1. References [Bessière and Régin, 1997] C. Bessière and J.-C. Régin. Arc consistency for general constraint networks: preliminary results. In Proc. IJCAI 97, pages 398–404, 1997. [Bessière et al., 2005] C. Bessière, J.-C. Régin, R. Yap, and Y. Zhang. An optimal coarse-grained arc consistency algorithm. Artificial Intelligence, 165:165–185, 2005. [Colton and Miguel, 2001] S. Colton and I. Miguel. Constraint generation via automated theory formation. In Proc. CP 2001, pages 575–579, 2001. [Frisch et al., 2002] A.M. Frisch, B. Hnich, Z. Kiziltan, I. Miguel, and T. Walsh. Global constraints for lexicographic orderings. In Proc. CP 2002, pages 93–108, 2002. [Gent et al., 2006a] I. Gent, C. Jefferson, and I. Miguel. Minion: A fast, scalable, constraint solver. In Proc. ECAI 2006, pages 98–102, 2006. [Gent et al., 2006b] I. Gent, C. Jefferson, and I. Miguel. Watched literals for constraint propagation in minion. In Proc. CP 2006, 2006. [Gent et al., 2007] I. Gent, C. Jefferson, I. Miguel, and P. Nightingale. Data structures for generalised arc consistency for extensional constraints. In Proc. AAAI-07, pages 191–197, 2007. [Jain et al., 2010] S. Jain, E. O’Mahony, and M. Sellmann. A complete multi-valued sat solver. In Proc. CP 2010, pages 281–296, 2010. [Katsirelos and Walsh, 2007] G. Katsirelos and T. Walsh. A compression algorithm for large arity extensional constraints. In Proc. CP 2007, pages 379–393, 2007. [Lagerkvist and Schulte, 2009] M. Lagerkvist and C. Schulte. Propagator groups. In Proc. CP 2009, pages 524–538, 2009. [Lhomme, 2003] O. Lhomme. An efficient filtering algorithm for disjunction of constraints. In Proc. CP 2003, pages 904– 908, 2003. [Mackworth, 1977] A. K. Mackworth. On reading sketch maps. In Proc. IJCAI 77, pages 598–606, 1977. [Mohr and Henderson, 1986] R. Mohr and T. C. Henderson. Arc and path consistency revisited. Artificial Intelligence, 28(2):225–233, 1986. [Régin, 1996] J.-C. Régin. Generalized arc consistency for global cardinality constraint. In Proc. AAAI 96, pages 209– 215, 1996. [Schulte and Tack, 2010] C. Schulte and G. Tack. Implementing efficient propagation control. In Proc. TRICS 2010, 2010. [Simonis and O’Sullivan, 2008] H. Simonis and B. O’Sullivan. Search strategies for rectangle packing. In Proc. CP 2008, pages 52–66, 2008. Related Work Our use of counters to count supports is inspired by AC4 [Mohr and Henderson, 1986], and is also related to the concept of quantitative supports [Jain et al., 2010]. There has been study of compressing the tuples of a constraint (eg using tries [Gent et al., 2007]). Such techniques are orthogonal to this paper because they only assist in finding full-length supports. Katsirelos and Walsh [2007] proposed a different generalisation of support, called a c-tuple. A c-tuple is a set of literals, such that every valid tuple contained in the c-tuple satisfies the constraint. Katsirelos and Walsh give an outline of a modified version of GAC-Schema which directly stores c-tuples. While c-tuples offer space savings when storing constraints, Katsirelos and Walsh found using c-tuples provides almost no performance improvement over GAC-Schema. For Constructive Or, Lhomme observed that a support for one disjunct A will support all values of any variable not contained in A. The concept is similar to a short support albeit less general, because the length of the supports is fixed to the length of the disjuncts. He presents a non-incremental constructive disjunction for two disjuncts [Lhomme, 2003]. 10 Conclusions We have introduced and described in detail S HORT GAC, a general purpose propagation algorithm for short supports. Either it can be given a specialised function to find new supports for each constraint, or used with a method which accepts an explicit list of short supports. In three case studies, S HORTGAC is far faster than general purpose methods. In the best case it achieved speeds about 50% of that of a special purpose propagator. We conclude that where short supports are available, S HORT GAC will provide much better performance than existing general-purpose constraint propagation methods. We identify two areas of interest for future work. First, we observed that S HORT GAC with lists has memory problems. Providing a practically effective version of the table constraint with short supports would further increase the utility of our work. Second, we see that S HORT GAC with full length supports was significantly slower than GAC-Schema. It would be beneficial if a single propagation algorithm could be found that was as fast as S HORT GAC on short supports and as fast as GAC-Schema on long supports. 628