1:- encoding(utf8).
2
3/*  Part of SWI-Prolog
4
5    Author:        Markus Triska
6    E-mail:        triska@metalevel.at
7    WWW:           http://www.swi-prolog.org
8    Copyright (C): 2007-2017 Markus Triska
9    All rights reserved.
10
11    Redistribution and use in source and binary forms, with or without
12    modification, are permitted provided that the following conditions
13    are met:
14
15    1. Redistributions of source code must retain the above copyright
16       notice, this list of conditions and the following disclaimer.
17
18    2. Redistributions in binary form must reproduce the above copyright
19       notice, this list of conditions and the following disclaimer in
20       the documentation and/or other materials provided with the
21       distribution.
22
23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34    POSSIBILITY OF SUCH DAMAGE.
35*/
36
37/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
38   Thanks to Tom Schrijvers for his "bounds.pl", the first finite
39   domain constraint solver included with SWI-Prolog. I've learned a
40   lot from it and could even use some of the code for this solver.
41   The propagation queue idea is taken from "prop.pl", a prototype
42   solver also written by Tom. Highlights of the present solver:
43
44   Symbolic constants for infinities
45   ---------------------------------
46
47   ?- X #>= 0, Y #=< 0.
48   %@ X in 0..sup,
49   %@ Y in inf..0.
50
51   No artificial limits (using GMP)
52   ---------------------------------
53
54   ?- N #= 2^66, X #\= N.
55   %@ N = 73786976294838206464,
56   %@ X in inf..73786976294838206463\/73786976294838206465..sup.
57
58   Often stronger propagation
59   ---------------------------------
60
61   ?- Y #= abs(X), Y #\= 3, Z * Z #= 4.
62   %@ Y in 0..2\/4..sup,
63   %@ Y#=abs(X),
64   %@ X in inf.. -4\/ -2..2\/4..sup,
65   %@ Z in -2\/2.
66
67   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68
69   Development of this library has moved to SICStus Prolog. If you
70   need any additional features or want to help, please file an issue at:
71
72                    https://github.com/triska/clpz
73                    ==============================
74
75- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
76
77:- module(clpfd, [
78                  op(760, yfx, #<==>),
79                  op(750, xfy, #==>),
80                  op(750, yfx, #<==),
81                  op(740, yfx, #\/),
82                  op(730, yfx, #\),
83                  op(720, yfx, #/\),
84                  op(710,  fy, #\),
85                  op(700, xfx, #>),
86                  op(700, xfx, #<),
87                  op(700, xfx, #>=),
88                  op(700, xfx, #=<),
89                  op(700, xfx, #=),
90                  op(700, xfx, #\=),
91                  op(700, xfx, in),
92                  op(700, xfx, ins),
93                  op(450, xfx, ..), % should bind more tightly than \/
94                  (#>)/2,
95                  (#<)/2,
96                  (#>=)/2,
97                  (#=<)/2,
98                  (#=)/2,
99                  (#\=)/2,
100                  (#\)/1,
101                  (#<==>)/2,
102                  (#==>)/2,
103                  (#<==)/2,
104                  (#\/)/2,
105                  (#\)/2,
106                  (#/\)/2,
107                  (in)/2,
108                  (ins)/2,
109                  all_different/1,
110                  all_distinct/1,
111                  sum/3,
112                  scalar_product/4,
113                  tuples_in/2,
114                  labeling/2,
115                  label/1,
116                  indomain/1,
117                  lex_chain/1,
118                  serialized/2,
119                  global_cardinality/2,
120                  global_cardinality/3,
121                  circuit/1,
122                  cumulative/1,
123                  cumulative/2,
124                  disjoint2/1,
125                  element/3,
126                  automaton/3,
127                  automaton/8,
128                  transpose/2,
129                  zcompare/3,
130                  chain/2,
131                  fd_var/1,
132                  fd_inf/2,
133                  fd_sup/2,
134                  fd_size/2,
135                  fd_dom/2
136                 ]).
137
138:- public                               % called from goal_expansion
139        clpfd_equal/2,
140        clpfd_geq/2.
141
142:- use_module(library(apply)).
143:- use_module(library(apply_macros)).
144:- use_module(library(assoc)).
145:- use_module(library(error)).
146:- use_module(library(lists)).
147:- use_module(library(pairs)).
148
149:- op(700, xfx, cis).
150:- op(700, xfx, cis_geq).
151:- op(700, xfx, cis_gt).
152:- op(700, xfx, cis_leq).
153:- op(700, xfx, cis_lt).
154
155/** <module> CLP(FD): Constraint Logic Programming over Finite Domains
156
157**Development of this library has moved to SICStus Prolog.**
158
159Please see [**CLP(Z)**](https://github.com/triska/clpz) for more
160information.
161
162## Introduction			{#clpfd-intro}
163
164This library provides CLP(FD): Constraint Logic Programming over
165Finite Domains. This is an instance of the general [CLP(_X_)
166scheme](<#clp>), extending logic programming with reasoning over
167specialised domains. CLP(FD) lets us reason about **integers** in a
168way that honors the relational nature of Prolog.
169
170Read [**The Power of Prolog**](https://www.metalevel.at/prolog) to
171understand how this library is meant to be used in practice.
172
173There are two major use cases of CLP(FD) constraints:
174
175    1. [**declarative integer arithmetic**](<#clpfd-integer-arith>)
176    2. solving **combinatorial problems** such as planning, scheduling
177       and allocation tasks.
178
179The predicates of this library can be classified as:
180
181    * _arithmetic_ constraints like #=/2, #>/2 and #\=/2 [](<#clpfd-arithmetic>)
182    * the _membership_ constraints in/2 and ins/2 [](<#clpfd-membership>)
183    * the _enumeration_ predicates indomain/1, label/1 and labeling/2 [](<#clpfd-enumeration>)
184    * _combinatorial_ constraints like all_distinct/1 and global_cardinality/2 [](<#clpfd-global>)
185    * _reification_ predicates such as #<==>/2 [](<#clpfd-reification-predicates>)
186    * _reflection_ predicates such as fd_dom/2 [](<#clpfd-reflection-predicates>)
187
188In most cases, [_arithmetic constraints_](<#clpfd-arith-constraints>)
189are the only predicates you will ever need from this library. When
190reasoning over integers, simply replace low-level arithmetic
191predicates like `(is)/2` and `(>)/2` by the corresponding CLP(FD)
192constraints like #=/2 and #>/2 to honor and preserve declarative
193properties of your programs. For satisfactory performance, arithmetic
194constraints are implicitly rewritten at compilation time so that
195low-level fallback predicates are automatically used whenever
196possible.
197
198Almost all Prolog programs also reason about integers. Therefore, it
199is highly advisable that you make CLP(FD) constraints available in all
200your programs. One way to do this is to put the following directive in
201your =|<config>/init.pl|= initialisation file:
202
203==
204:- use_module(library(clpfd)).
205==
206
207All example programs that appear in the CLP(FD) documentation assume
208that you have done this.
209
210Important concepts and principles of this library are illustrated by
211means of usage examples that are available in a public git repository:
212[**github.com/triska/clpfd**](https://github.com/triska/clpfd)
213
214If you are used to the complicated operational considerations that
215low-level arithmetic primitives necessitate, then moving to CLP(FD)
216constraints may, due to their power and convenience, at first feel to
217you excessive and almost like cheating. It _isn't_. Constraints are an
218integral part of all popular Prolog systems, and they are designed
219to help you eliminate and avoid the use of low-level and less general
220primitives by providing declarative alternatives that are meant to be
221used instead.
222
223When teaching Prolog, CLP(FD) constraints should be introduced
224_before_ explaining low-level arithmetic predicates and their
225procedural idiosyncrasies. This is because constraints are easy to
226explain, understand and use due to their purely relational nature. In
227contrast, the modedness and directionality of low-level arithmetic
228primitives are impure limitations that are better deferred to more
229advanced lectures.
230
231We recommend the following reference (PDF:
232[metalevel.at/swiclpfd.pdf](https://www.metalevel.at/swiclpfd.pdf)) for
233citing this library in scientific publications:
234
235==
236@inproceedings{Triska12,
237  author    = {Markus Triska},
238  title     = {The Finite Domain Constraint Solver of {SWI-Prolog}},
239  booktitle = {FLOPS},
240  series    = {LNCS},
241  volume    = {7294},
242  year      = {2012},
243  pages     = {307-316}
244}
245==
246
247More information about CLP(FD) constraints and their implementation is
248contained in: [**metalevel.at/drt.pdf**](https://www.metalevel.at/drt.pdf)
249
250The best way to discuss applying, improving and extending CLP(FD)
251constraints is to use the dedicated `clpfd` tag on
252[stackoverflow.com](http://stackoverflow.com). Several of the world's
253foremost CLP(FD) experts regularly participate in these discussions
254and will help you for free on this platform.
255
256## Arithmetic constraints		{#clpfd-arith-constraints}
257
258In modern Prolog systems, *arithmetic constraints* subsume and
259supersede low-level predicates over integers. The main advantage of
260arithmetic constraints is that they are true _relations_ and can be
261used in all directions. For most programs, arithmetic constraints are
262the only predicates you will ever need from this library.
263
264The most important arithmetic constraint is #=/2, which subsumes both
265`(is)/2` and `(=:=)/2` over integers. Use #=/2 to make your programs
266more general. See [declarative integer
267arithmetic](<#clpfd-integer-arith>).
268
269In total, the arithmetic constraints are:
270
271    | Expr1 `#=`  Expr2  | Expr1 equals Expr2                       |
272    | Expr1 `#\=` Expr2  | Expr1 is not equal to Expr2              |
273    | Expr1 `#>=` Expr2  | Expr1 is greater than or equal to Expr2  |
274    | Expr1 `#=<` Expr2  | Expr1 is less than or equal to Expr2     |
275    | Expr1 `#>` Expr2   | Expr1 is greater than Expr2              |
276    | Expr1 `#<` Expr2   | Expr1 is less than Expr2                 |
277
278`Expr1` and `Expr2` denote *arithmetic expressions*, which are:
279
280    | _integer_          | Given value                          |
281    | _variable_         | Unknown integer                      |
282    | ?(_variable_)      | Unknown integer                      |
283    | -Expr              | Unary minus                          |
284    | Expr + Expr        | Addition                             |
285    | Expr * Expr        | Multiplication                       |
286    | Expr - Expr        | Subtraction                          |
287    | Expr ^ Expr        | Exponentiation                       |
288    | min(Expr,Expr)     | Minimum of two expressions           |
289    | max(Expr,Expr)     | Maximum of two expressions           |
290    | Expr `mod` Expr    | Modulo induced by floored division   |
291    | Expr `rem` Expr    | Modulo induced by truncated division |
292    | abs(Expr)          | Absolute value                       |
293    | Expr // Expr       | Truncated integer division           |
294    | Expr div Expr      | Floored integer division             |
295
296where `Expr` again denotes an arithmetic expression.
297
298The bitwise operations `(\)/1`, `(/\)/2`, `(\/)/2`, `(>>)/2`,
299`(<<)/2`, `lsb/1`, `msb/1`, `popcount/1` and `(xor)/2` are also
300supported.
301
302## Declarative integer arithmetic		{#clpfd-integer-arith}
303
304The [_arithmetic constraints_](<#clpfd-arith-constraints>)   #=/2,  #>/2
305etc. are meant  to  be  used   _instead_  of  the  primitives  `(is)/2`,
306`(=:=)/2`, `(>)/2` etc. over integers. Almost   all Prolog programs also
307reason about integers. Therefore, it  is   recommended  that you put the
308following directive in your =|<config>/init.pl|=  initialisation file to
309make CLP(FD) constraints available in all your programs:
310
311==
312:- use_module(library(clpfd)).
313==
314
315Throughout the following, it is assumed that you have done this.
316
317The most basic use of CLP(FD) constraints is _evaluation_ of
318arithmetic expressions involving integers. For example:
319
320==
321?- X #= 1+2.
322X = 3.
323==
324
325This could in principle also be achieved with the lower-level
326predicate `(is)/2`. However, an important advantage of arithmetic
327constraints is their purely relational nature: Constraints can be used
328in _all directions_, also if one or more of their arguments are only
329partially instantiated. For example:
330
331==
332?- 3 #= Y+2.
333Y = 1.
334==
335
336This relational nature makes CLP(FD) constraints easy to explain and
337use, and well suited for beginners and experienced Prolog programmers
338alike. In contrast, when using low-level integer arithmetic, we get:
339
340==
341?- 3 is Y+2.
342ERROR: is/2: Arguments are not sufficiently instantiated
343
344?- 3 =:= Y+2.
345ERROR: =:=/2: Arguments are not sufficiently instantiated
346==
347
348Due to the necessary operational considerations, the use of these
349low-level arithmetic predicates is considerably harder to understand
350and should therefore be deferred to more advanced lectures.
351
352For supported expressions, CLP(FD) constraints are drop-in
353replacements of these low-level arithmetic predicates, often yielding
354more general programs. See [`n_factorial/2`](<#clpfd-factorial>) for an
355example.
356
357This library uses goal_expansion/2 to automatically rewrite
358constraints at compilation time so that low-level arithmetic
359predicates are _automatically_ used whenever possible. For example,
360the predicate:
361
362==
363positive_integer(N) :- N #>= 1.
364==
365
366is executed as if it were written as:
367
368==
369positive_integer(N) :-
370        (   integer(N)
371        ->  N >= 1
372        ;   N #>= 1
373        ).
374==
375
376This illustrates why the performance of CLP(FD) constraints is almost
377always completely satisfactory when they are used in modes that can be
378handled by low-level arithmetic. To disable the automatic rewriting,
379set the Prolog flag `clpfd_goal_expansion` to `false`.
380
381If you are used to the complicated operational considerations that
382low-level arithmetic primitives necessitate, then moving to CLP(FD)
383constraints may, due to their power and convenience, at first feel to
384you excessive and almost like cheating. It _isn't_. Constraints are an
385integral part of all popular Prolog systems, and they are designed
386to help you eliminate and avoid the use of low-level and less general
387primitives by providing declarative alternatives that are meant to be
388used instead.
389
390
391## Example: Factorial relation {#clpfd-factorial}
392
393We illustrate the benefit of using #=/2 for more generality with a
394simple example.
395
396Consider first a rather conventional definition of `n_factorial/2`,
397relating each natural number _N_ to its factorial _F_:
398
399==
400n_factorial(0, 1).
401n_factorial(N, F) :-
402        N #> 0,
403        N1 #= N - 1,
404        n_factorial(N1, F1),
405        F #= N * F1.
406==
407
408This program uses CLP(FD) constraints _instead_ of low-level
409arithmetic throughout, and everything that _would have worked_ with
410low-level arithmetic _also_ works with CLP(FD) constraints, retaining
411roughly the same performance. For example:
412
413==
414?- n_factorial(47, F).
415F = 258623241511168180642964355153611979969197632389120000000000 ;
416false.
417==
418
419Now the point: Due to the increased flexibility and generality of
420CLP(FD) constraints, we are free to _reorder_ the goals as follows:
421
422==
423n_factorial(0, 1).
424n_factorial(N, F) :-
425        N #> 0,
426        N1 #= N - 1,
427        F #= N * F1,
428        n_factorial(N1, F1).
429==
430
431In this concrete case, _termination_ properties of the predicate are
432improved. For example, the following queries now both terminate:
433
434==
435?- n_factorial(N, 1).
436N = 0 ;
437N = 1 ;
438false.
439
440?- n_factorial(N, 3).
441false.
442==
443
444To make the predicate terminate if _any_ argument is instantiated, add
445the (implied) constraint `F #\= 0` before the recursive call.
446Otherwise, the query `n_factorial(N, 0)` is the only non-terminating
447case of this kind.
448
449The value of CLP(FD) constraints does _not_ lie in completely freeing
450us from _all_ procedural phenomena. For example, the two programs do
451not even have the same _termination properties_ in all cases.
452Instead, the primary benefit of CLP(FD) constraints is that they allow
453you to try different execution orders and apply [**declarative
454debugging**](https://www.metalevel.at/prolog/debugging)
455techniques _at all_!  Reordering goals (and clauses) can significantly
456impact the performance of Prolog programs, and you are free to try
457different variants if you use declarative approaches. Moreover, since
458all CLP(FD) constraints _always terminate_, placing them earlier can
459at most _improve_, never worsen, the termination properties of your
460programs. An additional benefit of CLP(FD) constraints is that they
461eliminate the complexity of introducing `(is)/2` and `(=:=)/2` to
462beginners, since _both_ predicates are subsumed by #=/2 when reasoning
463over integers.
464
465In the case above, the clauses are mutually exclusive _if_ the first
466argument is sufficiently instantiated. To make the predicate
467deterministic in such cases while retaining its generality, you can
468use zcompare/3 to _reify_ a comparison, making the different cases
469distinguishable by pattern matching. For example, in this concrete
470case and others like it, you can use `zcompare(Comp, 0, N)` to obtain as
471`Comp` the symbolic outcome (`<`, `=`, `>`) of 0 compared to N.
472
473## Combinatorial constraints  {#clpfd-combinatorial}
474
475In addition to subsuming and replacing low-level arithmetic
476predicates, CLP(FD) constraints are often used to solve combinatorial
477problems such as planning, scheduling and allocation tasks. Among the
478most frequently used *combinatorial constraints* are all_distinct/1,
479global_cardinality/2 and cumulative/2. This library also provides
480several other constraints like disjoint2/1 and automaton/8, which are
481useful in more specialized applications.
482
483## Domains                             {#clpfd-domains}
484
485Each CLP(FD) variable has an associated set of admissible integers,
486which we call the variable's *domain*. Initially, the domain of each
487CLP(FD) variable is the set of _all_ integers. CLP(FD) constraints
488like #=/2, #>/2 and #\=/2 can at most reduce, and never extend, the
489domains of their arguments. The constraints in/2 and ins/2 let us
490explicitly state domains of CLP(FD) variables. The process of
491determining and adjusting domains of variables is called constraint
492*propagation*, and it is performed automatically by this library. When
493the domain of a variable contains only one element, then the variable
494is automatically unified to that element.
495
496Domains are taken into account when further constraints are stated,
497and by enumeration predicates like labeling/2.
498
499## Example: Sudoku {#clpfd-sudoku}
500
501As another example, consider _Sudoku_: It is a popular puzzle
502over integers that can be easily solved with CLP(FD) constraints.
503
504==
505sudoku(Rows) :-
506        length(Rows, 9), maplist(same_length(Rows), Rows),
507        append(Rows, Vs), Vs ins 1..9,
508        maplist(all_distinct, Rows),
509        transpose(Rows, Columns),
510        maplist(all_distinct, Columns),
511        Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
512        blocks(As, Bs, Cs),
513        blocks(Ds, Es, Fs),
514        blocks(Gs, Hs, Is).
515
516blocks([], [], []).
517blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
518        all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
519        blocks(Ns1, Ns2, Ns3).
520
521problem(1, [[_,_,_,_,_,_,_,_,_],
522            [_,_,_,_,_,3,_,8,5],
523            [_,_,1,_,2,_,_,_,_],
524            [_,_,_,5,_,7,_,_,_],
525            [_,_,4,_,_,_,1,_,_],
526            [_,9,_,_,_,_,_,_,_],
527            [5,_,_,_,_,_,_,7,3],
528            [_,_,2,_,1,_,_,_,_],
529            [_,_,_,_,4,_,_,_,9]]).
530==
531
532Sample query:
533
534==
535?- problem(1, Rows), sudoku(Rows), maplist(writeln, Rows).
536[9,8,7,6,5,4,3,2,1]
537[2,4,6,1,7,3,9,8,5]
538[3,5,1,9,2,8,7,4,6]
539[1,2,8,5,3,7,6,9,4]
540[6,3,4,8,9,2,1,5,7]
541[7,9,5,4,6,1,8,3,2]
542[5,1,9,2,8,6,4,7,3]
543[4,7,2,3,1,9,5,6,8]
544[8,6,3,7,4,5,2,1,9]
545Rows = [[9, 8, 7, 6, 5, 4, 3, 2|...], ... , [...|...]].
546==
547
548In this concrete case, the constraint solver is strong enough to find
549the unique solution without any search. For the general case, see
550[search](<#clpfd-search>).
551
552
553## Residual goals				{#clpfd-residual-goals}
554
555Here is an example session with a few queries and their answers:
556
557==
558?- X #> 3.
559X in 4..sup.
560
561?- X #\= 20.
562X in inf..19\/21..sup.
563
564?- 2*X #= 10.
565X = 5.
566
567?- X*X #= 144.
568X in -12\/12.
569
570?- 4*X + 2*Y #= 24, X + Y #= 9, [X,Y] ins 0..sup.
571X = 3,
572Y = 6.
573
574?- X #= Y #<==> B, X in 0..3, Y in 4..5.
575B = 0,
576X in 0..3,
577Y in 4..5.
578==
579
580The answers emitted by the toplevel are called _residual programs_,
581and the goals that comprise each answer are called **residual goals**.
582In each case above, and as for all pure programs, the residual program
583is declaratively equivalent to the original query. From the residual
584goals, it is clear that the constraint solver has deduced additional
585domain restrictions in many cases.
586
587To inspect residual goals, it is best to let the toplevel display them
588for us. Wrap the call of your predicate into call_residue_vars/2 to
589make sure that all constrained variables are displayed. To make the
590constraints a variable is involved in available as a Prolog term for
591further reasoning within your program, use copy_term/3. For example:
592
593==
594?- X #= Y + Z, X in 0..5, copy_term([X,Y,Z], [X,Y,Z], Gs).
595Gs = [clpfd: (X in 0..5), clpfd: (Y+Z#=X)],
596X in 0..5,
597Y+Z#=X.
598==
599
600This library also provides _reflection_ predicates (like fd_dom/2,
601fd_size/2 etc.) with which we can inspect a variable's current
602domain. These predicates can be useful if you want to implement your
603own labeling strategies.
604
605## Core relations and search    {#clpfd-search}
606
607Using CLP(FD) constraints to solve combinatorial tasks typically
608consists of two phases:
609
610    1. **Modeling**. In this phase, all relevant constraints are stated.
611    2. **Search**. In this phase, _enumeration predicates_ are used
612       to search for concrete solutions.
613
614It is good practice to keep the modeling part, via a dedicated
615predicate called the *core relation*, separate from the actual
616search for solutions. This lets us observe termination and
617determinism properties of the core relation in isolation from the
618search, and more easily try different search strategies.
619
620As an example of a constraint satisfaction problem, consider the
621cryptoarithmetic puzzle SEND + MORE = MONEY, where different letters
622denote distinct integers between 0 and 9. It can be modeled in CLP(FD)
623as follows:
624
625==
626puzzle([S,E,N,D] + [M,O,R,E] = [M,O,N,E,Y]) :-
627        Vars = [S,E,N,D,M,O,R,Y],
628        Vars ins 0..9,
629        all_different(Vars),
630                  S*1000 + E*100 + N*10 + D +
631                  M*1000 + O*100 + R*10 + E #=
632        M*10000 + O*1000 + N*100 + E*10 + Y,
633        M #\= 0, S #\= 0.
634==
635
636Notice that we are _not_ using labeling/2 in this predicate, so that
637we can first execute and observe the modeling part in isolation.
638Sample query and its result (actual variables replaced for
639readability):
640
641==
642?- puzzle(As+Bs=Cs).
643As = [9, A2, A3, A4],
644Bs = [1, 0, B3, A2],
645Cs = [1, 0, A3, A2, C5],
646A2 in 4..7,
647all_different([9, A2, A3, A4, 1, 0, B3, C5]),
64891*A2+A4+10*B3#=90*A3+C5,
649A3 in 5..8,
650A4 in 2..8,
651B3 in 2..8,
652C5 in 2..8.
653==
654
655From this answer, we see that this core relation _terminates_ and is in
656fact _deterministic_. Moreover, we see from the residual goals that
657the constraint solver has deduced more stringent bounds for all
658variables. Such observations are only possible if modeling and search
659parts are cleanly separated.
660
661Labeling can then be used to search for solutions in a separate
662predicate or goal:
663
664==
665?- puzzle(As+Bs=Cs), label(As).
666As = [9, 5, 6, 7],
667Bs = [1, 0, 8, 5],
668Cs = [1, 0, 6, 5, 2] ;
669false.
670==
671
672In this case, it suffices to label a subset of variables to find the
673puzzle's unique solution, since the constraint solver is strong enough
674to reduce the domains of remaining variables to singleton sets. In
675general though, it is necessary to label all variables to obtain
676ground solutions.
677
678## Example: Eight queens puzzle {#clpfd-n-queens}
679
680We illustrate the concepts of the preceding sections by means of the
681so-called _eight queens puzzle_. The task is to place 8 queens on an
6828x8 chessboard such that none of the queens is under attack. This
683means that no two queens share the same row, column or diagonal.
684
685To express this puzzle via CLP(FD) constraints, we must first pick a
686suitable representation. Since CLP(FD) constraints reason over
687_integers_, we must find a way to map the positions of queens to
688integers. Several such mappings are conceivable, and it is not
689immediately obvious which we should use. On top of that, different
690constraints can be used to express the desired relations. For such
691reasons, _modeling_ combinatorial problems via CLP(FD) constraints
692often necessitates some creativity and has been described as more of
693an art than a science.
694
695In our concrete case, we observe that there must be exactly one queen
696per column. The following representation therefore suggests itself: We
697are looking for 8 integers, one for each column, where each integer
698denotes the _row_ of the queen that is placed in the respective
699column, and which are subject to certain constraints.
700
701In fact, let us now generalize the task to the so-called _N queens
702puzzle_, which is obtained by replacing 8 by _N_ everywhere it occurs
703in the above description. We implement the above considerations in the
704**core relation** `n_queens/2`, where the first argument is the number
705of queens (which is identical to the number of rows and columns of the
706generalized chessboard), and the second argument is a list of _N_
707integers that represents a solution in the form described above.
708
709==
710n_queens(N, Qs) :-
711        length(Qs, N),
712        Qs ins 1..N,
713        safe_queens(Qs).
714
715safe_queens([]).
716safe_queens([Q|Qs]) :- safe_queens(Qs, Q, 1), safe_queens(Qs).
717
718safe_queens([], _, _).
719safe_queens([Q|Qs], Q0, D0) :-
720        Q0 #\= Q,
721        abs(Q0 - Q) #\= D0,
722        D1 #= D0 + 1,
723        safe_queens(Qs, Q0, D1).
724==
725
726Note that all these predicates can be used in _all directions_: We
727can use them to _find_ solutions, _test_ solutions and _complete_
728partially instantiated solutions.
729
730The original task can be readily solved with the following query:
731
732==
733?- n_queens(8, Qs), label(Qs).
734Qs = [1, 5, 8, 6, 3, 7, 2, 4] .
735==
736
737Using suitable labeling strategies, we can easily find solutions with
73880 queens and more:
739
740==
741?- n_queens(80, Qs), labeling([ff], Qs).
742Qs = [1, 3, 5, 44, 42, 4, 50, 7, 68|...] .
743
744?- time((n_queens(90, Qs), labeling([ff], Qs))).
745% 5,904,401 inferences, 0.722 CPU in 0.737 seconds (98% CPU)
746Qs = [1, 3, 5, 50, 42, 4, 49, 7, 59|...] .
747==
748
749Experimenting with different search strategies is easy because we have
750separated the core relation from the actual search.
751
752
753
754## Optimisation    {#clpfd-optimisation}
755
756We can use labeling/2 to minimize or maximize the value of a CLP(FD)
757expression, and generate solutions in increasing or decreasing order
758of the value. See the labeling options `min(Expr)` and `max(Expr)`,
759respectively.
760
761Again, to easily try different labeling options in connection with
762optimisation, we recommend to introduce a dedicated predicate for
763posting constraints, and to use `labeling/2` in a separate goal. This
764way, we can observe properties of the core relation in isolation,
765and try different labeling options without recompiling our code.
766
767If necessary, we can use `once/1` to commit to the first optimal
768solution. However, it is often very valuable to see alternative
769solutions that are _also_ optimal, so that we can choose among optimal
770solutions by other criteria. For the sake of
771[**purity**](https://www.metalevel.at/prolog/purity) and
772completeness, we recommend to avoid `once/1` and other constructs that
773lead to impurities in CLP(FD) programs.
774
775Related to optimisation with CLP(FD) constraints are
776[`library(simplex)`](http://eu.swi-prolog.org/man/simplex.html) and
777CLP(Q) which reason about _linear_ constraints over rational numbers.
778
779## Reification				{#clpfd-reification}
780
781The constraints in/2, #=/2, #\=/2, #</2, #>/2, #=</2, and #>=/2 can be
782_reified_, which means reflecting their truth values into Boolean
783values represented by the integers 0 and 1. Let P and Q denote
784reifiable constraints or Boolean variables, then:
785
786    | #\ Q      | True iff Q is false                  |
787    | P #\/ Q   | True iff either P or Q               |
788    | P #/\ Q   | True iff both P and Q                |
789    | P #\ Q    | True iff either P or Q, but not both |
790    | P #<==> Q | True iff P and Q are equivalent      |
791    | P #==> Q  | True iff P implies Q                 |
792    | P #<== Q  | True iff Q implies P                 |
793
794The constraints of this table are reifiable as well.
795
796When reasoning over Boolean variables, also consider using
797CLP(B) constraints as provided by
798[`library(clpb)`](http://eu.swi-prolog.org/man/clpb.html).
799
800## Enabling monotonic CLP(FD)		{#clpfd-monotonicity}
801
802In the default execution mode, CLP(FD) constraints still exhibit some
803non-relational properties. For example, _adding_ constraints can yield
804new solutions:
805
806==
807?-          X #= 2, X = 1+1.
808false.
809
810?- X = 1+1, X #= 2, X = 1+1.
811X = 1+1.
812==
813
814This behaviour is highly problematic from a logical point of view, and
815it may render declarative debugging techniques inapplicable.
816
817Set the Prolog flag `clpfd_monotonic` to `true` to make CLP(FD)
818**monotonic**: This means that _adding_ new constraints _cannot_ yield
819new solutions. When this flag is `true`, we must wrap variables that
820occur in arithmetic expressions with the functor `(?)/1` or `(#)/1`. For
821example:
822
823==
824?- set_prolog_flag(clpfd_monotonic, true).
825true.
826
827?- #(X) #= #(Y) + #(Z).
828#(Y)+ #(Z)#= #(X).
829
830?-          X #= 2, X = 1+1.
831ERROR: Arguments are not sufficiently instantiated
832==
833
834The wrapper can be omitted for variables that are already constrained
835to integers.
836
837## Custom constraints			{#clpfd-custom-constraints}
838
839We can define custom constraints. The mechanism to do this is not yet
840finalised, and we welcome suggestions and descriptions of use cases
841that are important to you.
842
843As an example of how it can be done currently, let us define a new
844custom constraint `oneground(X,Y,Z)`, where Z shall be 1 if at least
845one of X and Y is instantiated:
846
847==
848:- multifile clpfd:run_propagator/2.
849
850oneground(X, Y, Z) :-
851        clpfd:make_propagator(oneground(X, Y, Z), Prop),
852        clpfd:init_propagator(X, Prop),
853        clpfd:init_propagator(Y, Prop),
854        clpfd:trigger_once(Prop).
855
856clpfd:run_propagator(oneground(X, Y, Z), MState) :-
857        (   integer(X) -> clpfd:kill(MState), Z = 1
858        ;   integer(Y) -> clpfd:kill(MState), Z = 1
859        ;   true
860        ).
861==
862
863First, clpfd:make_propagator/2 is used to transform a user-defined
864representation of the new constraint to an internal form. With
865clpfd:init_propagator/2, this internal form is then attached to X and
866Y. From now on, the propagator will be invoked whenever the domains of
867X or Y are changed. Then, clpfd:trigger_once/1 is used to give the
868propagator its first chance for propagation even though the variables'
869domains have not yet changed. Finally, clpfd:run_propagator/2 is
870extended to define the actual propagator. As explained, this predicate
871is automatically called by the constraint solver. The first argument
872is the user-defined representation of the constraint as used in
873clpfd:make_propagator/2, and the second argument is a mutable state
874that can be used to prevent further invocations of the propagator when
875the constraint has become entailed, by using clpfd:kill/1. An example
876of using the new constraint:
877
878==
879?- oneground(X, Y, Z), Y = 5.
880Y = 5,
881Z = 1,
882X in inf..sup.
883==
884
885## Applications   {#clpfd-applications}
886
887CLP(FD) applications that we find particularly impressive and worth
888studying include:
889
890  * Michael Hendricks uses CLP(FD) constraints for flexible reasoning
891    about _dates_ and _times_ in the
892    [`julian`](http://www.swi-prolog.org/pack/list?p=julian) package.
893  * Julien Cumin uses CLP(FD) constraints for integer arithmetic in
894    [=Brachylog=](https://github.com/JCumin/Brachylog).
895
896## Acknowledgments {#clpfd-acknowledgments}
897
898This library gives you a glimpse of what [**SICStus
899Prolog**](https://sicstus.sics.se/) can do. The API is intentionally
900mostly compatible with that of SICStus Prolog, so that you can easily
901switch to a much more feature-rich and much faster CLP(FD) system when
902you need it. I thank [Mats Carlsson](https://www.sics.se/~matsc/), the
903designer and main implementor of SICStus Prolog, for his elegant
904example. I first encountered his system as part of the excellent
905[**GUPU**](http://www.complang.tuwien.ac.at/ulrich/gupu/) teaching
906environment by [Ulrich
907Neumerkel](http://www.complang.tuwien.ac.at/ulrich/). Ulrich was also
908the first and most determined tester of the present system, filing
909hundreds of comments and suggestions for improvement. [Tom
910Schrijvers](https://people.cs.kuleuven.be/~tom.schrijvers/) has
911contributed several constraint libraries to SWI-Prolog, and I learned
912a lot from his coding style and implementation examples. [Bart
913Demoen](https://people.cs.kuleuven.be/~bart.demoen/) was a driving
914force behind the implementation of attributed variables in SWI-Prolog,
915and this library could not even have started without his prior work
916and contributions. Thank you all!
917
918## CLP(FD) predicate index			{#clpfd-predicate-index}
919
920In the following, each CLP(FD) predicate is described in more detail.
921
922We recommend the following link to refer to this manual:
923
924http://eu.swi-prolog.org/man/clpfd.html
925
926@author [Markus Triska](https://www.metalevel.at)
927*/
928
929:- create_prolog_flag(clpfd_monotonic, false, []).
930
931/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
932   A bound is either:
933
934   n(N):    integer N
935   inf:     infimum of Z (= negative infinity)
936   sup:     supremum of Z (= positive infinity)
937- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
938
939is_bound(n(N)) :- integer(N).
940is_bound(inf).
941is_bound(sup).
942
943defaulty_to_bound(D, P) :- ( integer(D) -> P = n(D) ; P = D ).
944
945/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
946   Compactified is/2 and predicates for several arithmetic expressions
947   with infinities, tailored for the modes needed by this solver.
948- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
949
950goal_expansion(A cis B, Expansion) :-
951        phrase(cis_goals(B, A), Goals),
952        list_goal(Goals, Expansion).
953goal_expansion(A cis_lt B, B cis_gt A).
954goal_expansion(A cis_leq B, B cis_geq A).
955goal_expansion(A cis_geq B, cis_leq_numeric(B, N)) :- nonvar(A), A = n(N).
956goal_expansion(A cis_geq B, cis_geq_numeric(A, N)) :- nonvar(B), B = n(N).
957goal_expansion(A cis_gt B, cis_lt_numeric(B, N))   :- nonvar(A), A = n(N).
958goal_expansion(A cis_gt B, cis_gt_numeric(A, N))   :- nonvar(B), B = n(N).
959
960% cis_gt only works for terms of depth 0 on both sides
961cis_gt(sup, B0) :- B0 \== sup.
962cis_gt(n(N), B) :- cis_lt_numeric(B, N).
963
964cis_lt_numeric(inf, _).
965cis_lt_numeric(n(B), A) :- B < A.
966
967cis_gt_numeric(sup, _).
968cis_gt_numeric(n(B), A) :- B > A.
969
970cis_geq(inf, inf).
971cis_geq(sup, _).
972cis_geq(n(N), B) :- cis_leq_numeric(B, N).
973
974cis_leq_numeric(inf, _).
975cis_leq_numeric(n(B), A) :- B =< A.
976
977cis_geq_numeric(sup, _).
978cis_geq_numeric(n(B), A) :- B >= A.
979
980cis_min(inf, _, inf).
981cis_min(sup, B, B).
982cis_min(n(N), B, Min) :- cis_min_(B, N, Min).
983
984cis_min_(inf, _, inf).
985cis_min_(sup, N, n(N)).
986cis_min_(n(B), A, n(M)) :- M is min(A,B).
987
988cis_max(sup, _, sup).
989cis_max(inf, B, B).
990cis_max(n(N), B, Max) :- cis_max_(B, N, Max).
991
992cis_max_(inf, N, n(N)).
993cis_max_(sup, _, sup).
994cis_max_(n(B), A, n(M)) :- M is max(A,B).
995
996cis_plus(inf, _, inf).
997cis_plus(sup, _, sup).
998cis_plus(n(A), B, Plus) :- cis_plus_(B, A, Plus).
999
1000cis_plus_(sup, _, sup).
1001cis_plus_(inf, _, inf).
1002cis_plus_(n(B), A, n(S)) :- S is A + B.
1003
1004cis_minus(inf, _, inf).
1005cis_minus(sup, _, sup).
1006cis_minus(n(A), B, M) :- cis_minus_(B, A, M).
1007
1008cis_minus_(inf, _, sup).
1009cis_minus_(sup, _, inf).
1010cis_minus_(n(B), A, n(M)) :- M is A - B.
1011
1012cis_uminus(inf, sup).
1013cis_uminus(sup, inf).
1014cis_uminus(n(A), n(B)) :- B is -A.
1015
1016cis_abs(inf, sup).
1017cis_abs(sup, sup).
1018cis_abs(n(A), n(B)) :- B is abs(A).
1019
1020cis_times(inf, B, P) :-
1021        (   B cis_lt n(0) -> P = sup
1022        ;   B cis_gt n(0) -> P = inf
1023        ;   P = n(0)
1024        ).
1025cis_times(sup, B, P) :-
1026        (   B cis_gt n(0) -> P = sup
1027        ;   B cis_lt n(0) -> P = inf
1028        ;   P = n(0)
1029        ).
1030cis_times(n(N), B, P) :- cis_times_(B, N, P).
1031
1032cis_times_(inf, A, P)     :- cis_times(inf, n(A), P).
1033cis_times_(sup, A, P)     :- cis_times(sup, n(A), P).
1034cis_times_(n(B), A, n(P)) :- P is A * B.
1035
1036cis_exp(inf, n(Y), R) :-
1037        (   even(Y) -> R = sup
1038        ;   R = inf
1039        ).
1040cis_exp(sup, _, sup).
1041cis_exp(n(N), Y, R) :- cis_exp_(Y, N, R).
1042
1043cis_exp_(n(Y), N, n(R)) :- R is N^Y.
1044cis_exp_(sup, _, sup).
1045cis_exp_(inf, _, inf).
1046
1047cis_goals(V, V)          --> { var(V) }, !.
1048cis_goals(n(N), n(N))    --> [].
1049cis_goals(inf, inf)      --> [].
1050cis_goals(sup, sup)      --> [].
1051cis_goals(sign(A0), R)   --> cis_goals(A0, A), [cis_sign(A, R)].
1052cis_goals(abs(A0), R)    --> cis_goals(A0, A), [cis_abs(A, R)].
1053cis_goals(-A0, R)        --> cis_goals(A0, A), [cis_uminus(A, R)].
1054cis_goals(A0+B0, R)      -->
1055        cis_goals(A0, A),
1056        cis_goals(B0, B),
1057        [cis_plus(A, B, R)].
1058cis_goals(A0-B0, R)      -->
1059        cis_goals(A0, A),
1060        cis_goals(B0, B),
1061        [cis_minus(A, B, R)].
1062cis_goals(min(A0,B0), R) -->
1063        cis_goals(A0, A),
1064        cis_goals(B0, B),
1065        [cis_min(A, B, R)].
1066cis_goals(max(A0,B0), R) -->
1067        cis_goals(A0, A),
1068        cis_goals(B0, B),
1069        [cis_max(A, B, R)].
1070cis_goals(A0*B0, R)      -->
1071        cis_goals(A0, A),
1072        cis_goals(B0, B),
1073        [cis_times(A, B, R)].
1074cis_goals(div(A0,B0), R) -->
1075        cis_goals(A0, A),
1076        cis_goals(B0, B),
1077        [cis_div(A, B, R)].
1078cis_goals(A0//B0, R)     -->
1079        cis_goals(A0, A),
1080        cis_goals(B0, B),
1081        [cis_slash(A, B, R)].
1082cis_goals(A0^B0, R)      -->
1083        cis_goals(A0, A),
1084        cis_goals(B0, B),
1085        [cis_exp(A, B, R)].
1086
1087list_goal([], true).
1088list_goal([G|Gs], Goal) :- foldl(list_goal_, Gs, G, Goal).
1089
1090list_goal_(G, G0, (G0,G)).
1091
1092cis_sign(sup, n(1)).
1093cis_sign(inf, n(-1)).
1094cis_sign(n(N), n(S)) :- S is sign(N).
1095
1096cis_div(sup, Y, Z)  :- ( Y cis_geq n(0) -> Z = sup ; Z = inf ).
1097cis_div(inf, Y, Z)  :- ( Y cis_geq n(0) -> Z = inf ; Z = sup ).
1098cis_div(n(X), Y, Z) :- cis_div_(Y, X, Z).
1099
1100cis_div_(sup, _, n(0)).
1101cis_div_(inf, _, n(0)).
1102cis_div_(n(Y), X, Z) :-
1103        (   Y =:= 0 -> (  X >= 0 -> Z = sup ; Z = inf )
1104        ;   Z0 is X // Y, Z = n(Z0)
1105        ).
1106
1107cis_slash(sup, _, sup).
1108cis_slash(inf, _, inf).
1109cis_slash(n(N), B, S) :- cis_slash_(B, N, S).
1110
1111cis_slash_(sup, _, n(0)).
1112cis_slash_(inf, _, n(0)).
1113cis_slash_(n(B), A, n(S)) :- S is A // B.
1114
1115
1116/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1117   A domain is a finite set of disjoint intervals. Internally, domains
1118   are represented as trees. Each node is one of:
1119
1120   empty: empty domain.
1121
1122   split(N, Left, Right)
1123      - split on integer N, with Left and Right domains whose elements are
1124        all less than and greater than N, respectively. The domain is the
1125        union of Left and Right, i.e., N is a hole.
1126
1127   from_to(From, To)
1128      - interval (From-1, To+1); From and To are bounds
1129
1130   Desiderata: rebalance domains; singleton intervals.
1131- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1132
1133/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1134   Type definition and inspection of domains.
1135- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1136
1137check_domain(D) :-
1138        (   var(D) -> instantiation_error(D)
1139        ;   is_domain(D) -> true
1140        ;   domain_error(clpfd_domain, D)
1141        ).
1142
1143is_domain(empty).
1144is_domain(from_to(From,To)) :-
1145        is_bound(From), is_bound(To),
1146        From cis_leq To.
1147is_domain(split(S, Left, Right)) :-
1148        integer(S),
1149        is_domain(Left), is_domain(Right),
1150        all_less_than(Left, S),
1151        all_greater_than(Right, S).
1152
1153all_less_than(empty, _).
1154all_less_than(from_to(From,To), S) :-
1155        From cis_lt n(S), To cis_lt n(S).
1156all_less_than(split(S0,Left,Right), S) :-
1157        S0 < S,
1158        all_less_than(Left, S),
1159        all_less_than(Right, S).
1160
1161all_greater_than(empty, _).
1162all_greater_than(from_to(From,To), S) :-
1163        From cis_gt n(S), To cis_gt n(S).
1164all_greater_than(split(S0,Left,Right), S) :-
1165        S0 > S,
1166        all_greater_than(Left, S),
1167        all_greater_than(Right, S).
1168
1169default_domain(from_to(inf,sup)).
1170
1171domain_infimum(from_to(I, _), I).
1172domain_infimum(split(_, Left, _), I) :- domain_infimum(Left, I).
1173
1174domain_supremum(from_to(_, S), S).
1175domain_supremum(split(_, _, Right), S) :- domain_supremum(Right, S).
1176
1177domain_num_elements(empty, n(0)).
1178domain_num_elements(from_to(From,To), Num) :- Num cis To - From + n(1).
1179domain_num_elements(split(_, Left, Right), Num) :-
1180        domain_num_elements(Left, NL),
1181        domain_num_elements(Right, NR),
1182        Num cis NL + NR.
1183
1184domain_direction_element(from_to(n(From), n(To)), Dir, E) :-
1185        (   Dir == up -> between(From, To, E)
1186        ;   between(From, To, E0),
1187            E is To - (E0 - From)
1188        ).
1189domain_direction_element(split(_, D1, D2), Dir, E) :-
1190        (   Dir == up ->
1191            (   domain_direction_element(D1, Dir, E)
1192            ;   domain_direction_element(D2, Dir, E)
1193            )
1194        ;   (   domain_direction_element(D2, Dir, E)
1195            ;   domain_direction_element(D1, Dir, E)
1196            )
1197        ).
1198
1199/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1200   Test whether domain contains a given integer.
1201- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1202
1203domain_contains(from_to(From,To), I) :- From cis_leq n(I), n(I) cis_leq To.
1204domain_contains(split(S, Left, Right), I) :-
1205        (   I < S -> domain_contains(Left, I)
1206        ;   I > S -> domain_contains(Right, I)
1207        ).
1208
1209/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1210   Test whether a domain contains another domain.
1211- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1212
1213domain_subdomain(Dom, Sub) :- domain_subdomain(Dom, Dom, Sub).
1214
1215domain_subdomain(from_to(_,_), Dom, Sub) :-
1216        domain_subdomain_fromto(Sub, Dom).
1217domain_subdomain(split(_, _, _), Dom, Sub) :-
1218        domain_subdomain_split(Sub, Dom, Sub).
1219
1220domain_subdomain_split(empty, _, _).
1221domain_subdomain_split(from_to(From,To), split(S,Left0,Right0), Sub) :-
1222        (   To cis_lt n(S) -> domain_subdomain(Left0, Left0, Sub)
1223        ;   From cis_gt n(S) -> domain_subdomain(Right0, Right0, Sub)
1224        ).
1225domain_subdomain_split(split(_,Left,Right), Dom, _) :-
1226        domain_subdomain(Dom, Dom, Left),
1227        domain_subdomain(Dom, Dom, Right).
1228
1229domain_subdomain_fromto(empty, _).
1230domain_subdomain_fromto(from_to(From,To), from_to(From0,To0)) :-
1231        From0 cis_leq From, To0 cis_geq To.
1232domain_subdomain_fromto(split(_,Left,Right), Dom) :-
1233        domain_subdomain_fromto(Left, Dom),
1234        domain_subdomain_fromto(Right, Dom).
1235
1236/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1237   Remove an integer from a domain. The domain is traversed until an
1238   interval is reached from which the element can be removed, or until
1239   it is clear that no such interval exists.
1240- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1241
1242domain_remove(empty, _, empty).
1243domain_remove(from_to(L0, U0), X, D) :- domain_remove_(L0, U0, X, D).
1244domain_remove(split(S, Left0, Right0), X, D) :-
1245        (   X =:= S -> D = split(S, Left0, Right0)
1246        ;   X < S ->
1247            domain_remove(Left0, X, Left1),
1248            (   Left1 == empty -> D = Right0
1249            ;   D = split(S, Left1, Right0)
1250            )
1251        ;   domain_remove(Right0, X, Right1),
1252            (   Right1 == empty -> D = Left0
1253            ;   D = split(S, Left0, Right1)
1254            )
1255        ).
1256
1257%?- domain_remove(from_to(n(0),n(5)), 3, D).
1258
1259domain_remove_(inf, U0, X, D) :-
1260        (   U0 == n(X) -> U1 is X - 1, D = from_to(inf, n(U1))
1261        ;   U0 cis_lt n(X) -> D = from_to(inf,U0)
1262        ;   L1 is X + 1, U1 is X - 1,
1263            D = split(X, from_to(inf, n(U1)), from_to(n(L1),U0))
1264        ).
1265domain_remove_(n(N), U0, X, D) :- domain_remove_upper(U0, N, X, D).
1266
1267domain_remove_upper(sup, L0, X, D) :-
1268        (   L0 =:= X -> L1 is X + 1, D = from_to(n(L1),sup)
1269        ;   L0 > X -> D = from_to(n(L0),sup)
1270        ;   L1 is X + 1, U1 is X - 1,
1271            D = split(X, from_to(n(L0),n(U1)), from_to(n(L1),sup))
1272        ).
1273domain_remove_upper(n(U0), L0, X, D) :-
1274        (   L0 =:= U0, X =:= L0 -> D = empty
1275        ;   L0 =:= X -> L1 is X + 1, D = from_to(n(L1), n(U0))
1276        ;   U0 =:= X -> U1 is X - 1, D = from_to(n(L0), n(U1))
1277        ;   between(L0, U0, X) ->
1278            U1 is X - 1, L1 is X + 1,
1279            D = split(X, from_to(n(L0), n(U1)), from_to(n(L1), n(U0)))
1280        ;   D = from_to(n(L0),n(U0))
1281        ).
1282
1283/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1284   Remove all elements greater than / less than a constant.
1285- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1286
1287domain_remove_greater_than(empty, _, empty).
1288domain_remove_greater_than(from_to(From0,To0), G, D) :-
1289        (   From0 cis_gt n(G) -> D = empty
1290        ;   To cis min(To0,n(G)), D = from_to(From0,To)
1291        ).
1292domain_remove_greater_than(split(S,Left0,Right0), G, D) :-
1293        (   S =< G ->
1294            domain_remove_greater_than(Right0, G, Right),
1295            (   Right == empty -> D = Left0
1296            ;   D = split(S, Left0, Right)
1297            )
1298        ;   domain_remove_greater_than(Left0, G, D)
1299        ).
1300
1301domain_remove_smaller_than(empty, _, empty).
1302domain_remove_smaller_than(from_to(From0,To0), V, D) :-
1303        (   To0 cis_lt n(V) -> D = empty
1304        ;   From cis max(From0,n(V)), D = from_to(From,To0)
1305        ).
1306domain_remove_smaller_than(split(S,Left0,Right0), V, D) :-
1307        (   S >= V ->
1308            domain_remove_smaller_than(Left0, V, Left),
1309            (   Left == empty -> D = Right0
1310            ;   D = split(S, Left, Right0)
1311            )
1312        ;   domain_remove_smaller_than(Right0, V, D)
1313        ).
1314
1315
1316/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1317   Remove a whole domain from another domain. (Set difference.)
1318- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1319
1320domain_subtract(Dom0, Sub, Dom) :- domain_subtract(Dom0, Dom0, Sub, Dom).
1321
1322domain_subtract(empty, _, _, empty).
1323domain_subtract(from_to(From0,To0), Dom, Sub, D) :-
1324        (   Sub == empty -> D = Dom
1325        ;   Sub = from_to(From,To) ->
1326            (   From == To -> From = n(X), domain_remove(Dom, X, D)
1327            ;   From cis_gt To0 -> D = Dom
1328            ;   To cis_lt From0 -> D = Dom
1329            ;   From cis_leq From0 ->
1330                (   To cis_geq To0 -> D = empty
1331                ;   From1 cis To + n(1),
1332                    D = from_to(From1, To0)
1333                )
1334            ;   To1 cis From - n(1),
1335                (   To cis_lt To0 ->
1336                    From = n(S),
1337                    From2 cis To + n(1),
1338                    D = split(S,from_to(From0,To1),from_to(From2,To0))
1339                ;   D = from_to(From0,To1)
1340                )
1341            )
1342        ;   Sub = split(S, Left, Right) ->
1343            (   n(S) cis_gt To0 -> domain_subtract(Dom, Dom, Left, D)
1344            ;   n(S) cis_lt From0 -> domain_subtract(Dom, Dom, Right, D)
1345            ;   domain_subtract(Dom, Dom, Left, D1),
1346                domain_subtract(D1, D1, Right, D)
1347            )
1348        ).
1349domain_subtract(split(S, Left0, Right0), _, Sub, D) :-
1350        domain_subtract(Left0, Left0, Sub, Left),
1351        domain_subtract(Right0, Right0, Sub, Right),
1352        (   Left == empty -> D = Right
1353        ;   Right == empty -> D = Left
1354        ;   D = split(S, Left, Right)
1355        ).
1356
1357/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1358   Complement of a domain
1359- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1360
1361domain_complement(D, C) :-
1362        default_domain(Default),
1363        domain_subtract(Default, D, C).
1364
1365/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1366   Convert domain to a list of disjoint intervals From-To.
1367- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1368
1369domain_intervals(D, Is) :- phrase(domain_intervals(D), Is).
1370
1371domain_intervals(split(_, Left, Right)) -->
1372        domain_intervals(Left), domain_intervals(Right).
1373domain_intervals(empty)                 --> [].
1374domain_intervals(from_to(From,To))      --> [From-To].
1375
1376/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1377   To compute the intersection of two domains D1 and D2, we choose D1
1378   as the reference domain. For each interval of D1, we compute how
1379   far and to which values D2 lets us extend it.
1380- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1381
1382domains_intersection(D1, D2, Intersection) :-
1383        domains_intersection_(D1, D2, Intersection),
1384        Intersection \== empty.
1385
1386domains_intersection_(empty, _, empty).
1387domains_intersection_(from_to(L0,U0), D2, Dom) :-
1388        narrow(D2, L0, U0, Dom).
1389domains_intersection_(split(S,Left0,Right0), D2, Dom) :-
1390        domains_intersection_(Left0, D2, Left1),
1391        domains_intersection_(Right0, D2, Right1),
1392        (   Left1 == empty -> Dom = Right1
1393        ;   Right1 == empty -> Dom = Left1
1394        ;   Dom = split(S, Left1, Right1)
1395        ).
1396
1397narrow(empty, _, _, empty).
1398narrow(from_to(L0,U0), From0, To0, Dom) :-
1399        From1 cis max(From0,L0), To1 cis min(To0,U0),
1400        (   From1 cis_gt To1 -> Dom = empty
1401        ;   Dom = from_to(From1,To1)
1402        ).
1403narrow(split(S, Left0, Right0), From0, To0, Dom) :-
1404        (   To0 cis_lt n(S) -> narrow(Left0, From0, To0, Dom)
1405        ;   From0 cis_gt n(S) -> narrow(Right0, From0, To0, Dom)
1406        ;   narrow(Left0, From0, To0, Left1),
1407            narrow(Right0, From0, To0, Right1),
1408            (   Left1 == empty -> Dom = Right1
1409            ;   Right1 == empty -> Dom = Left1
1410            ;   Dom = split(S, Left1, Right1)
1411            )
1412        ).
1413
1414/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1415   Union of 2 domains.
1416- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1417
1418domains_union(D1, D2, Union) :-
1419        domain_intervals(D1, Is1),
1420        domain_intervals(D2, Is2),
1421        append(Is1, Is2, IsU0),
1422        merge_intervals(IsU0, IsU1),
1423        intervals_to_domain(IsU1, Union).
1424
1425/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1426   Shift the domain by an offset.
1427- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1428
1429domain_shift(empty, _, empty).
1430domain_shift(from_to(From0,To0), O, from_to(From,To)) :-
1431        From cis From0 + n(O), To cis To0 + n(O).
1432domain_shift(split(S0, Left0, Right0), O, split(S, Left, Right)) :-
1433        S is S0 + O,
1434        domain_shift(Left0, O, Left),
1435        domain_shift(Right0, O, Right).
1436
1437/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1438   The new domain contains all values of the old domain,
1439   multiplied by a constant multiplier.
1440- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1441
1442domain_expand(D0, M, D) :-
1443        (   M < 0 ->
1444            domain_negate(D0, D1),
1445            M1 is abs(M),
1446            domain_expand_(D1, M1, D)
1447        ;   M =:= 1 -> D = D0
1448        ;   domain_expand_(D0, M, D)
1449        ).
1450
1451domain_expand_(empty, _, empty).
1452domain_expand_(from_to(From0, To0), M, from_to(From,To)) :-
1453        From cis From0*n(M),
1454        To cis To0*n(M).
1455domain_expand_(split(S0, Left0, Right0), M, split(S, Left, Right)) :-
1456        S is M*S0,
1457        domain_expand_(Left0, M, Left),
1458        domain_expand_(Right0, M, Right).
1459
1460/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1461   similar to domain_expand/3, tailored for truncated division: an
1462   interval [From,To] is extended to [From*M, ((To+1)*M - 1)], i.e.,
1463   to all values that truncated integer-divided by M yield a value
1464   from interval.
1465- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1466
1467domain_expand_more(D0, M, D) :-
1468        %format("expanding ~w by ~w\n", [D0,M]),
1469        (   M < 0 -> domain_negate(D0, D1), M1 is abs(M)
1470        ;   D1 = D0, M1 = M
1471        ),
1472        domain_expand_more_(D1, M1, D).
1473        %format("yield: ~w\n", [D]).
1474
1475domain_expand_more_(empty, _, empty).
1476domain_expand_more_(from_to(From0, To0), M, from_to(From,To)) :-
1477        (   From0 cis_leq n(0) ->
1478            From cis (From0-n(1))*n(M) + n(1)
1479        ;   From cis From0*n(M)
1480        ),
1481        (   To0 cis_lt n(0) ->
1482            To cis To0*n(M)
1483        ;   To cis (To0+n(1))*n(M) - n(1)
1484        ).
1485domain_expand_more_(split(S0, Left0, Right0), M, split(S, Left, Right)) :-
1486        S is M*S0,
1487        domain_expand_more_(Left0, M, Left),
1488        domain_expand_more_(Right0, M, Right).
1489
1490/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1491   Scale a domain down by a constant multiplier. Assuming (//)/2.
1492- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1493
1494domain_contract(D0, M, D) :-
1495        %format("contracting ~w by ~w\n", [D0,M]),
1496        (   M < 0 -> domain_negate(D0, D1), M1 is abs(M)
1497        ;   D1 = D0, M1 = M
1498        ),
1499        domain_contract_(D1, M1, D).
1500
1501domain_contract_(empty, _, empty).
1502domain_contract_(from_to(From0, To0), M, from_to(From,To)) :-
1503        (   From0 cis_geq n(0) ->
1504            From cis (From0 + n(M) - n(1)) // n(M)
1505        ;   From cis From0 // n(M)
1506        ),
1507        (   To0 cis_geq n(0) ->
1508            To cis To0 // n(M)
1509        ;   To cis (To0 - n(M) + n(1)) // n(M)
1510        ).
1511domain_contract_(split(_,Left0,Right0), M, D) :-
1512        %  Scaled down domains do not necessarily retain any holes of
1513        %  the original domain.
1514        domain_contract_(Left0, M, Left),
1515        domain_contract_(Right0, M, Right),
1516        domains_union(Left, Right, D).
1517
1518/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1519   Similar to domain_contract, tailored for division, i.e.,
1520   {21,23} contracted by 4 is 5. It contracts "less".
1521- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1522
1523domain_contract_less(D0, M, D) :-
1524        (   M < 0 -> domain_negate(D0, D1), M1 is abs(M)
1525        ;   D1 = D0, M1 = M
1526        ),
1527        domain_contract_less_(D1, M1, D).
1528
1529domain_contract_less_(empty, _, empty).
1530domain_contract_less_(from_to(From0, To0), M, from_to(From,To)) :-
1531        From cis From0 // n(M), To cis To0 // n(M).
1532domain_contract_less_(split(_,Left0,Right0), M, D) :-
1533        %  Scaled down domains do not necessarily retain any holes of
1534        %  the original domain.
1535        domain_contract_less_(Left0, M, Left),
1536        domain_contract_less_(Right0, M, Right),
1537        domains_union(Left, Right, D).
1538
1539/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1540   Negate the domain. Left and Right sub-domains and bounds switch sides.
1541- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1542
1543domain_negate(empty, empty).
1544domain_negate(from_to(From0, To0), from_to(From, To)) :-
1545        From cis -To0, To cis -From0.
1546domain_negate(split(S0, Left0, Right0), split(S, Left, Right)) :-
1547        S is -S0,
1548        domain_negate(Left0, Right),
1549        domain_negate(Right0, Left).
1550
1551/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1552   Construct a domain from a list of integers. Try to balance it.
1553- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1554
1555list_to_disjoint_intervals([], []).
1556list_to_disjoint_intervals([N|Ns], Is) :-
1557        list_to_disjoint_intervals(Ns, N, N, Is).
1558
1559list_to_disjoint_intervals([], M, N, [n(M)-n(N)]).
1560list_to_disjoint_intervals([B|Bs], M, N, Is) :-
1561        (   B =:= N + 1 ->
1562            list_to_disjoint_intervals(Bs, M, B, Is)
1563        ;   Is = [n(M)-n(N)|Rest],
1564            list_to_disjoint_intervals(Bs, B, B, Rest)
1565        ).
1566
1567list_to_domain(List0, D) :-
1568        (   List0 == [] -> D = empty
1569        ;   sort(List0, List),
1570            list_to_disjoint_intervals(List, Is),
1571            intervals_to_domain(Is, D)
1572        ).
1573
1574intervals_to_domain([], empty) :- !.
1575intervals_to_domain([M-N], from_to(M,N)) :- !.
1576intervals_to_domain(Is, D) :-
1577        length(Is, L),
1578        FL is L // 2,
1579        length(Front, FL),
1580        append(Front, Tail, Is),
1581        Tail = [n(Start)-_|_],
1582        Hole is Start - 1,
1583        intervals_to_domain(Front, Left),
1584        intervals_to_domain(Tail, Right),
1585        D = split(Hole, Left, Right).
1586
1587%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1588
1589
1590%% ?Var in +Domain
1591%
1592%  Var is an element of Domain. Domain is one of:
1593%
1594%         * Integer
1595%           Singleton set consisting only of _Integer_.
1596%         * Lower..Upper
1597%           All integers _I_ such that _Lower_ =< _I_ =< _Upper_.
1598%           _Lower_ must be an integer or the atom *inf*, which
1599%           denotes negative infinity. _Upper_ must be an integer or
1600%           the atom *sup*, which denotes positive infinity.
1601%         * Domain1 \/ Domain2
1602%           The union of Domain1 and Domain2.
1603
1604Var in Dom :- clpfd_in(Var, Dom).
1605
1606clpfd_in(V, D) :-
1607        fd_variable(V),
1608        drep_to_domain(D, Dom),
1609        domain(V, Dom).
1610
1611fd_variable(V) :-
1612        (   var(V) -> true
1613        ;   integer(V) -> true
1614        ;   type_error(integer, V)
1615        ).
1616
1617%% +Vars ins +Domain
1618%
1619%  The variables in the list Vars are elements of Domain. See in/2 for
1620%  the syntax of Domain.
1621
1622Vs ins D :-
1623        fd_must_be_list(Vs),
1624        maplist(fd_variable, Vs),
1625        drep_to_domain(D, Dom),
1626        domains(Vs, Dom).
1627
1628fd_must_be_list(Ls) :-
1629        (   fd_var(Ls) -> type_error(list, Ls)
1630        ;   must_be(list, Ls)
1631        ).
1632
1633%% indomain(?Var)
1634%
1635% Bind Var to all feasible values of its domain on backtracking. The
1636% domain of Var must be finite.
1637
1638indomain(Var) :- label([Var]).
1639
1640order_dom_next(up, Dom, Next)   :- domain_infimum(Dom, n(Next)).
1641order_dom_next(down, Dom, Next) :- domain_supremum(Dom, n(Next)).
1642order_dom_next(random_value(_), Dom, Next) :-
1643        phrase(domain_to_intervals(Dom), Is),
1644        length(Is, L),
1645        R is random(L),
1646        nth0(R, Is, From-To),
1647        random_between(From, To, Next).
1648
1649domain_to_intervals(from_to(n(From),n(To))) --> [From-To].
1650domain_to_intervals(split(_, Left, Right)) -->
1651        domain_to_intervals(Left),
1652        domain_to_intervals(Right).
1653
1654%% label(+Vars)
1655%
1656% Equivalent to labeling([], Vars). See labeling/2.
1657
1658label(Vs) :- labeling([], Vs).
1659
1660%% labeling(+Options, +Vars)
1661%
1662% Assign a value to each variable in Vars. Labeling means systematically
1663% trying out values for the finite domain   variables  Vars until all of
1664% them are ground. The domain of each   variable in Vars must be finite.
1665% Options is a list of options that   let  you exhibit some control over
1666% the search process. Several categories of options exist:
1667%
1668% The variable selection strategy lets you specify which variable of
1669% Vars is labeled next and is one of:
1670%
1671%   * leftmost
1672%   Label the variables in the order they occur in Vars. This is the
1673%   default.
1674%
1675%   * ff
1676%   _|First fail|_. Label the leftmost variable with smallest domain next,
1677%   in order to detect infeasibility early. This is often a good
1678%   strategy.
1679%
1680%   * ffc
1681%   Of the variables with smallest domains, the leftmost one
1682%   participating in most constraints is labeled next.
1683%
1684%   * min
1685%   Label the leftmost variable whose lower bound is the lowest next.
1686%
1687%   * max
1688%   Label the leftmost variable whose upper bound is the highest next.
1689%
1690% The value order is one of:
1691%
1692%   * up
1693%   Try the elements of the chosen variable's domain in ascending order.
1694%   This is the default.
1695%
1696%   * down
1697%   Try the domain elements in descending order.
1698%
1699% The branching strategy is one of:
1700%
1701%   * step
1702%   For each variable X, a choice is made between X = V and X #\= V,
1703%   where V is determined by the value ordering options. This is the
1704%   default.
1705%
1706%   * enum
1707%   For each variable X, a choice is made between X = V_1, X = V_2
1708%   etc., for all values V_i of the domain of X. The order is
1709%   determined by the value ordering options.
1710%
1711%   * bisect
1712%   For each variable X, a choice is made between X #=< M and X #> M,
1713%   where M is the midpoint of the domain of X.
1714%
1715% At most one option of each category can be specified, and an option
1716% must not occur repeatedly.
1717%
1718% The order of solutions can be influenced with:
1719%
1720%   * min(Expr)
1721%   * max(Expr)
1722%
1723% This generates solutions in ascending/descending order with respect
1724% to the evaluation of the arithmetic expression Expr. Labeling Vars
1725% must make Expr ground. If several such options are specified, they
1726% are interpreted from left to right, e.g.:
1727%
1728% ==
1729% ?- [X,Y] ins 10..20, labeling([max(X),min(Y)],[X,Y]).
1730% ==
1731%
1732% This generates solutions in descending order of X, and for each
1733% binding of X, solutions are generated in ascending order of Y. To
1734% obtain the incomplete behaviour that other systems exhibit with
1735% "maximize(Expr)" and "minimize(Expr)", use once/1, e.g.:
1736%
1737% ==
1738% once(labeling([max(Expr)], Vars))
1739% ==
1740%
1741% Labeling is always complete, always terminates, and yields no
1742% redundant solutions. See [core relations and
1743% search](<#clpfd-search>) for usage advice.
1744
1745labeling(Options, Vars) :-
1746        must_be(list, Options),
1747        fd_must_be_list(Vars),
1748        maplist(must_be_finite_fdvar, Vars),
1749        label(Options, Options, default(leftmost), default(up), default(step), [], upto_ground, Vars).
1750
1751finite_domain(Dom) :-
1752        domain_infimum(Dom, n(_)),
1753        domain_supremum(Dom, n(_)).
1754
1755must_be_finite_fdvar(Var) :-
1756        (   fd_get(Var, Dom, _) ->
1757            (   finite_domain(Dom) -> true
1758            ;   instantiation_error(Var)
1759            )
1760        ;   integer(Var) -> true
1761        ;   must_be(integer, Var)
1762        ).
1763
1764
1765label([O|Os], Options, Selection, Order, Choice, Optim, Consistency, Vars) :-
1766        (   var(O)-> instantiation_error(O)
1767        ;   override(selection, Selection, O, Options, S1) ->
1768            label(Os, Options, S1, Order, Choice, Optim, Consistency, Vars)
1769        ;   override(order, Order, O, Options, O1) ->
1770            label(Os, Options, Selection, O1, Choice, Optim, Consistency, Vars)
1771        ;   override(choice, Choice, O, Options, C1) ->
1772            label(Os, Options, Selection, Order, C1, Optim, Consistency, Vars)
1773        ;   optimisation(O) ->
1774            label(Os, Options, Selection, Order, Choice, [O|Optim], Consistency, Vars)
1775        ;   consistency(O, O1) ->
1776            label(Os, Options, Selection, Order, Choice, Optim, O1, Vars)
1777        ;   domain_error(labeling_option, O)
1778        ).
1779label([], _, Selection, Order, Choice, Optim0, Consistency, Vars) :-
1780        maplist(arg(1), [Selection,Order,Choice], [S,O,C]),
1781        (   Optim0 == [] ->
1782            label(Vars, S, O, C, Consistency)
1783        ;   reverse(Optim0, Optim),
1784            exprs_singlevars(Optim, SVs),
1785            optimise(Vars, [S,O,C], SVs)
1786        ).
1787
1788% Introduce new variables for each min/max expression to avoid
1789% reparsing expressions during optimisation.
1790
1791exprs_singlevars([], []).
1792exprs_singlevars([E|Es], [SV|SVs]) :-
1793        E =.. [F,Expr],
1794        ?(Single) #= Expr,
1795        SV =.. [F,Single],
1796        exprs_singlevars(Es, SVs).
1797
1798all_dead(fd_props(Bs,Gs,Os)) :-
1799        all_dead_(Bs),
1800        all_dead_(Gs),
1801        all_dead_(Os).
1802
1803all_dead_([]).
1804all_dead_([propagator(_, S)|Ps]) :- S == dead, all_dead_(Ps).
1805
1806label([], _, _, _, Consistency) :- !,
1807        (   Consistency = upto_in(I0,I) -> I0 = I
1808        ;   true
1809        ).
1810label(Vars, Selection, Order, Choice, Consistency) :-
1811        (   Vars = [V|Vs], nonvar(V) -> label(Vs, Selection, Order, Choice, Consistency)
1812        ;   select_var(Selection, Vars, Var, RVars),
1813            (   var(Var) ->
1814                (   Consistency = upto_in(I0,I), fd_get(Var, _, Ps), all_dead(Ps) ->
1815                    fd_size(Var, Size),
1816                    I1 is I0*Size,
1817                    label(RVars, Selection, Order, Choice, upto_in(I1,I))
1818                ;   Consistency = upto_in, fd_get(Var, _, Ps), all_dead(Ps) ->
1819                    label(RVars, Selection, Order, Choice, Consistency)
1820                ;   choice_order_variable(Choice, Order, Var, RVars, Vars, Selection, Consistency)
1821                )
1822            ;   label(RVars, Selection, Order, Choice, Consistency)
1823            )
1824        ).
1825
1826choice_order_variable(step, Order, Var, Vars, Vars0, Selection, Consistency) :-
1827        fd_get(Var, Dom, _),
1828        order_dom_next(Order, Dom, Next),
1829        (   Var = Next,
1830            label(Vars, Selection, Order, step, Consistency)
1831        ;   neq_num(Var, Next),
1832            do_queue,
1833            label(Vars0, Selection, Order, step, Consistency)
1834        ).
1835choice_order_variable(enum, Order, Var, Vars, _, Selection, Consistency) :-
1836        fd_get(Var, Dom0, _),
1837        domain_direction_element(Dom0, Order, Var),
1838        label(Vars, Selection, Order, enum, Consistency).
1839choice_order_variable(bisect, Order, Var, _, Vars0, Selection, Consistency) :-
1840        fd_get(Var, Dom, _),
1841        domain_infimum(Dom, n(I)),
1842        domain_supremum(Dom, n(S)),
1843        Mid0 is (I + S) // 2,
1844        (   Mid0 =:= S -> Mid is Mid0 - 1 ; Mid = Mid0 ),
1845        (   Order == up -> ( Var #=< Mid ; Var #> Mid )
1846        ;   Order == down -> ( Var #> Mid ; Var #=< Mid )
1847        ;   domain_error(bisect_up_or_down, Order)
1848        ),
1849        label(Vars0, Selection, Order, bisect, Consistency).
1850
1851override(What, Prev, Value, Options, Result) :-
1852        call(What, Value),
1853        override_(Prev, Value, Options, Result).
1854
1855override_(default(_), Value, _, user(Value)).
1856override_(user(Prev), Value, Options, _) :-
1857        (   Value == Prev ->
1858            domain_error(nonrepeating_labeling_options, Options)
1859        ;   domain_error(consistent_labeling_options, Options)
1860        ).
1861
1862selection(ff).
1863selection(ffc).
1864selection(min).
1865selection(max).
1866selection(leftmost).
1867selection(random_variable(Seed)) :-
1868        must_be(integer, Seed),
1869        set_random(seed(Seed)).
1870
1871choice(step).
1872choice(enum).
1873choice(bisect).
1874
1875order(up).
1876order(down).
1877% TODO: random_variable and random_value currently both set the seed,
1878% so exchanging the options can yield different results.
1879order(random_value(Seed)) :-
1880        must_be(integer, Seed),
1881        set_random(seed(Seed)).
1882
1883consistency(upto_in(I), upto_in(1, I)).
1884consistency(upto_in, upto_in).
1885consistency(upto_ground, upto_ground).
1886
1887optimisation(min(_)).
1888optimisation(max(_)).
1889
1890select_var(leftmost, [Var|Vars], Var, Vars).
1891select_var(min, [V|Vs], Var, RVars) :-
1892        find_min(Vs, V, Var),
1893        delete_eq([V|Vs], Var, RVars).
1894select_var(max, [V|Vs], Var, RVars) :-
1895        find_max(Vs, V, Var),
1896        delete_eq([V|Vs], Var, RVars).
1897select_var(ff, [V|Vs], Var, RVars) :-
1898        fd_size_(V, n(S)),
1899        find_ff(Vs, V, S, Var),
1900        delete_eq([V|Vs], Var, RVars).
1901select_var(ffc, [V|Vs], Var, RVars) :-
1902        find_ffc(Vs, V, Var),
1903        delete_eq([V|Vs], Var, RVars).
1904select_var(random_variable(_), Vars0, Var, Vars) :-
1905        length(Vars0, L),
1906        I is random(L),
1907        nth0(I, Vars0, Var),
1908        delete_eq(Vars0, Var, Vars).
1909
1910find_min([], Var, Var).
1911find_min([V|Vs], CM, Min) :-
1912        (   min_lt(V, CM) ->
1913            find_min(Vs, V, Min)
1914        ;   find_min(Vs, CM, Min)
1915        ).
1916
1917find_max([], Var, Var).
1918find_max([V|Vs], CM, Max) :-
1919        (   max_gt(V, CM) ->
1920            find_max(Vs, V, Max)
1921        ;   find_max(Vs, CM, Max)
1922        ).
1923
1924find_ff([], Var, _, Var).
1925find_ff([V|Vs], CM, S0, FF) :-
1926        (   nonvar(V) -> find_ff(Vs, CM, S0, FF)
1927        ;   (   fd_size_(V, n(S1)), S1 < S0 ->
1928                find_ff(Vs, V, S1, FF)
1929            ;   find_ff(Vs, CM, S0, FF)
1930            )
1931        ).
1932
1933find_ffc([], Var, Var).
1934find_ffc([V|Vs], Prev, FFC) :-
1935        (   ffc_lt(V, Prev) ->
1936            find_ffc(Vs, V, FFC)
1937        ;   find_ffc(Vs, Prev, FFC)
1938        ).
1939
1940
1941ffc_lt(X, Y) :-
1942        (   fd_get(X, XD, XPs) ->
1943            domain_num_elements(XD, n(NXD))
1944        ;   NXD = 1, XPs = []
1945        ),
1946        (   fd_get(Y, YD, YPs) ->
1947            domain_num_elements(YD, n(NYD))
1948        ;   NYD = 1, YPs = []
1949        ),
1950        (   NXD < NYD -> true
1951        ;   NXD =:= NYD,
1952            props_number(XPs, NXPs),
1953            props_number(YPs, NYPs),
1954            NXPs > NYPs
1955        ).
1956
1957min_lt(X,Y) :- bounds(X,LX,_), bounds(Y,LY,_), LX < LY.
1958
1959max_gt(X,Y) :- bounds(X,_,UX), bounds(Y,_,UY), UX > UY.
1960
1961bounds(X, L, U) :-
1962        (   fd_get(X, Dom, _) ->
1963            domain_infimum(Dom, n(L)),
1964            domain_supremum(Dom, n(U))
1965        ;   L = X, U = L
1966        ).
1967
1968delete_eq([], _, []).
1969delete_eq([X|Xs], Y, List) :-
1970        (   nonvar(X) -> delete_eq(Xs, Y, List)
1971        ;   X == Y -> List = Xs
1972        ;   List = [X|Tail],
1973            delete_eq(Xs, Y, Tail)
1974        ).
1975
1976/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1977   contracting/1 -- subject to change
1978
1979   This can remove additional domain elements from the boundaries.
1980- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1981
1982contracting(Vs) :-
1983        must_be(list, Vs),
1984        maplist(must_be_finite_fdvar, Vs),
1985        contracting(Vs, false, Vs).
1986
1987contracting([], Repeat, Vars) :-
1988        (   Repeat -> contracting(Vars, false, Vars)
1989        ;   true
1990        ).
1991contracting([V|Vs], Repeat, Vars) :-
1992        fd_inf(V, Min),
1993        (   \+ \+ (V = Min) ->
1994            fd_sup(V, Max),
1995            (   \+ \+ (V = Max) ->
1996                contracting(Vs, Repeat, Vars)
1997            ;   V #\= Max,
1998                contracting(Vs, true, Vars)
1999            )
2000        ;   V #\= Min,
2001            contracting(Vs, true, Vars)
2002        ).
2003
2004/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2005   fds_sespsize(Vs, S).
2006
2007   S is an upper bound on the search space size with respect to finite
2008   domain variables Vs.
2009- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2010
2011fds_sespsize(Vs, S) :-
2012        must_be(list, Vs),
2013        maplist(fd_variable, Vs),
2014        fds_sespsize(Vs, n(1), S1),
2015        bound_portray(S1, S).
2016
2017fd_size_(V, S) :-
2018        (   fd_get(V, D, _) ->
2019            domain_num_elements(D, S)
2020        ;   S = n(1)
2021        ).
2022
2023fds_sespsize([], S, S).
2024fds_sespsize([V|Vs], S0, S) :-
2025        fd_size_(V, S1),
2026        S2 cis S0*S1,
2027        fds_sespsize(Vs, S2, S).
2028
2029/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2030   Optimisation uses destructive assignment to save the computed
2031   extremum over backtracking. Failure is used to get rid of copies of
2032   attributed variables that are created in intermediate steps. At
2033   least that's the intention - it currently doesn't work in SWI:
2034
2035   %?- X in 0..3, call_residue_vars(labeling([min(X)], [X]), Vs).
2036   %@ X = 0,
2037   %@ Vs = [_G6174, _G6177],
2038   %@ _G6174 in 0..3
2039
2040- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2041
2042optimise(Vars, Options, Whats) :-
2043        Whats = [What|WhatsRest],
2044        Extremum = extremum(none),
2045        (   catch(store_extremum(Vars, Options, What, Extremum),
2046                  time_limit_exceeded,
2047                  false)
2048        ;   Extremum = extremum(n(Val)),
2049            arg(1, What, Expr),
2050            append(WhatsRest, Options, Options1),
2051            (   Expr #= Val,
2052                labeling(Options1, Vars)
2053            ;   Expr #\= Val,
2054                optimise(Vars, Options, Whats)
2055            )
2056        ).
2057
2058store_extremum(Vars, Options, What, Extremum) :-
2059        catch((labeling(Options, Vars), throw(w(What))), w(What1), true),
2060        functor(What, Direction, _),
2061        maplist(arg(1), [What,What1], [Expr,Expr1]),
2062        optimise(Direction, Options, Vars, Expr1, Expr, Extremum).
2063
2064optimise(Direction, Options, Vars, Expr0, Expr, Extremum) :-
2065        must_be(ground, Expr0),
2066        nb_setarg(1, Extremum, n(Expr0)),
2067        catch((tighten(Direction, Expr, Expr0),
2068               labeling(Options, Vars),
2069               throw(v(Expr))), v(Expr1), true),
2070        optimise(Direction, Options, Vars, Expr1, Expr, Extremum).
2071
2072tighten(min, E, V) :- E #< V.
2073tighten(max, E, V) :- E #> V.
2074
2075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2076
2077%% all_different(+Vars)
2078%
2079% Like all_distinct/1, but with weaker propagation. Consider using
2080% all_distinct/1 instead, since all_distinct/1 is typically acceptably
2081% efficient and propagates much more strongly.
2082
2083all_different(Ls) :-
2084        fd_must_be_list(Ls),
2085        maplist(fd_variable, Ls),
2086        Orig = original_goal(_, all_different(Ls)),
2087        all_different(Ls, [], Orig),
2088        do_queue.
2089
2090all_different([], _, _).
2091all_different([X|Right], Left, Orig) :-
2092        (   var(X) ->
2093            make_propagator(pdifferent(Left,Right,X,Orig), Prop),
2094            init_propagator(X, Prop),
2095            trigger_prop(Prop)
2096        ;   exclude_fire(Left, Right, X)
2097        ),
2098        all_different(Right, [X|Left], Orig).
2099
2100%% all_distinct(+Vars).
2101%
2102%  True iff Vars are pairwise distinct. For example, all_distinct/1
2103%  can detect that not all variables can assume distinct values given
2104%  the following domains:
2105%
2106%  ==
2107%  ?- maplist(in, Vs,
2108%             [1\/3..4, 1..2\/4, 1..2\/4, 1..3, 1..3, 1..6]),
2109%     all_distinct(Vs).
2110%  false.
2111%  ==
2112
2113all_distinct(Ls) :-
2114        fd_must_be_list(Ls),
2115        maplist(fd_variable, Ls),
2116        make_propagator(pdistinct(Ls), Prop),
2117        distinct_attach(Ls, Prop, []),
2118        trigger_once(Prop).
2119
2120%% sum(+Vars, +Rel, ?Expr)
2121%
2122% The sum of elements of the list Vars is in relation Rel to Expr.
2123% Rel is one of #=, #\=, #<, #>, #=< or #>=. For example:
2124%
2125% ==
2126% ?- [A,B,C] ins 0..sup, sum([A,B,C], #=, 100).
2127% A in 0..100,
2128% A+B+C#=100,
2129% B in 0..100,
2130% C in 0..100.
2131% ==
2132
2133sum(Vs, Op, Value) :-
2134        must_be(list, Vs),
2135        same_length(Vs, Ones),
2136        maplist(=(1), Ones),
2137        scalar_product(Ones, Vs, Op, Value).
2138
2139%% scalar_product(+Cs, +Vs, +Rel, ?Expr)
2140%
2141% True iff the scalar product of Cs and Vs is in relation Rel to Expr.
2142% Cs is a list of integers, Vs is a list of variables and integers.
2143% Rel is #=, #\=, #<, #>, #=< or #>=.
2144
2145scalar_product(Cs, Vs, Op, Value) :-
2146        must_be(list(integer), Cs),
2147        must_be(list, Vs),
2148        maplist(fd_variable, Vs),
2149        (   Op = (#=), single_value(Value, Right), ground(Vs) ->
2150            foldl(coeff_int_linsum, Cs, Vs, 0, Right)
2151        ;   must_be(callable, Op),
2152            (   memberchk(Op, [#=,#\=,#<,#>,#=<,#>=]) -> true
2153            ;   domain_error(scalar_product_relation, Op)
2154            ),
2155            must_be(acyclic, Value),
2156            foldl(coeff_var_plusterm, Cs, Vs, 0, Left),
2157            (   left_right_linsum_const(Left, Value, Cs1, Vs1, Const) ->
2158                scalar_product_(Op, Cs1, Vs1, Const)
2159            ;   sum(Cs, Vs, 0, Op, Value)
2160            )
2161        ).
2162
2163single_value(V, V)    :- var(V), !, non_monotonic(V).
2164single_value(V, V)    :- integer(V).
2165single_value(?(V), V) :- fd_variable(V).
2166
2167coeff_var_plusterm(C, V, T0, T0+(C* ?(V))).
2168
2169coeff_int_linsum(C, I, S0, S) :- S is S0 + C*I.
2170
2171sum([], _, Sum, Op, Value) :- call(Op, Sum, Value).
2172sum([C|Cs], [X|Xs], Acc, Op, Value) :-
2173        ?(NAcc) #= Acc + C* ?(X),
2174        sum(Cs, Xs, NAcc, Op, Value).
2175
2176multiples([], [], _).
2177multiples([C|Cs], [V|Vs], Left) :-
2178        (   (   Cs = [N|_] ; Left = [N|_] ) ->
2179            (   N =\= 1, gcd(C,N) =:= 1 ->
2180                gcd(Cs, N, GCD0),
2181                gcd(Left, GCD0, GCD),
2182                (   GCD > 1 -> ?(V) #= GCD * ?(_)
2183                ;   true
2184                )
2185            ;   true
2186            )
2187        ;   true
2188        ),
2189        multiples(Cs, Vs, [C|Left]).
2190
2191abs(N, A) :- A is abs(N).
2192
2193divide(D, N, R) :- R is N // D.
2194
2195scalar_product_(#=, Cs0, Vs, S0) :-
2196        (   Cs0 = [C|Rest] ->
2197            gcd(Rest, C, GCD),
2198            S0 mod GCD =:= 0,
2199            maplist(divide(GCD), [S0|Cs0], [S|Cs])
2200        ;   S0 =:= 0, S = S0, Cs = Cs0
2201        ),
2202        (   S0 =:= 0 ->
2203            maplist(abs, Cs, As),
2204            multiples(As, Vs, [])
2205        ;   true
2206        ),
2207        propagator_init_trigger(Vs, scalar_product_eq(Cs, Vs, S)).
2208scalar_product_(#\=, Cs, Vs, C) :-
2209        propagator_init_trigger(Vs, scalar_product_neq(Cs, Vs, C)).
2210scalar_product_(#=<, Cs, Vs, C) :-
2211        propagator_init_trigger(Vs, scalar_product_leq(Cs, Vs, C)).
2212scalar_product_(#<, Cs, Vs, C) :-
2213        C1 is C - 1,
2214        scalar_product_(#=<, Cs, Vs, C1).
2215scalar_product_(#>, Cs, Vs, C) :-
2216        C1 is C + 1,
2217        scalar_product_(#>=, Cs, Vs, C1).
2218scalar_product_(#>=, Cs, Vs, C) :-
2219        maplist(negative, Cs, Cs1),
2220        C1 is -C,
2221        scalar_product_(#=<, Cs1, Vs, C1).
2222
2223negative(X0, X) :- X is -X0.
2224
2225coeffs_variables_const([], [], [], [], I, I).
2226coeffs_variables_const([C|Cs], [V|Vs], Cs1, Vs1, I0, I) :-
2227        (   var(V) ->
2228            Cs1 = [C|CRest], Vs1 = [V|VRest], I1 = I0
2229        ;   I1 is I0 + C*V,
2230            Cs1 = CRest, Vs1 = VRest
2231        ),
2232        coeffs_variables_const(Cs, Vs, CRest, VRest, I1, I).
2233
2234sum_finite_domains([], [], [], [], Inf, Sup, Inf, Sup).
2235sum_finite_domains([C|Cs], [V|Vs], Infs, Sups, Inf0, Sup0, Inf, Sup) :-
2236        fd_get(V, _, Inf1, Sup1, _),
2237        (   Inf1 = n(NInf) ->
2238            (   C < 0 ->
2239                Sup2 is Sup0 + C*NInf
2240            ;   Inf2 is Inf0 + C*NInf
2241            ),
2242            Sups = Sups1,
2243            Infs = Infs1
2244        ;   (   C < 0 ->
2245                Sup2 = Sup0,
2246                Sups = [C*V|Sups1],
2247                Infs = Infs1
2248            ;   Inf2 = Inf0,
2249                Infs = [C*V|Infs1],
2250                Sups = Sups1
2251            )
2252        ),
2253        (   Sup1 = n(NSup) ->
2254            (   C < 0 ->
2255                Inf2 is Inf0 + C*NSup
2256            ;   Sup2 is Sup0 + C*NSup
2257            ),
2258            Sups1 = Sups2,
2259            Infs1 = Infs2
2260        ;   (   C < 0 ->
2261                Inf2 = Inf0,
2262                Infs1 = [C*V|Infs2],
2263                Sups1 = Sups2
2264            ;   Sup2 = Sup0,
2265                Sups1 = [C*V|Sups2],
2266                Infs1 = Infs2
2267            )
2268        ),
2269        sum_finite_domains(Cs, Vs, Infs2, Sups2, Inf2, Sup2, Inf, Sup).
2270
2271remove_dist_upper_lower([], _, _, _).
2272remove_dist_upper_lower([C|Cs], [V|Vs], D1, D2) :-
2273        (   fd_get(V, VD, VPs) ->
2274            (   C < 0 ->
2275                domain_supremum(VD, n(Sup)),
2276                L is Sup + D1//C,
2277                domain_remove_smaller_than(VD, L, VD1),
2278                domain_infimum(VD1, n(Inf)),
2279                G is Inf - D2//C,
2280                domain_remove_greater_than(VD1, G, VD2)
2281            ;   domain_infimum(VD, n(Inf)),
2282                G is Inf + D1//C,
2283                domain_remove_greater_than(VD, G, VD1),
2284                domain_supremum(VD1, n(Sup)),
2285                L is Sup - D2//C,
2286                domain_remove_smaller_than(VD1, L, VD2)
2287            ),
2288            fd_put(V, VD2, VPs)
2289        ;   true
2290        ),
2291        remove_dist_upper_lower(Cs, Vs, D1, D2).
2292
2293
2294remove_dist_upper_leq([], _, _).
2295remove_dist_upper_leq([C|Cs], [V|Vs], D1) :-
2296        (   fd_get(V, VD, VPs) ->
2297            (   C < 0 ->
2298                domain_supremum(VD, n(Sup)),
2299                L is Sup + D1//C,
2300                domain_remove_smaller_than(VD, L, VD1)
2301            ;   domain_infimum(VD, n(Inf)),
2302                G is Inf + D1//C,
2303                domain_remove_greater_than(VD, G, VD1)
2304            ),
2305            fd_put(V, VD1, VPs)
2306        ;   true
2307        ),
2308        remove_dist_upper_leq(Cs, Vs, D1).
2309
2310
2311remove_dist_upper([], _).
2312remove_dist_upper([C*V|CVs], D) :-
2313        (   fd_get(V, VD, VPs) ->
2314            (   C < 0 ->
2315                (   domain_supremum(VD, n(Sup)) ->
2316                    L is Sup + D//C,
2317                    domain_remove_smaller_than(VD, L, VD1)
2318                ;   VD1 = VD
2319                )
2320            ;   (   domain_infimum(VD, n(Inf)) ->
2321                    G is Inf + D//C,
2322                    domain_remove_greater_than(VD, G, VD1)
2323                ;   VD1 = VD
2324                )
2325            ),
2326            fd_put(V, VD1, VPs)
2327        ;   true
2328        ),
2329        remove_dist_upper(CVs, D).
2330
2331remove_dist_lower([], _).
2332remove_dist_lower([C*V|CVs], D) :-
2333        (   fd_get(V, VD, VPs) ->
2334            (   C < 0 ->
2335                (   domain_infimum(VD, n(Inf)) ->
2336                    G is Inf - D//C,
2337                    domain_remove_greater_than(VD, G, VD1)
2338                ;   VD1 = VD
2339                )
2340            ;   (   domain_supremum(VD, n(Sup)) ->
2341                    L is Sup - D//C,
2342                    domain_remove_smaller_than(VD, L, VD1)
2343                ;   VD1 = VD
2344                )
2345            ),
2346            fd_put(V, VD1, VPs)
2347        ;   true
2348        ),
2349        remove_dist_lower(CVs, D).
2350
2351remove_upper([], _).
2352remove_upper([C*X|CXs], Max) :-
2353        (   fd_get(X, XD, XPs) ->
2354            D is Max//C,
2355            (   C < 0 ->
2356                domain_remove_smaller_than(XD, D, XD1)
2357            ;   domain_remove_greater_than(XD, D, XD1)
2358            ),
2359            fd_put(X, XD1, XPs)
2360        ;   true
2361        ),
2362        remove_upper(CXs, Max).
2363
2364remove_lower([], _).
2365remove_lower([C*X|CXs], Min) :-
2366        (   fd_get(X, XD, XPs) ->
2367            D is -Min//C,
2368            (   C < 0 ->
2369                domain_remove_greater_than(XD, D, XD1)
2370            ;   domain_remove_smaller_than(XD, D, XD1)
2371            ),
2372            fd_put(X, XD1, XPs)
2373        ;   true
2374        ),
2375        remove_lower(CXs, Min).
2376
2377%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2378
2379/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2380   Constraint propagation proceeds as follows: Each CLP(FD) variable
2381   has an attribute that stores its associated domain and constraints.
2382   Constraints are triggered when the event they are registered for
2383   occurs (for example: variable is instantiated, bounds change etc.).
2384   do_queue/0 works off all triggered constraints, possibly triggering
2385   new ones, until fixpoint.
2386- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2387
2388% FIFO queue
2389
2390make_queue :- nb_setval('$clpfd_queue', fast_slow([], [])).
2391
2392push_queue(E, Which) :-
2393        nb_getval('$clpfd_queue', Qs),
2394        arg(Which, Qs, Q),
2395        (   Q == [] ->
2396            setarg(Which, Qs, [E|T]-T)
2397        ;   Q = H-[E|T],
2398            setarg(Which, Qs, H-T)
2399        ).
2400
2401pop_queue(E) :-
2402        nb_getval('$clpfd_queue', Qs),
2403        (   pop_queue(E, Qs, 1) ->  true
2404        ;   pop_queue(E, Qs, 2)
2405        ).
2406
2407pop_queue(E, Qs, Which) :-
2408        arg(Which, Qs, [E|NH]-T),
2409        (   var(NH) ->
2410            setarg(Which, Qs, [])
2411        ;   setarg(Which, Qs, NH-T)
2412        ).
2413
2414fetch_propagator(Prop) :-
2415        pop_queue(P),
2416        (   propagator_state(P, S), S == dead -> fetch_propagator(Prop)
2417        ;   Prop = P
2418        ).
2419
2420/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2421   Parsing a CLP(FD) expression has two important side-effects: First,
2422   it constrains the variables occurring in the expression to
2423   integers. Second, it constrains some of them even more: For
2424   example, in X/Y and X mod Y, Y is constrained to be #\= 0.
2425- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2426
2427constrain_to_integer(Var) :-
2428        (   integer(Var) -> true
2429        ;   fd_get(Var, D, Ps),
2430            fd_put(Var, D, Ps)
2431        ).
2432
2433power_var_num(P, X, N) :-
2434        (   var(P) -> X = P, N = 1
2435        ;   P = Left*Right,
2436            power_var_num(Left, XL, L),
2437            power_var_num(Right, XR, R),
2438            XL == XR,
2439            X = XL,
2440            N is L + R
2441        ).
2442
2443/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2444   Given expression E, we obtain the finite domain variable R by
2445   interpreting a simple committed-choice language that is a list of
2446   conditions and bodies. In conditions, g(Goal) means literally Goal,
2447   and m(Match) means that E can be decomposed as stated. The
2448   variables are to be understood as the result of parsing the
2449   subexpressions recursively. In the body, g(Goal) means again Goal,
2450   and p(Propagator) means to attach and trigger once a propagator.
2451- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2452
2453:- op(800, xfx, =>).
2454
2455parse_clpfd(E, R,
2456            [g(cyclic_term(E)) => [g(domain_error(clpfd_expression, E))],
2457             g(var(E))         => [g(non_monotonic(E)),
2458                                   g(constrain_to_integer(E)), g(E = R)],
2459             g(integer(E))     => [g(R = E)],
2460             ?(E)              => [g(must_be_fd_integer(E)), g(R = E)],
2461             #(E)              => [g(must_be_fd_integer(E)), g(R = E)],
2462             m(A+B)            => [p(pplus(A, B, R))],
2463             % power_var_num/3 must occur before */2 to be useful
2464             g(power_var_num(E, V, N)) => [p(pexp(V, N, R))],
2465             m(A*B)            => [p(ptimes(A, B, R))],
2466             m(A-B)            => [p(pplus(R,B,A))],
2467             m(-A)             => [p(ptimes(-1,A,R))],
2468             m(max(A,B))       => [g(A #=< ?(R)), g(B #=< R), p(pmax(A, B, R))],
2469             m(min(A,B))       => [g(A #>= ?(R)), g(B #>= R), p(pmin(A, B, R))],
2470             m(A mod B)        => [g(B #\= 0), p(pmod(A, B, R))],
2471             m(A rem B)        => [g(B #\= 0), p(prem(A, B, R))],
2472             m(abs(A))         => [g(?(R) #>= 0), p(pabs(A, R))],
2473%             m(A/B)            => [g(B #\= 0), p(ptzdiv(A, B, R))],
2474             m(A//B)           => [g(B #\= 0), p(ptzdiv(A, B, R))],
2475             m(A div B)        => [g(?(R) #= (A - (A mod B)) // B)],
2476             m(A rdiv B)       => [g(B #\= 0), p(prdiv(A, B, R))],
2477             m(A^B)            => [p(pexp(A, B, R))],
2478             % bitwise operations
2479             m(\A)             => [p(pfunction(\, A, R))],
2480             m(msb(A))         => [p(pfunction(msb, A, R))],
2481             m(lsb(A))         => [p(pfunction(lsb, A, R))],
2482             m(popcount(A))    => [p(pfunction(popcount, A, R))],
2483             m(A<<B)           => [p(pfunction(<<, A, B, R))],
2484             m(A>>B)           => [p(pfunction(>>, A, B, R))],
2485             m(A/\B)           => [p(pfunction(/\, A, B, R))],
2486             m(A\/B)           => [p(pfunction(\/, A, B, R))],
2487             m(A xor B)        => [p(pfunction(xor, A, B, R))],
2488             g(true)           => [g(domain_error(clpfd_expression, E))]
2489            ]).
2490
2491non_monotonic(X) :-
2492        (   \+ fd_var(X), current_prolog_flag(clpfd_monotonic, true) ->
2493            instantiation_error(X)
2494        ;   true
2495        ).
2496
2497% Here, we compile the committed choice language to a single
2498% predicate, parse_clpfd/2.
2499
2500make_parse_clpfd(Clauses) :-
2501        parse_clpfd_clauses(Clauses0),
2502        maplist(goals_goal, Clauses0, Clauses).
2503
2504goals_goal((Head :- Goals), (Head :- Body)) :-
2505        list_goal(Goals, Body).
2506
2507parse_clpfd_clauses(Clauses) :-
2508        parse_clpfd(E, R, Matchers),
2509        maplist(parse_matcher(E, R), Matchers, Clauses).
2510
2511parse_matcher(E, R, Matcher, Clause) :-
2512        Matcher = (Condition0 => Goals0),
2513        phrase((parse_condition(Condition0, E, Head),
2514                parse_goals(Goals0)), Goals),
2515        Clause = (parse_clpfd(Head, R) :- Goals).
2516
2517parse_condition(g(Goal), E, E)       --> [Goal, !].
2518parse_condition(?(E), _, ?(E))       --> [!].
2519parse_condition(#(E), _, #(E))       --> [!].
2520parse_condition(m(Match), _, Match0) -->
2521        [!],
2522        { copy_term(Match, Match0),
2523          term_variables(Match0, Vs0),
2524          term_variables(Match, Vs)
2525        },
2526        parse_match_variables(Vs0, Vs).
2527
2528parse_match_variables([], []) --> [].
2529parse_match_variables([V0|Vs0], [V|Vs]) -->
2530        [parse_clpfd(V0, V)],
2531        parse_match_variables(Vs0, Vs).
2532
2533parse_goals([]) --> [].
2534parse_goals([G|Gs]) --> parse_goal(G), parse_goals(Gs).
2535
2536parse_goal(g(Goal)) --> [Goal].
2537parse_goal(p(Prop)) -->
2538        [make_propagator(Prop, P)],
2539        { term_variables(Prop, Vs) },
2540        parse_init(Vs, P),
2541        [trigger_once(P)].
2542
2543parse_init([], _)     --> [].
2544parse_init([V|Vs], P) --> [init_propagator(V, P)], parse_init(Vs, P).
2545
2546%?- set_prolog_flag(answer_write_options, [portray(true)]),
2547%   clpfd:parse_clpfd_clauses(Clauses), maplist(portray_clause, Clauses).
2548
2549
2550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2551%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2552
2553trigger_once(Prop) :- trigger_prop(Prop), do_queue.
2554
2555neq(A, B) :- propagator_init_trigger(pneq(A, B)).
2556
2557propagator_init_trigger(P) -->
2558        { term_variables(P, Vs) },
2559        propagator_init_trigger(Vs, P).
2560
2561propagator_init_trigger(Vs, P) -->
2562        [p(Prop)],
2563        { make_propagator(P, Prop),
2564          maplist(prop_init(Prop), Vs),
2565          trigger_once(Prop) }.
2566
2567propagator_init_trigger(P) :-
2568        phrase(propagator_init_trigger(P), _).
2569
2570propagator_init_trigger(Vs, P) :-
2571        phrase(propagator_init_trigger(Vs, P), _).
2572
2573prop_init(Prop, V) :- init_propagator(V, Prop).
2574
2575geq(A, B) :-
2576        (   fd_get(A, AD, APs) ->
2577            domain_infimum(AD, AI),
2578            (   fd_get(B, BD, _) ->
2579                domain_supremum(BD, BS),
2580                (   AI cis_geq BS -> true
2581                ;   propagator_init_trigger(pgeq(A,B))
2582                )
2583            ;   (   AI cis_geq n(B) -> true
2584                ;   domain_remove_smaller_than(AD, B, AD1),
2585                    fd_put(A, AD1, APs),
2586                    do_queue
2587                )
2588            )
2589        ;   fd_get(B, BD, BPs) ->
2590            domain_remove_greater_than(BD, A, BD1),
2591            fd_put(B, BD1, BPs),
2592            do_queue
2593        ;   A >= B
2594        ).
2595
2596/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2597   Naive parsing of inequalities and disequalities can result in a lot
2598   of unnecessary work if expressions of non-trivial depth are
2599   involved: Auxiliary variables are introduced for sub-expressions,
2600   and propagation proceeds on them as if they were involved in a
2601   tighter constraint (like equality), whereas eventually only very
2602   little of the propagated information is actually used. For example,
2603   only extremal values are of interest in inequalities. Introducing
2604   auxiliary variables should be avoided when possible, and
2605   specialised propagators should be used for common constraints.
2606
2607   We again use a simple committed-choice language for matching
2608   special cases of constraints. m_c(M,C) means that M matches and C
2609   holds. d(X, Y) means decomposition, i.e., it is short for
2610   g(parse_clpfd(X, Y)). r(X, Y) means to rematch with X and Y.
2611
2612   Two things are important: First, although the actual constraint
2613   functors (#\=2, #=/2 etc.) are used in the description, they must
2614   expand to the respective auxiliary predicates (match_expand/2)
2615   because the actual constraints are subject to goal expansion.
2616   Second, when specialised constraints (like scalar product) post
2617   simpler constraints on their own, these simpler versions must be
2618   handled separately and must occur before.
2619- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2620
2621match_expand(#>=, clpfd_geq_).
2622match_expand(#=, clpfd_equal_).
2623match_expand(#\=, clpfd_neq).
2624
2625symmetric(#=).
2626symmetric(#\=).
2627
2628matches([
2629         m_c(any(X) #>= any(Y), left_right_linsum_const(X, Y, Cs, Vs, Const)) =>
2630            [g((   Cs = [1], Vs = [A] -> geq(A, Const)
2631               ;   Cs = [-1], Vs = [A] -> Const1 is -Const, geq(Const1, A)
2632               ;   Cs = [1,1], Vs = [A,B] -> ?(A) + ?(B) #= ?(S), geq(S, Const)
2633               ;   Cs = [1,-1], Vs = [A,B] ->
2634                   (   Const =:= 0 -> geq(A, B)
2635                   ;   C1 is -Const,
2636                       propagator_init_trigger(x_leq_y_plus_c(B, A, C1))
2637                   )
2638               ;   Cs = [-1,1], Vs = [A,B] ->
2639                   (   Const =:= 0 -> geq(B, A)
2640                   ;   C1 is -Const,
2641                       propagator_init_trigger(x_leq_y_plus_c(A, B, C1))
2642                   )
2643               ;   Cs = [-1,-1], Vs = [A,B] ->
2644                   ?(A) + ?(B) #= ?(S), Const1 is -Const, geq(Const1, S)
2645               ;   scalar_product_(#>=, Cs, Vs, Const)
2646               ))],
2647         m(any(X) - any(Y) #>= integer(C))     => [d(X, X1), d(Y, Y1), g(C1 is -C), p(x_leq_y_plus_c(Y1, X1, C1))],
2648         m(integer(X) #>= any(Z) + integer(A)) => [g(C is X - A), r(C, Z)],
2649         m(abs(any(X)-any(Y)) #>= integer(I))  => [d(X, X1), d(Y, Y1), p(absdiff_geq(X1, Y1, I))],
2650         m(abs(any(X)) #>= integer(I))         => [d(X, RX), g((I>0 -> I1 is -I, RX in inf..I1 \/ I..sup; true))],
2651         m(integer(I) #>= abs(any(X)))         => [d(X, RX), g(I>=0), g(I1 is -I), g(RX in I1..I)],
2652         m(any(X) #>= any(Y))                  => [d(X, RX), d(Y, RY), g(geq(RX, RY))],
2653
2654         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2655         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2656
2657         m(var(X) #= var(Y))        => [g(constrain_to_integer(X)), g(X=Y)],
2658         m(var(X) #= var(Y)+var(Z)) => [p(pplus(Y,Z,X))],
2659         m(var(X) #= var(Y)-var(Z)) => [p(pplus(X,Z,Y))],
2660         m(var(X) #= var(Y)*var(Z)) => [p(ptimes(Y,Z,X))],
2661         m(var(X) #= -var(Z))       => [p(ptimes(-1, Z, X))],
2662         m_c(any(X) #= any(Y), left_right_linsum_const(X, Y, Cs, Vs, S)) =>
2663            [g(scalar_product_(#=, Cs, Vs, S))],
2664         m(var(X) #= any(Y))       => [d(Y,X)],
2665         m(any(X) #= any(Y))       => [d(X, RX), d(Y, RX)],
2666
2667         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2668         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2669
2670         m(var(X) #\= integer(Y))             => [g(neq_num(X, Y))],
2671         m(var(X) #\= var(Y))                 => [g(neq(X,Y))],
2672         m(var(X) #\= var(Y) + var(Z))        => [p(x_neq_y_plus_z(X, Y, Z))],
2673         m(var(X) #\= var(Y) - var(Z))        => [p(x_neq_y_plus_z(Y, X, Z))],
2674         m(var(X) #\= var(Y)*var(Z))          => [p(ptimes(Y,Z,P)), g(neq(X,P))],
2675         m(integer(X) #\= abs(any(Y)-any(Z))) => [d(Y, Y1), d(Z, Z1), p(absdiff_neq(Y1, Z1, X))],
2676         m_c(any(X) #\= any(Y), left_right_linsum_const(X, Y, Cs, Vs, S)) =>
2677            [g(scalar_product_(#\=, Cs, Vs, S))],
2678         m(any(X) #\= any(Y) + any(Z))        => [d(X, X1), d(Y, Y1), d(Z, Z1), p(x_neq_y_plus_z(X1, Y1, Z1))],
2679         m(any(X) #\= any(Y) - any(Z))        => [d(X, X1), d(Y, Y1), d(Z, Z1), p(x_neq_y_plus_z(Y1, X1, Z1))],
2680         m(any(X) #\= any(Y)) => [d(X, RX), d(Y, RY), g(neq(RX, RY))]
2681        ]).
2682
2683/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2684   We again compile the committed-choice matching language to the
2685   intended auxiliary predicates. We now must take care not to
2686   unintentionally unify a variable with a complex term.
2687- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2688
2689make_matches(Clauses) :-
2690        matches(Ms),
2691        findall(F, (member(M=>_, Ms), arg(1, M, M1), functor(M1, F, _)), Fs0),
2692        sort(Fs0, Fs),
2693        maplist(prevent_cyclic_argument, Fs, PrevCyclicClauses),
2694        phrase(matchers(Ms), Clauses0),
2695        maplist(goals_goal, Clauses0, MatcherClauses),
2696        append(PrevCyclicClauses, MatcherClauses, Clauses1),
2697        sort_by_predicate(Clauses1, Clauses).
2698
2699sort_by_predicate(Clauses, ByPred) :-
2700        map_list_to_pairs(predname, Clauses, Keyed),
2701        keysort(Keyed, KeyedByPred),
2702        pairs_values(KeyedByPred, ByPred).
2703
2704predname((H:-_), Key)   :- !, predname(H, Key).
2705predname(M:H, M:Key)    :- !, predname(H, Key).
2706predname(H, Name/Arity) :- !, functor(H, Name, Arity).
2707
2708prevent_cyclic_argument(F0, Clause) :-
2709        match_expand(F0, F),
2710        Head =.. [F,X,Y],
2711        Clause = (Head :- (   cyclic_term(X) ->
2712                              domain_error(clpfd_expression, X)
2713                          ;   cyclic_term(Y) ->
2714                              domain_error(clpfd_expression, Y)
2715                          ;   false
2716                          )).
2717
2718matchers([]) --> [].
2719matchers([Condition => Goals|Ms]) -->
2720        matcher(Condition, Goals),
2721        matchers(Ms).
2722
2723matcher(m(M), Gs) --> matcher(m_c(M,true), Gs).
2724matcher(m_c(Matcher,Cond), Gs) -->
2725        [(Head :- Goals0)],
2726        { Matcher =.. [F,A,B],
2727          match_expand(F, Expand),
2728          Head =.. [Expand,X,Y],
2729          phrase((match(A, X), match(B, Y)), Goals0, [Cond,!|Goals1]),
2730          phrase(match_goals(Gs, Expand), Goals1) },
2731        (   { symmetric(F), \+ (subsumes_term(A, B), subsumes_term(B, A)) } ->
2732            { Head1 =.. [Expand,Y,X] },
2733            [(Head1 :- Goals0)]
2734        ;   []
2735        ).
2736
2737match(any(A), T)     --> [A = T].
2738match(var(V), T)     --> [( nonvar(T), ( T = ?(Var) ; T = #(Var) ) ->
2739                            must_be_fd_integer(Var), V = Var
2740                          ; v_or_i(T), V = T
2741                          )].
2742match(integer(I), T) --> [integer(T), I = T].
2743match(-X, T)         --> [nonvar(T), T = -A], match(X, A).
2744match(abs(X), T)     --> [nonvar(T), T = abs(A)], match(X, A).
2745match(Binary, T)     -->
2746        { Binary =.. [Op,X,Y], Term =.. [Op,A,B] },
2747        [nonvar(T), T = Term],
2748        match(X, A), match(Y, B).
2749
2750match_goals([], _)     --> [].
2751match_goals([G|Gs], F) --> match_goal(G, F), match_goals(Gs, F).
2752
2753match_goal(r(X,Y), F)  --> { G =.. [F,X,Y] }, [G].
2754match_goal(d(X,Y), _)  --> [parse_clpfd(X, Y)].
2755match_goal(g(Goal), _) --> [Goal].
2756match_goal(p(Prop), _) -->
2757        [make_propagator(Prop, P)],
2758        { term_variables(Prop, Vs) },
2759        parse_init(Vs, P),
2760        [trigger_once(P)].
2761
2762
2763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2764
2765
2766
2767%% ?X #>= ?Y
2768%
2769% Same as Y #=< X. When reasoning over integers, replace `(>=)/2` by
2770% #>=/2 to obtain more general relations. See [declarative integer
2771% arithmetic](<#clpfd-integer-arith>).
2772
2773X #>= Y :- clpfd_geq(X, Y).
2774
2775clpfd_geq(X, Y) :- clpfd_geq_(X, Y), reinforce(X), reinforce(Y).
2776
2777%% ?X #=< ?Y
2778%
2779% The arithmetic expression X is less than or equal to Y. When
2780% reasoning over integers, replace `(=<)/2` by #=</2 to obtain more
2781% general relations. See [declarative integer
2782% arithmetic](<#clpfd-integer-arith>).
2783
2784X #=< Y :- Y #>= X.
2785
2786%% ?X #= ?Y
2787%
2788% The arithmetic expression X equals Y. This is the most important
2789% [arithmetic constraint](<#clpfd-arith-constraints>), subsuming and
2790% replacing both `(is)/2` _and_ `(=:=)/2` over integers. See
2791% [declarative integer arithmetic](<#clpfd-integer-arith>).
2792
2793X #= Y :- clpfd_equal(X, Y).
2794
2795clpfd_equal(X, Y) :- clpfd_equal_(X, Y), reinforce(X).
2796
2797/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2798   Conditions under which an equality can be compiled to built-in
2799   arithmetic. Their order is significant. (/)/2 becomes (//)/2.
2800- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2801
2802expr_conds(E, E)                 --> [integer(E)],
2803        { var(E), !, \+ current_prolog_flag(clpfd_monotonic, true) }.
2804expr_conds(E, E)                 --> { integer(E) }.
2805expr_conds(?(E), E)              --> [integer(E)].
2806expr_conds(#(E), E)              --> [integer(E)].
2807expr_conds(-E0, -E)              --> expr_conds(E0, E).
2808expr_conds(abs(E0), abs(E))      --> expr_conds(E0, E).
2809expr_conds(A0+B0, A+B)           --> expr_conds(A0, A), expr_conds(B0, B).
2810expr_conds(A0*B0, A*B)           --> expr_conds(A0, A), expr_conds(B0, B).
2811expr_conds(A0-B0, A-B)           --> expr_conds(A0, A), expr_conds(B0, B).
2812expr_conds(A0//B0, A//B)         -->
2813        expr_conds(A0, A), expr_conds(B0, B),
2814        [B =\= 0].
2815%expr_conds(A0/B0, AB)            --> expr_conds(A0//B0, AB).
2816expr_conds(min(A0,B0), min(A,B)) --> expr_conds(A0, A), expr_conds(B0, B).
2817expr_conds(max(A0,B0), max(A,B)) --> expr_conds(A0, A), expr_conds(B0, B).
2818expr_conds(A0 mod B0, A mod B)   -->
2819        expr_conds(A0, A), expr_conds(B0, B),
2820        [B =\= 0].
2821expr_conds(A0^B0, A^B)           -->
2822        expr_conds(A0, A), expr_conds(B0, B),
2823        [(B >= 0 ; A =:= -1)].
2824% Bitwise operations, added to make CLP(FD) usable in more cases
2825expr_conds(\ A0, \ A) --> expr_conds(A0, A).
2826expr_conds(A0<<B0, A<<B) --> expr_conds(A0, A), expr_conds(B0, B).
2827expr_conds(A0>>B0, A>>B) --> expr_conds(A0, A), expr_conds(B0, B).
2828expr_conds(A0/\B0, A/\B) --> expr_conds(A0, A), expr_conds(B0, B).
2829expr_conds(A0\/B0, A\/B) --> expr_conds(A0, A), expr_conds(B0, B).
2830expr_conds(A0 xor B0, A xor B) --> expr_conds(A0, A), expr_conds(B0, B).
2831expr_conds(lsb(A0), lsb(A)) --> expr_conds(A0, A).
2832expr_conds(msb(A0), msb(A)) --> expr_conds(A0, A).
2833expr_conds(popcount(A0), popcount(A)) --> expr_conds(A0, A).
2834
2835:- multifile
2836        system:goal_expansion/2.
2837:- dynamic
2838        system:goal_expansion/2.
2839
2840system:goal_expansion(Goal, Expansion) :-
2841        \+ current_prolog_flag(clpfd_goal_expansion, false),
2842        clpfd_expandable(Goal),
2843        prolog_load_context(module, M),
2844	(   M == clpfd
2845	->  true
2846	;   predicate_property(M:Goal, imported_from(clpfd))
2847	),
2848        clpfd_expansion(Goal, Expansion).
2849
2850clpfd_expandable(_ in _).
2851clpfd_expandable(_ #= _).
2852clpfd_expandable(_ #>= _).
2853clpfd_expandable(_ #=< _).
2854clpfd_expandable(_ #> _).
2855clpfd_expandable(_ #< _).
2856
2857clpfd_expansion(Var in Dom, In) :-
2858        (   ground(Dom), Dom = L..U, integer(L), integer(U) ->
2859            expansion_simpler(
2860                (   integer(Var) ->
2861                    between(L, U, Var)
2862                ;   clpfd:clpfd_in(Var, Dom)
2863                ), In)
2864        ;   In = clpfd:clpfd_in(Var, Dom)
2865        ).
2866clpfd_expansion(X0 #= Y0, Equal) :-
2867        phrase(expr_conds(X0, X), CsX),
2868        phrase(expr_conds(Y0, Y), CsY),
2869        list_goal(CsX, CondX),
2870        list_goal(CsY, CondY),
2871        expansion_simpler(
2872                (   CondX ->
2873                    (   var(Y) -> Y is X
2874                    ;   CondY -> X =:= Y
2875                    ;   T is X, clpfd:clpfd_equal(T, Y0)
2876                    )
2877                ;   CondY ->
2878                    (   var(X) -> X is Y
2879                    ;   T is Y, clpfd:clpfd_equal(X0, T)
2880                    )
2881                ;   clpfd:clpfd_equal(X0, Y0)
2882                ), Equal).
2883clpfd_expansion(X0 #>= Y0, Geq) :-
2884        phrase(expr_conds(X0, X), CsX),
2885        phrase(expr_conds(Y0, Y), CsY),
2886        list_goal(CsX, CondX),
2887        list_goal(CsY, CondY),
2888        expansion_simpler(
2889              (   CondX ->
2890                  (   CondY -> X >= Y
2891                  ;   T is X, clpfd:clpfd_geq(T, Y0)
2892                  )
2893              ;   CondY -> T is Y, clpfd:clpfd_geq(X0, T)
2894              ;   clpfd:clpfd_geq(X0, Y0)
2895              ), Geq).
2896clpfd_expansion(X #=< Y,  Leq) :- clpfd_expansion(Y #>= X, Leq).
2897clpfd_expansion(X #> Y, Gt)    :- clpfd_expansion(X #>= Y+1, Gt).
2898clpfd_expansion(X #< Y, Lt)    :- clpfd_expansion(Y #> X, Lt).
2899
2900expansion_simpler((True->Then0;_), Then) :-
2901        is_true(True), !,
2902        expansion_simpler(Then0, Then).
2903expansion_simpler((False->_;Else0), Else) :-
2904        is_false(False), !,
2905        expansion_simpler(Else0, Else).
2906expansion_simpler((If->Then0;Else0), (If->Then;Else)) :- !,
2907        expansion_simpler(Then0, Then),
2908        expansion_simpler(Else0, Else).
2909expansion_simpler((A0,B0), (A,B)) :-
2910        expansion_simpler(A0, A),
2911        expansion_simpler(B0, B).
2912expansion_simpler(Var is Expr0, Goal) :-
2913        ground(Expr0), !,
2914        phrase(expr_conds(Expr0, Expr), Gs),
2915        (   maplist(call, Gs) -> Value is Expr, Goal = (Var = Value)
2916        ;   Goal = false
2917        ).
2918expansion_simpler(Var =:= Expr0, Goal) :-
2919        ground(Expr0), !,
2920        phrase(expr_conds(Expr0, Expr), Gs),
2921        (   maplist(call, Gs) -> Value is Expr, Goal = (Var =:= Value)
2922        ;   Goal = false
2923        ).
2924expansion_simpler(Var is Expr, Var = Expr) :- var(Expr), !.
2925expansion_simpler(Var is Expr, Goal) :- !,
2926        (   var(Var), nonvar(Expr),
2927            Expr = E mod M, nonvar(E), E = A^B ->
2928            Goal = ( ( integer(A), integer(B), integer(M),
2929                       A >= 0, B >= 0, M > 0 ->
2930                       Var is powm(A, B, M)
2931                     ; Var is Expr
2932                     ) )
2933        ;   Goal = ( Var is Expr )
2934        ).
2935expansion_simpler(between(L,U,V), Goal) :- maplist(integer, [L,U,V]), !,
2936        (   between(L,U,V) -> Goal = true
2937        ;   Goal = false
2938        ).
2939expansion_simpler(Goal, Goal).
2940
2941is_true(true).
2942is_true(integer(I))  :- integer(I).
2943:- if(current_predicate(var_property/2)).
2944is_true(var(X))      :- var(X), var_property(X, fresh(true)).
2945is_false(integer(X)) :- var(X), var_property(X, fresh(true)).
2946is_false((A,B))      :- is_false(A) ; is_false(B).
2947:- endif.
2948is_false(var(X)) :- nonvar(X).
2949
2950
2951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2952
2953linsum(X, S, S)    --> { var(X), !, non_monotonic(X) }, [vn(X,1)].
2954linsum(I, S0, S)   --> { integer(I), S is S0 + I }.
2955linsum(?(X), S, S) --> { must_be_fd_integer(X) }, [vn(X,1)].
2956linsum(#(X), S, S) --> { must_be_fd_integer(X) }, [vn(X,1)].
2957linsum(-A, S0, S)  --> mulsum(A, -1, S0, S).
2958linsum(N*A, S0, S) --> { integer(N) }, !, mulsum(A, N, S0, S).
2959linsum(A*N, S0, S) --> { integer(N) }, !, mulsum(A, N, S0, S).
2960linsum(A+B, S0, S) --> linsum(A, S0, S1), linsum(B, S1, S).
2961linsum(A-B, S0, S) --> linsum(A, S0, S1), mulsum(B, -1, S1, S).
2962
2963mulsum(A, M, S0, S) -->
2964        { phrase(linsum(A, 0, CA), As), S is S0 + M*CA },
2965        lin_mul(As, M).
2966
2967lin_mul([], _)             --> [].
2968lin_mul([vn(X,N0)|VNs], M) --> { N is N0*M }, [vn(X,N)], lin_mul(VNs, M).
2969
2970v_or_i(V) :- var(V), !, non_monotonic(V).
2971v_or_i(I) :- integer(I).
2972
2973must_be_fd_integer(X) :-
2974        (   var(X) -> constrain_to_integer(X)
2975        ;   must_be(integer, X)
2976        ).
2977
2978left_right_linsum_const(Left, Right, Cs, Vs, Const) :-
2979        phrase(linsum(Left, 0, CL), Lefts0, Rights),
2980        phrase(linsum(Right, 0, CR), Rights0),
2981        maplist(linterm_negate, Rights0, Rights),
2982        msort(Lefts0, Lefts),
2983        Lefts = [vn(First,N)|LeftsRest],
2984        vns_coeffs_variables(LeftsRest, N, First, Cs0, Vs0),
2985        filter_linsum(Cs0, Vs0, Cs, Vs),
2986        Const is CR - CL.
2987        %format("linear sum: ~w ~w ~w\n", [Cs,Vs,Const]).
2988
2989linterm_negate(vn(V,N0), vn(V,N)) :- N is -N0.
2990
2991vns_coeffs_variables([], N, V, [N], [V]).
2992vns_coeffs_variables([vn(V,N)|VNs], N0, V0, Ns, Vs) :-
2993        (   V == V0 ->
2994            N1 is N0 + N,
2995            vns_coeffs_variables(VNs, N1, V0, Ns, Vs)
2996        ;   Ns = [N0|NRest],
2997            Vs = [V0|VRest],
2998            vns_coeffs_variables(VNs, N, V, NRest, VRest)
2999        ).
3000
3001filter_linsum([], [], [], []).
3002filter_linsum([C0|Cs0], [V0|Vs0], Cs, Vs) :-
3003        (   C0 =:= 0 ->
3004            constrain_to_integer(V0),
3005            filter_linsum(Cs0, Vs0, Cs, Vs)
3006        ;   Cs = [C0|Cs1], Vs = [V0|Vs1],
3007            filter_linsum(Cs0, Vs0, Cs1, Vs1)
3008        ).
3009
3010gcd([], G, G).
3011gcd([N|Ns], G0, G) :-
3012        G1 is gcd(N, G0),
3013        gcd(Ns, G1, G).
3014
3015even(N) :- N mod 2 =:= 0.
3016
3017odd(N) :- \+ even(N).
3018
3019/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3020   k-th root of N, if N is a k-th power.
3021
3022   TODO: Replace this when the GMP function becomes available.
3023- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3024
3025integer_kth_root(N, K, R) :-
3026        (   even(K) ->
3027            N >= 0
3028        ;   true
3029        ),
3030        (   N < 0 ->
3031            odd(K),
3032            integer_kroot(N, 0, N, K, R)
3033        ;   integer_kroot(0, N, N, K, R)
3034        ).
3035
3036integer_kroot(L, U, N, K, R) :-
3037        (   L =:= U -> N =:= L^K, R = L
3038        ;   L + 1 =:= U ->
3039            (   L^K =:= N -> R = L
3040            ;   U^K =:= N -> R = U
3041            ;   false
3042            )
3043        ;   Mid is (L + U)//2,
3044            (   Mid^K > N ->
3045                integer_kroot(L, Mid, N, K, R)
3046            ;   integer_kroot(Mid, U, N, K, R)
3047            )
3048        ).
3049
3050integer_log_b(N, B, Log0, Log) :-
3051        T is B^Log0,
3052        (   T =:= N -> Log = Log0
3053        ;   T < N,
3054            Log1 is Log0 + 1,
3055            integer_log_b(N, B, Log1, Log)
3056        ).
3057
3058floor_integer_log_b(N, B, Log0, Log) :-
3059        T is B^Log0,
3060        (   T > N -> Log is Log0 - 1
3061        ;   T =:= N -> Log = Log0
3062        ;   T < N,
3063            Log1 is Log0 + 1,
3064            floor_integer_log_b(N, B, Log1, Log)
3065        ).
3066
3067
3068/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3069   Largest R such that R^K =< N.
3070- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3071
3072:- if(current_predicate(nth_integer_root_and_remainder/4)).
3073
3074% This currently only works for K >= 1, which is all that is needed for now.
3075integer_kth_root_leq(N, K, R) :-
3076        nth_integer_root_and_remainder(K, N, R, _).
3077
3078:- else.
3079
3080integer_kth_root_leq(N, K, R) :-
3081        (   even(K) ->
3082            N >= 0
3083        ;   true
3084        ),
3085        (   N < 0 ->
3086            odd(K),
3087            integer_kroot_leq(N, 0, N, K, R)
3088        ;   integer_kroot_leq(0, N, N, K, R)
3089        ).
3090
3091integer_kroot_leq(L, U, N, K, R) :-
3092        (   L =:= U -> R = L
3093        ;   L + 1 =:= U ->
3094            (   U^K =< N -> R = U
3095            ;   R = L
3096            )
3097        ;   Mid is (L + U)//2,
3098            (   Mid^K > N ->
3099                integer_kroot_leq(L, Mid, N, K, R)
3100            ;   integer_kroot_leq(Mid, U, N, K, R)
3101            )
3102        ).
3103
3104:- endif.
3105
3106%% ?X #\= ?Y
3107%
3108% The arithmetic expressions X and Y evaluate to distinct integers.
3109% When reasoning over integers, replace `(=\=)/2` by #\=/2 to obtain
3110% more general relations. See [declarative integer
3111% arithmetic](<#clpfd-integer-arith>).
3112
3113X #\= Y :- clpfd_neq(X, Y), do_queue.
3114
3115% X #\= Y + Z
3116
3117x_neq_y_plus_z(X, Y, Z) :-
3118        propagator_init_trigger(x_neq_y_plus_z(X,Y,Z)).
3119
3120% X is distinct from the number N. This is used internally, and does
3121% not reinforce other constraints.
3122
3123neq_num(X, N) :-
3124        (   fd_get(X, XD, XPs) ->
3125            domain_remove(XD, N, XD1),
3126            fd_put(X, XD1, XPs)
3127        ;   X =\= N
3128        ).
3129
3130%% ?X #> ?Y
3131%
3132% Same as Y #< X. When reasoning over integers, replace `(>)/2` by
3133% #>/2 to obtain more general relations See [declarative integer
3134% arithmetic](<#clpfd-integer-arith>).
3135
3136X #> Y  :- X #>= Y + 1.
3137
3138%% #<(?X, ?Y)
3139%
3140% The arithmetic expression X is less than Y. When reasoning over
3141% integers, replace `(<)/2` by #</2 to obtain more general relations. See
3142% [declarative integer arithmetic](<#clpfd-integer-arith>).
3143%
3144% In addition to its regular use in tasks that require it, this
3145% constraint can also be useful to eliminate uninteresting symmetries
3146% from a problem. For example, all possible matches between pairs
3147% built from four players in total:
3148%
3149% ==
3150% ?- Vs = [A,B,C,D], Vs ins 1..4,
3151%         all_different(Vs),
3152%         A #< B, C #< D, A #< C,
3153%    findall(pair(A,B)-pair(C,D), label(Vs), Ms).
3154% Ms = [ pair(1, 2)-pair(3, 4),
3155%        pair(1, 3)-pair(2, 4),
3156%        pair(1, 4)-pair(2, 3)].
3157% ==
3158
3159X #< Y  :- Y #> X.
3160
3161%% #\ (+Q)
3162%
3163% Q does _not_ hold. See [reification](<#clpfd-reification>).
3164%
3165% For example, to obtain the complement of a domain:
3166%
3167% ==
3168% ?- #\ X in -3..0\/10..80.
3169% X in inf.. -4\/1..9\/81..sup.
3170% ==
3171
3172#\ Q       :- reify(Q, 0), do_queue.
3173
3174%% ?P #<==> ?Q
3175%
3176% P and Q are equivalent. See [reification](<#clpfd-reification>).
3177%
3178% For example:
3179%
3180% ==
3181% ?- X #= 4 #<==> B, X #\= 4.
3182% B = 0,
3183% X in inf..3\/5..sup.
3184% ==
3185% The following example uses reified constraints to relate a list of
3186% finite domain variables to the number of occurrences of a given value:
3187%
3188% ==
3189% vs_n_num(Vs, N, Num) :-
3190%         maplist(eq_b(N), Vs, Bs),
3191%         sum(Bs, #=, Num).
3192%
3193% eq_b(X, Y, B) :- X #= Y #<==> B.
3194% ==
3195%
3196% Sample queries and their results:
3197%
3198% ==
3199% ?- Vs = [X,Y,Z], Vs ins 0..1, vs_n_num(Vs, 4, Num).
3200% Vs = [X, Y, Z],
3201% Num = 0,
3202% X in 0..1,
3203% Y in 0..1,
3204% Z in 0..1.
3205%
3206% ?- vs_n_num([X,Y,Z], 2, 3).
3207% X = 2,
3208% Y = 2,
3209% Z = 2.
3210% ==
3211
3212L #<==> R  :- reify(L, B), reify(R, B), do_queue.
3213
3214%% ?P #==> ?Q
3215%
3216% P implies Q. See [reification](<#clpfd-reification>).
3217
3218/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3219   Implication is special in that created auxiliary constraints can be
3220   retracted when the implication becomes entailed, for example:
3221
3222   %?- X + 1 #= Y #==> Z, Z #= 1.
3223   %@ Z = 1,
3224   %@ X in inf..sup,
3225   %@ Y in inf..sup.
3226
3227   We cannot use propagator_init_trigger/1 here because the states of
3228   auxiliary propagators are themselves part of the propagator.
3229- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3230
3231L #==> R   :-
3232        reify(L, LB, LPs),
3233        reify(R, RB, RPs),
3234        append(LPs, RPs, Ps),
3235        propagator_init_trigger([LB,RB], pimpl(LB,RB,Ps)).
3236
3237%% ?P #<== ?Q
3238%
3239% Q implies P. See [reification](<#clpfd-reification>).
3240
3241L #<== R   :- R #==> L.
3242
3243%% ?P #/\ ?Q
3244%
3245% P and Q hold. See [reification](<#clpfd-reification>).
3246
3247L #/\ R    :- reify(L, 1), reify(R, 1), do_queue.
3248
3249conjunctive_neqs_var_drep(Eqs, Var, Drep) :-
3250        conjunctive_neqs_var(Eqs, Var),
3251        phrase(conjunctive_neqs_vals(Eqs), Vals),
3252        list_to_domain(Vals, Dom),
3253        domain_complement(Dom, C),
3254        domain_to_drep(C, Drep).
3255
3256conjunctive_neqs_var(V, _) :- var(V), !, false.
3257conjunctive_neqs_var(L #\= R, Var) :-
3258        (   var(L), integer(R) -> Var = L
3259        ;   integer(L), var(R) -> Var = R
3260        ;   false
3261        ).
3262conjunctive_neqs_var(A #/\ B, VA) :-
3263        conjunctive_neqs_var(A, VA),
3264        conjunctive_neqs_var(B, VB),
3265        VA == VB.
3266
3267conjunctive_neqs_vals(L #\= R) --> ( { integer(L) } -> [L] ; [R] ).
3268conjunctive_neqs_vals(A #/\ B) -->
3269        conjunctive_neqs_vals(A),
3270        conjunctive_neqs_vals(B).
3271
3272%% ?P #\/ ?Q
3273%
3274% P or Q holds. See [reification](<#clpfd-reification>).
3275%
3276% For example, the sum of natural numbers below 1000 that are
3277% multiples of 3 or 5:
3278%
3279% ==
3280% ?- findall(N, (N mod 3 #= 0 #\/ N mod 5 #= 0, N in 0..999,
3281%                indomain(N)),
3282%            Ns),
3283%    sum(Ns, #=, Sum).
3284% Ns = [0, 3, 5, 6, 9, 10, 12, 15, 18|...],
3285% Sum = 233168.
3286% ==
3287
3288L #\/ R :-
3289        (   disjunctive_eqs_var_drep(L #\/ R, Var, Drep) -> Var in Drep
3290        ;   reify(L, X, Ps1),
3291            reify(R, Y, Ps2),
3292            propagator_init_trigger([X,Y], reified_or(X,Ps1,Y,Ps2,1))
3293        ).
3294
3295disjunctive_eqs_var_drep(Eqs, Var, Drep) :-
3296        disjunctive_eqs_var(Eqs, Var),
3297        phrase(disjunctive_eqs_vals(Eqs), Vals),
3298        list_to_drep(Vals, Drep).
3299
3300disjunctive_eqs_var(V, _) :- var(V), !, false.
3301disjunctive_eqs_var(V in I, V) :- var(V), integer(I).
3302disjunctive_eqs_var(L #= R, Var) :-
3303        (   var(L), integer(R) -> Var = L
3304        ;   integer(L), var(R) -> Var = R
3305        ;   false
3306        ).
3307disjunctive_eqs_var(A #\/ B, VA) :-
3308        disjunctive_eqs_var(A, VA),
3309        disjunctive_eqs_var(B, VB),
3310        VA == VB.
3311
3312disjunctive_eqs_vals(L #= R)  --> ( { integer(L) } -> [L] ; [R] ).
3313disjunctive_eqs_vals(_ in I)  --> [I].
3314disjunctive_eqs_vals(A #\/ B) -->
3315        disjunctive_eqs_vals(A),
3316        disjunctive_eqs_vals(B).
3317
3318%% ?P #\ ?Q
3319%
3320% Either P holds or Q holds, but not both. See
3321% [reification](<#clpfd-reification>).
3322
3323L #\ R :- (L #\/ R) #/\ #\ (L #/\ R).
3324
3325/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3326   A constraint that is being reified need not hold. Therefore, in
3327   X/Y, Y can as well be 0, for example. Note that it is OK to
3328   constrain the *result* of an expression (which does not appear
3329   explicitly in the expression and is not visible to the outside),
3330   but not the operands, except for requiring that they be integers.
3331
3332   In contrast to parse_clpfd/2, the result of an expression can now
3333   also be undefined, in which case the constraint cannot hold.
3334   Therefore, the committed-choice language is extended by an element
3335   d(D) that states D is 1 iff all subexpressions are defined. a(V)
3336   means that V is an auxiliary variable that was introduced while
3337   parsing a compound expression. a(X,V) means V is auxiliary unless
3338   it is ==/2 X, and a(X,Y,V) means V is auxiliary unless it is ==/2 X
3339   or Y. l(L) means the literal L occurs in the described list.
3340
3341   When a constraint becomes entailed or subexpressions become
3342   undefined, created auxiliary constraints are killed, and the
3343   "clpfd" attribute is removed from auxiliary variables.
3344
3345   For (/)/2, mod/2 and rem/2, we create a skeleton propagator and
3346   remember it as an auxiliary constraint. The pskeleton propagator
3347   can use the skeleton when the constraint is defined.
3348- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3349
3350parse_reified(E, R, D,
3351              [g(cyclic_term(E)) => [g(domain_error(clpfd_expression, E))],
3352               g(var(E))     => [g(non_monotonic(E)),
3353                                 g(constrain_to_integer(E)), g(R = E), g(D=1)],
3354               g(integer(E)) => [g(R=E), g(D=1)],
3355               ?(E)          => [g(must_be_fd_integer(E)), g(R=E), g(D=1)],
3356               #(E)          => [g(must_be_fd_integer(E)), g(R=E), g(D=1)],
3357               m(A+B)        => [d(D), p(pplus(A,B,R)), a(A,B,R)],
3358               m(A*B)        => [d(D), p(ptimes(A,B,R)), a(A,B,R)],
3359               m(A-B)        => [d(D), p(pplus(R,B,A)), a(A,B,R)],
3360               m(-A)         => [d(D), p(ptimes(-1,A,R)), a(R)],
3361               m(max(A,B))   => [d(D), p(pgeq(R, A)), p(pgeq(R, B)), p(pmax(A,B,R)), a(A,B,R)],
3362               m(min(A,B))   => [d(D), p(pgeq(A, R)), p(pgeq(B, R)), p(pmin(A,B,R)), a(A,B,R)],
3363               m(abs(A))     => [g(?(R)#>=0), d(D), p(pabs(A, R)), a(A,R)],
3364%               m(A/B)        => [skeleton(A,B,D,R,ptzdiv)],
3365               m(A//B)       => [skeleton(A,B,D,R,ptzdiv)],
3366               m(A div B)    => [skeleton(A,B,D,R,pdiv)],
3367               m(A rdiv B)   => [skeleton(A,B,D,R,prdiv)],
3368               m(A mod B)    => [skeleton(A,B,D,R,pmod)],
3369               m(A rem B)    => [skeleton(A,B,D,R,prem)],
3370               m(A^B)        => [d(D), p(pexp(A,B,R)), a(A,B,R)],
3371               % bitwise operations
3372               m(\A)         => [function(D,\,A,R)],
3373               m(msb(A))     => [function(D,msb,A,R)],
3374               m(lsb(A))     => [function(D,lsb,A,R)],
3375               m(popcount(A)) => [function(D,popcount,A,R)],
3376               m(A<<B)       => [function(D,<<,A,B,R)],
3377               m(A>>B)       => [function(D,>>,A,B,R)],
3378               m(A/\B)       => [function(D,/\,A,B,R)],
3379               m(A\/B)       => [function(D,\/,A,B,R)],
3380               m(A xor B)    => [function(D,xor,A,B,R)],
3381               g(true)       => [g(domain_error(clpfd_expression, E))]]
3382             ).
3383
3384% Again, we compile this to a predicate, parse_reified_clpfd//3. This
3385% time, it is a DCG that describes the list of auxiliary variables and
3386% propagators for the given expression, in addition to relating it to
3387% its reified (Boolean) finite domain variable and its Boolean
3388% definedness.
3389
3390make_parse_reified(Clauses) :-
3391        parse_reified_clauses(Clauses0),
3392        maplist(goals_goal_dcg, Clauses0, Clauses).
3393
3394goals_goal_dcg((Head --> Goals), Clause) :-
3395        list_goal(Goals, Body),
3396        expand_term((Head --> Body), Clause).
3397
3398parse_reified_clauses(Clauses) :-
3399        parse_reified(E, R, D, Matchers),
3400        maplist(parse_reified(E, R, D), Matchers, Clauses).
3401
3402parse_reified(E, R, D, Matcher, Clause) :-
3403        Matcher = (Condition0 => Goals0),
3404        phrase((reified_condition(Condition0, E, Head, Ds),
3405                reified_goals(Goals0, Ds)), Goals, [a(D)]),
3406        Clause = (parse_reified_clpfd(Head, R, D) --> Goals).
3407
3408reified_condition(g(Goal), E, E, []) --> [{Goal}, !].
3409reified_condition(?(E), _, ?(E), []) --> [!].
3410reified_condition(#(E), _, #(E), []) --> [!].
3411reified_condition(m(Match), _, Match0, Ds) -->
3412        [!],
3413        { copy_term(Match, Match0),
3414          term_variables(Match0, Vs0),
3415          term_variables(Match, Vs)
3416        },
3417        reified_variables(Vs0, Vs, Ds).
3418
3419reified_variables([], [], []) --> [].
3420reified_variables([V0|Vs0], [V|Vs], [D|Ds]) -->
3421        [parse_reified_clpfd(V0, V, D)],
3422        reified_variables(Vs0, Vs, Ds).
3423
3424reified_goals([], _) --> [].
3425reified_goals([G|Gs], Ds) --> reified_goal(G, Ds), reified_goals(Gs, Ds).
3426
3427reified_goal(d(D), Ds) -->
3428        (   { Ds = [X] } -> [{D=X}]
3429        ;   { Ds = [X,Y] } ->
3430            { phrase(reified_goal(p(reified_and(X,[],Y,[],D)), _), Gs),
3431              list_goal(Gs, Goal) },
3432            [( {X==1, Y==1} -> {D = 1} ; Goal )]
3433        ;   { domain_error(one_or_two_element_list, Ds) }
3434        ).
3435reified_goal(g(Goal), _) --> [{Goal}].
3436reified_goal(p(Vs, Prop), _) -->
3437        [{make_propagator(Prop, P)}],
3438        parse_init_dcg(Vs, P),
3439        [{trigger_once(P)}],
3440        [( { propagator_state(P, S), S == dead } -> [] ; [p(P)])].
3441reified_goal(p(Prop), Ds) -->
3442        { term_variables(Prop, Vs) },
3443        reified_goal(p(Vs,Prop), Ds).
3444reified_goal(function(D,Op,A,B,R), Ds) -->
3445        reified_goals([d(D),p(pfunction(Op,A,B,R)),a(A,B,R)], Ds).
3446reified_goal(function(D,Op,A,R), Ds) -->
3447        reified_goals([d(D),p(pfunction(Op,A,R)),a(A,R)], Ds).
3448reified_goal(skeleton(A,B,D,R,F), Ds) -->
3449        { Prop =.. [F,X,Y,Z] },
3450        reified_goals([d(D1),l(p(P)),g(make_propagator(Prop, P)),
3451                       p([A,B,D2,R], pskeleton(A,B,D2,[X,Y,Z]-P,R,F)),
3452                       p(reified_and(D1,[],D2,[],D)),a(D2),a(A,B,R)], Ds).
3453reified_goal(a(V), _)     --> [a(V)].
3454reified_goal(a(X,V), _)   --> [a(X,V)].
3455reified_goal(a(X,Y,V), _) --> [a(X,Y,V)].
3456reified_goal(l(L), _)     --> [[L]].
3457
3458parse_init_dcg([], _)     --> [].
3459parse_init_dcg([V|Vs], P) --> [{init_propagator(V, P)}], parse_init_dcg(Vs, P).
3460
3461%?- set_prolog_flag(answer_write_options, [portray(true)]),
3462%   clpfd:parse_reified_clauses(Cs), maplist(portray_clause, Cs).
3463
3464reify(E, B) :- reify(E, B, _).
3465
3466reify(Expr, B, Ps) :-
3467        (   acyclic_term(Expr), reifiable(Expr) -> phrase(reify(Expr, B), Ps)
3468        ;   domain_error(clpfd_reifiable_expression, Expr)
3469        ).
3470
3471reifiable(E)      :- var(E), non_monotonic(E).
3472reifiable(E)      :- integer(E), E in 0..1.
3473reifiable(?(E))   :- must_be_fd_integer(E).
3474reifiable(#(E))   :- must_be_fd_integer(E).
3475reifiable(V in _) :- fd_variable(V).
3476reifiable(Expr)   :-
3477        Expr =.. [Op,Left,Right],
3478        (   memberchk(Op, [#>=,#>,#=<,#<,#=,#\=])
3479        ;   memberchk(Op, [#==>,#<==,#<==>,#/\,#\/,#\]),
3480            reifiable(Left),
3481            reifiable(Right)
3482        ).
3483reifiable(#\ E) :- reifiable(E).
3484reifiable(tuples_in(Tuples, Relation)) :-
3485        must_be(list(list), Tuples),
3486        maplist(maplist(fd_variable), Tuples),
3487        must_be(list(list(integer)), Relation).
3488reifiable(finite_domain(V)) :- fd_variable(V).
3489
3490reify(E, B) --> { B in 0..1 }, reify_(E, B).
3491
3492reify_(E, B) --> { var(E), !, E = B }.
3493reify_(E, B) --> { integer(E), E = B }.
3494reify_(?(B), B) --> [].
3495reify_(#(B), B) --> [].
3496reify_(V in Drep, B) -->
3497        { drep_to_domain(Drep, Dom) },
3498        propagator_init_trigger(reified_in(V,Dom,B)),
3499        a(B).
3500reify_(tuples_in(Tuples, Relation), B) -->
3501        { maplist(relation_tuple_b_prop(Relation), Tuples, Bs, Ps),
3502          maplist(monotonic, Bs, Bs1),
3503          fold_statement(conjunction, Bs1, And),
3504          ?(B) #<==> And },
3505        propagator_init_trigger([B], tuples_not_in(Tuples, Relation, B)),
3506        kill_reified_tuples(Bs, Ps, Bs),
3507        list(Ps),
3508        as([B|Bs]).
3509reify_(finite_domain(V), B) -->
3510        propagator_init_trigger(reified_fd(V,B)),
3511        a(B).
3512reify_(L #>= R, B) --> arithmetic(L, R, B, reified_geq).
3513reify_(L #= R, B)  --> arithmetic(L, R, B, reified_eq).
3514reify_(L #\= R, B) --> arithmetic(L, R, B, reified_neq).
3515reify_(L #> R, B)  --> reify_(L #>= (R+1), B).
3516reify_(L #=< R, B) --> reify_(R #>= L, B).
3517reify_(L #< R, B)  --> reify_(R #>= (L+1), B).
3518reify_(L #==> R, B)  --> reify_((#\ L) #\/ R, B).
3519reify_(L #<== R, B)  --> reify_(R #==> L, B).
3520reify_(L #<==> R, B) --> reify_((L #==> R) #/\ (R #==> L), B).
3521reify_(L #\ R, B) --> reify_((L #\/ R) #/\ #\ (L #/\ R), B).
3522reify_(L #/\ R, B)   -->
3523        (   { conjunctive_neqs_var_drep(L #/\ R, V, D) } -> reify_(V in D, B)
3524        ;   boolean(L, R, B, reified_and)
3525        ).
3526reify_(L #\/ R, B) -->
3527        (   { disjunctive_eqs_var_drep(L #\/ R, V, D) } -> reify_(V in D, B)
3528        ;   boolean(L, R, B, reified_or)
3529        ).
3530reify_(#\ Q, B) -->
3531        reify(Q, QR),
3532        propagator_init_trigger(reified_not(QR,B)),
3533        a(B).
3534
3535arithmetic(L, R, B, Functor) -->
3536        { phrase((parse_reified_clpfd(L, LR, LD),
3537                  parse_reified_clpfd(R, RR, RD)), Ps),
3538          Prop =.. [Functor,LD,LR,RD,RR,Ps,B] },
3539        list(Ps),
3540        propagator_init_trigger([LD,LR,RD,RR,B], Prop),
3541        a(B).
3542
3543boolean(L, R, B, Functor) -->
3544        { reify(L, LR, Ps1), reify(R, RR, Ps2),
3545          Prop =.. [Functor,LR,Ps1,RR,Ps2,B] },
3546        list(Ps1), list(Ps2),
3547        propagator_init_trigger([LR,RR,B], Prop),
3548        a(LR, RR, B).
3549
3550list([])     --> [].
3551list([L|Ls]) --> [L], list(Ls).
3552
3553a(X,Y,B) -->
3554        (   { nonvar(X) } -> a(Y, B)
3555        ;   { nonvar(Y) } -> a(X, B)
3556        ;   [a(X,Y,B)]
3557        ).
3558
3559a(X, B) -->
3560        (   { var(X) } -> [a(X, B)]
3561        ;   a(B)
3562        ).
3563
3564a(B) -->
3565        (   { var(B) } -> [a(B)]
3566        ;   []
3567        ).
3568
3569as([])     --> [].
3570as([B|Bs]) --> a(B), as(Bs).
3571
3572kill_reified_tuples([], _, _) --> [].
3573kill_reified_tuples([B|Bs], Ps, All) -->
3574        propagator_init_trigger([B], kill_reified_tuples(B, Ps, All)),
3575        kill_reified_tuples(Bs, Ps, All).
3576
3577relation_tuple_b_prop(Relation, Tuple, B, p(Prop)) :-
3578        put_attr(R, clpfd_relation, Relation),
3579        make_propagator(reified_tuple_in(Tuple, R, B), Prop),
3580        tuple_freeze_(Tuple, Prop),
3581        init_propagator(B, Prop).
3582
3583
3584tuples_in_conjunction(Tuples, Relation, Conj) :-
3585        maplist(tuple_in_disjunction(Relation), Tuples, Disjs),
3586        fold_statement(conjunction, Disjs, Conj).
3587
3588tuple_in_disjunction(Relation, Tuple, Disj) :-
3589        maplist(tuple_in_conjunction(Tuple), Relation, Conjs),
3590        fold_statement(disjunction, Conjs, Disj).
3591
3592tuple_in_conjunction(Tuple, Element, Conj) :-
3593        maplist(var_eq, Tuple, Element, Eqs),
3594        fold_statement(conjunction, Eqs, Conj).
3595
3596fold_statement(Operation, List, Statement) :-
3597        (   List = [] -> Statement = 1
3598        ;   List = [First|Rest],
3599            foldl(Operation, Rest, First, Statement)
3600        ).
3601
3602conjunction(E, Conj, Conj #/\ E).
3603
3604disjunction(E, Disj, Disj #\/ E).
3605
3606var_eq(V, N, ?(V) #= N).
3607
3608% Match variables to created skeleton.
3609
3610skeleton(Vs, Vs-Prop) :-
3611        maplist(prop_init(Prop), Vs),
3612        trigger_once(Prop).
3613
3614/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3615   A drep is a user-accessible and visible domain representation. N,
3616   N..M, and D1 \/ D2 are dreps, if D1 and D2 are dreps.
3617- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3618
3619is_drep(N)      :- integer(N).
3620is_drep(N..M)   :- drep_bound(N), drep_bound(M), N \== sup, M \== inf.
3621is_drep(D1\/D2) :- is_drep(D1), is_drep(D2).
3622is_drep({AI})   :- is_and_integers(AI).
3623is_drep(\D)     :- is_drep(D).
3624
3625is_and_integers(I)     :- integer(I).
3626is_and_integers((A,B)) :- is_and_integers(A), is_and_integers(B).
3627
3628drep_bound(I)   :- integer(I).
3629drep_bound(sup).
3630drep_bound(inf).
3631
3632drep_to_intervals(I)        --> { integer(I) }, [n(I)-n(I)].
3633drep_to_intervals(N..M)     -->
3634        (   { defaulty_to_bound(N, N1), defaulty_to_bound(M, M1),
3635              N1 cis_leq M1} -> [N1-M1]
3636        ;   []
3637        ).
3638drep_to_intervals(D1 \/ D2) -->
3639        drep_to_intervals(D1), drep_to_intervals(D2).
3640drep_to_intervals(\D0) -->
3641        { drep_to_domain(D0, D1),
3642          domain_complement(D1, D),
3643          domain_to_drep(D, Drep) },
3644        drep_to_intervals(Drep).
3645drep_to_intervals({AI}) -->
3646        and_integers_(AI).
3647
3648and_integers_(I)     --> { integer(I) }, [n(I)-n(I)].
3649and_integers_((A,B)) --> and_integers_(A), and_integers_(B).
3650
3651drep_to_domain(DR, D) :-
3652        must_be(ground, DR),
3653        (   is_drep(DR) -> true
3654        ;   domain_error(clpfd_domain, DR)
3655        ),
3656        phrase(drep_to_intervals(DR), Is0),
3657        merge_intervals(Is0, Is1),
3658        intervals_to_domain(Is1, D).
3659
3660merge_intervals(Is0, Is) :-
3661        keysort(Is0, Is1),
3662        merge_overlapping(Is1, Is).
3663
3664merge_overlapping([], []).
3665merge_overlapping([A-B0|ABs0], [A-B|ABs]) :-
3666        merge_remaining(ABs0, B0, B, Rest),
3667        merge_overlapping(Rest, ABs).
3668
3669merge_remaining([], B, B, []).
3670merge_remaining([N-M|NMs], B0, B, Rest) :-
3671        Next cis B0 + n(1),
3672        (   N cis_gt Next -> B = B0, Rest = [N-M|NMs]
3673        ;   B1 cis max(B0,M),
3674            merge_remaining(NMs, B1, B, Rest)
3675        ).
3676
3677domain(V, Dom) :-
3678        (   fd_get(V, Dom0, VPs) ->
3679            domains_intersection(Dom, Dom0, Dom1),
3680            %format("intersected\n: ~w\n ~w\n==> ~w\n\n", [Dom,Dom0,Dom1]),
3681            fd_put(V, Dom1, VPs),
3682            do_queue,
3683            reinforce(V)
3684        ;   domain_contains(Dom, V)
3685        ).
3686
3687domains([], _).
3688domains([V|Vs], D) :- domain(V, D), domains(Vs, D).
3689
3690props_number(fd_props(Gs,Bs,Os), N) :-
3691        length(Gs, N1),
3692        length(Bs, N2),
3693        length(Os, N3),
3694        N is N1 + N2 + N3.
3695
3696fd_get(X, Dom, Ps) :-
3697        (   get_attr(X, clpfd, Attr) -> Attr = clpfd_attr(_,_,_,Dom,Ps)
3698        ;   var(X) -> default_domain(Dom), Ps = fd_props([],[],[])
3699        ).
3700
3701fd_get(X, Dom, Inf, Sup, Ps) :-
3702        fd_get(X, Dom, Ps),
3703        domain_infimum(Dom, Inf),
3704        domain_supremum(Dom, Sup).
3705
3706/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3707   By default, propagation always terminates. Currently, this is
3708   ensured by allowing the left and right boundaries, as well as the
3709   distance between the smallest and largest number occurring in the
3710   domain representation to be changed at most once after a constraint
3711   is posted, unless the domain is bounded. Set the experimental
3712   Prolog flag 'clpfd_propagation' to 'full' to make the solver
3713   propagate as much as possible. This can make queries
3714   non-terminating, like: X #> abs(X), or: X #> Y, Y #> X, X #> 0.
3715   Importantly, it can also make labeling non-terminating, as in:
3716
3717   ?- B #==> X #> abs(X), indomain(B).
3718- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3719
3720fd_put(X, Dom, Ps) :-
3721        (   current_prolog_flag(clpfd_propagation, full) ->
3722            put_full(X, Dom, Ps)
3723        ;   put_terminating(X, Dom, Ps)
3724        ).
3725
3726put_terminating(X, Dom, Ps) :-
3727        Dom \== empty,
3728        (   Dom = from_to(F, F) -> F = n(X)
3729        ;   (   get_attr(X, clpfd, Attr) ->
3730                Attr = clpfd_attr(Left,Right,Spread,OldDom, _OldPs),
3731                put_attr(X, clpfd, clpfd_attr(Left,Right,Spread,Dom,Ps)),
3732                (   OldDom == Dom -> true
3733                ;   (   Left == (.) -> Bounded = yes
3734                    ;   domain_infimum(Dom, Inf), domain_supremum(Dom, Sup),
3735                        (   Inf = n(_), Sup = n(_) ->
3736                            Bounded = yes
3737                        ;   Bounded = no
3738                        )
3739                    ),
3740                    (   Bounded == yes ->
3741                        put_attr(X, clpfd, clpfd_attr(.,.,.,Dom,Ps)),
3742                        trigger_props(Ps, X, OldDom, Dom)
3743                    ;   % infinite domain; consider border and spread changes
3744                        domain_infimum(OldDom, OldInf),
3745                        (   Inf == OldInf -> LeftP = Left
3746                        ;   LeftP = yes
3747                        ),
3748                        domain_supremum(OldDom, OldSup),
3749                        (   Sup == OldSup -> RightP = Right
3750                        ;   RightP = yes
3751                        ),
3752                        domain_spread(OldDom, OldSpread),
3753                        domain_spread(Dom, NewSpread),
3754                        (   NewSpread == OldSpread -> SpreadP = Spread
3755                        ;   NewSpread cis_lt OldSpread -> SpreadP = no
3756                        ;   SpreadP = yes
3757                        ),
3758                        put_attr(X, clpfd, clpfd_attr(LeftP,RightP,SpreadP,Dom,Ps)),
3759                        (   RightP == yes, Right = yes -> true
3760                        ;   LeftP == yes, Left = yes -> true
3761                        ;   SpreadP == yes, Spread = yes -> true
3762                        ;   trigger_props(Ps, X, OldDom, Dom)
3763                        )
3764                    )
3765                )
3766            ;   var(X) ->
3767                put_attr(X, clpfd, clpfd_attr(no,no,no,Dom, Ps))
3768            ;   true
3769            )
3770        ).
3771
3772domain_spread(Dom, Spread) :-
3773        domain_smallest_finite(Dom, S),
3774        domain_largest_finite(Dom, L),
3775        Spread cis L - S.
3776
3777smallest_finite(inf, Y, Y).
3778smallest_finite(n(N), _, n(N)).
3779
3780domain_smallest_finite(from_to(F,T), S)   :- smallest_finite(F, T, S).
3781domain_smallest_finite(split(_, L, _), S) :- domain_smallest_finite(L, S).
3782
3783largest_finite(sup, Y, Y).
3784largest_finite(n(N), _, n(N)).
3785
3786domain_largest_finite(from_to(F,T), L)   :- largest_finite(T, F, L).
3787domain_largest_finite(split(_, _, R), L) :- domain_largest_finite(R, L).
3788
3789/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3790   With terminating propagation, all relevant constraints get a
3791   propagation opportunity whenever a new constraint is posted.
3792- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3793
3794reinforce(X) :-
3795        (   current_prolog_flag(clpfd_propagation, full) ->
3796            % full propagation propagates everything in any case
3797            true
3798        ;   term_variables(X, Vs),
3799            maplist(reinforce_, Vs),
3800            do_queue
3801        ).
3802
3803reinforce_(X) :-
3804        (   fd_var(X), fd_get(X, Dom, Ps) ->
3805            put_full(X, Dom, Ps)
3806        ;   true
3807        ).
3808
3809put_full(X, Dom, Ps) :-
3810        Dom \== empty,
3811        (   Dom = from_to(F, F) -> F = n(X)
3812        ;   (   get_attr(X, clpfd, Attr) ->
3813                Attr = clpfd_attr(_,_,_,OldDom, _OldPs),
3814                put_attr(X, clpfd, clpfd_attr(no,no,no,Dom, Ps)),
3815                %format("putting dom: ~w\n", [Dom]),
3816                (   OldDom == Dom -> true
3817                ;   trigger_props(Ps, X, OldDom, Dom)
3818                )
3819            ;   var(X) -> %format('\t~w in ~w .. ~w\n',[X,L,U]),
3820                put_attr(X, clpfd, clpfd_attr(no,no,no,Dom, Ps))
3821            ;   true
3822            )
3823        ).
3824
3825/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3826   A propagator is a term of the form propagator(C, State), where C
3827   represents a constraint, and State is a free variable that can be
3828   used to destructively change the state of the propagator via
3829   attributes. This can be used to avoid redundant invocation of the
3830   same propagator, or to disable the propagator.
3831- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3832
3833make_propagator(C, propagator(C, _)).
3834
3835propagator_state(propagator(_,S), S).
3836
3837trigger_props(fd_props(Gs,Bs,Os), X, D0, D) :-
3838        (   ground(X) ->
3839            trigger_props_(Gs),
3840            trigger_props_(Bs)
3841        ;   Bs \== [] ->
3842            domain_infimum(D0, I0),
3843            domain_infimum(D, I),
3844            (   I == I0 ->
3845                domain_supremum(D0, S0),
3846                domain_supremum(D, S),
3847                (   S == S0 -> true
3848                ;   trigger_props_(Bs)
3849                )
3850            ;   trigger_props_(Bs)
3851            )
3852        ;   true
3853        ),
3854        trigger_props_(Os).
3855
3856trigger_props(fd_props(Gs,Bs,Os), X) :-
3857        trigger_props_(Os),
3858        trigger_props_(Bs),
3859        (   ground(X) ->
3860            trigger_props_(Gs)
3861        ;   true
3862        ).
3863
3864trigger_props(fd_props(Gs,Bs,Os)) :-
3865        trigger_props_(Gs),
3866        trigger_props_(Bs),
3867        trigger_props_(Os).
3868
3869trigger_props_([]).
3870trigger_props_([P|Ps]) :- trigger_prop(P), trigger_props_(Ps).
3871
3872trigger_prop(Propagator) :-
3873        propagator_state(Propagator, State),
3874        (   State == dead -> true
3875        ;   get_attr(State, clpfd_aux, queued) -> true
3876        ;   b_getval('$clpfd_current_propagator', C), C == State -> true
3877        ;   % passive
3878            % format("triggering: ~w\n", [Propagator]),
3879            put_attr(State, clpfd_aux, queued),
3880            (   arg(1, Propagator, C), functor(C, F, _), global_constraint(F) ->
3881                push_queue(Propagator, 2)
3882            ;   push_queue(Propagator, 1)
3883            )
3884        ).
3885
3886kill(State) :- del_attr(State, clpfd_aux), State = dead.
3887
3888kill(State, Ps) :-
3889        kill(State),
3890        maplist(kill_entailed, Ps).
3891
3892kill_entailed(p(Prop)) :-
3893        propagator_state(Prop, State),
3894        kill(State).
3895kill_entailed(a(V)) :-
3896        del_attr(V, clpfd).
3897kill_entailed(a(X,B)) :-
3898        (   X == B -> true
3899        ;   del_attr(B, clpfd)
3900        ).
3901kill_entailed(a(X,Y,B)) :-
3902        (   X == B -> true
3903        ;   Y == B -> true
3904        ;   del_attr(B, clpfd)
3905        ).
3906
3907no_reactivation(rel_tuple(_,_)).
3908no_reactivation(pdistinct(_)).
3909no_reactivation(pgcc(_,_,_)).
3910no_reactivation(pgcc_single(_,_)).
3911%no_reactivation(scalar_product(_,_,_,_)).
3912
3913activate_propagator(propagator(P,State)) :-
3914        % format("running: ~w\n", [P]),
3915        del_attr(State, clpfd_aux),
3916        (   no_reactivation(P) ->
3917            b_setval('$clpfd_current_propagator', State),
3918            run_propagator(P, State),
3919            b_setval('$clpfd_current_propagator', [])
3920        ;   run_propagator(P, State)
3921        ).
3922
3923disable_queue :- b_setval('$clpfd_queue_status', disabled).
3924enable_queue  :- b_setval('$clpfd_queue_status', enabled).
3925
3926portray_propagator(propagator(P,_), F) :- functor(P, F, _).
3927
3928portray_queue(V, []) :- var(V), !.
3929portray_queue([P|Ps], [F|Fs]) :-
3930        portray_propagator(P, F),
3931        portray_queue(Ps, Fs).
3932
3933do_queue :-
3934        % b_getval('$clpfd_queue', H-_),
3935        % portray_queue(H, Port),
3936        % format("queue: ~w\n", [Port]),
3937        (   b_getval('$clpfd_queue_status', enabled) ->
3938            (   fetch_propagator(Propagator) ->
3939                activate_propagator(Propagator),
3940                do_queue
3941            ;   true
3942            )
3943        ;   true
3944        ).
3945
3946init_propagator(Var, Prop) :-
3947        (   fd_get(Var, Dom, Ps0) ->
3948            insert_propagator(Prop, Ps0, Ps),
3949            fd_put(Var, Dom, Ps)
3950        ;   true
3951        ).
3952
3953constraint_wake(pneq, ground).
3954constraint_wake(x_neq_y_plus_z, ground).
3955constraint_wake(absdiff_neq, ground).
3956constraint_wake(pdifferent, ground).
3957constraint_wake(pexclude, ground).
3958constraint_wake(scalar_product_neq, ground).
3959
3960constraint_wake(x_leq_y_plus_c, bounds).
3961constraint_wake(scalar_product_eq, bounds).
3962constraint_wake(scalar_product_leq, bounds).
3963constraint_wake(pplus, bounds).
3964constraint_wake(pgeq, bounds).
3965constraint_wake(pgcc_single, bounds).
3966constraint_wake(pgcc_check_single, bounds).
3967
3968global_constraint(pdistinct).
3969global_constraint(pgcc).
3970global_constraint(pgcc_single).
3971global_constraint(pcircuit).
3972%global_constraint(rel_tuple).
3973%global_constraint(scalar_product_eq).
3974
3975insert_propagator(Prop, Ps0, Ps) :-
3976        Ps0 = fd_props(Gs,Bs,Os),
3977        arg(1, Prop, Constraint),
3978        functor(Constraint, F, _),
3979        (   constraint_wake(F, ground) ->
3980            Ps = fd_props([Prop|Gs], Bs, Os)
3981        ;   constraint_wake(F, bounds) ->
3982            Ps = fd_props(Gs, [Prop|Bs], Os)
3983        ;   Ps = fd_props(Gs, Bs, [Prop|Os])
3984        ).
3985
3986%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3987
3988%% lex_chain(+Lists)
3989%
3990% Lists are lexicographically non-decreasing.
3991
3992lex_chain(Lss) :-
3993        must_be(list(list), Lss),
3994        maplist(maplist(fd_variable), Lss),
3995        (   Lss == [] -> true
3996        ;   Lss = [First|Rest],
3997            make_propagator(presidual(lex_chain(Lss)), Prop),
3998            foldl(lex_chain_(Prop), Rest, First, _)
3999        ).
4000
4001lex_chain_(Prop, Ls, Prev, Ls) :-
4002        maplist(prop_init(Prop), Ls),
4003        lex_le(Prev, Ls).
4004
4005lex_le([], []).
4006lex_le([V1|V1s], [V2|V2s]) :-
4007        ?(V1) #=< ?(V2),
4008        (   integer(V1) ->
4009            (   integer(V2) ->
4010                (   V1 =:= V2 -> lex_le(V1s, V2s) ;  true )
4011            ;   freeze(V2, lex_le([V1|V1s], [V2|V2s]))
4012            )
4013        ;   freeze(V1, lex_le([V1|V1s], [V2|V2s]))
4014        ).
4015
4016%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4017
4018
4019%% tuples_in(+Tuples, +Relation).
4020%
4021% True iff all Tuples are elements of Relation. Each element of the
4022% list Tuples is a list of integers or finite domain variables.
4023% Relation is a list of lists of integers. Arbitrary finite relations,
4024% such as compatibility tables, can be modeled in this way. For
4025% example, if 1 is compatible with 2 and 5, and 4 is compatible with 0
4026% and 3:
4027%
4028% ==
4029% ?- tuples_in([[X,Y]], [[1,2],[1,5],[4,0],[4,3]]), X = 4.
4030% X = 4,
4031% Y in 0\/3.
4032% ==
4033%
4034% As another example, consider a train schedule represented as a list
4035% of quadruples, denoting departure and arrival places and times for
4036% each train. In the following program, Ps is a feasible journey of
4037% length 3 from A to D via trains that are part of the given schedule.
4038%
4039% ==
4040% trains([[1,2,0,1],
4041%         [2,3,4,5],
4042%         [2,3,0,1],
4043%         [3,4,5,6],
4044%         [3,4,2,3],
4045%         [3,4,8,9]]).
4046%
4047% threepath(A, D, Ps) :-
4048%         Ps = [[A,B,_T0,T1],[B,C,T2,T3],[C,D,T4,_T5]],
4049%         T2 #> T1,
4050%         T4 #> T3,
4051%         trains(Ts),
4052%         tuples_in(Ps, Ts).
4053% ==
4054%
4055% In this example, the unique solution is found without labeling:
4056%
4057% ==
4058% ?- threepath(1, 4, Ps).
4059% Ps = [[1, 2, 0, 1], [2, 3, 4, 5], [3, 4, 8, 9]].
4060% ==
4061
4062tuples_in(Tuples, Relation) :-
4063        must_be(list(list), Tuples),
4064        maplist(maplist(fd_variable), Tuples),
4065        must_be(list(list(integer)), Relation),
4066        maplist(relation_tuple(Relation), Tuples),
4067        do_queue.
4068
4069relation_tuple(Relation, Tuple) :-
4070        relation_unifiable(Relation, Tuple, Us, _, _),
4071        (   ground(Tuple) -> memberchk(Tuple, Relation)
4072        ;   tuple_domain(Tuple, Us),
4073            (   Tuple = [_,_|_] -> tuple_freeze(Tuple, Us)
4074            ;   true
4075            )
4076        ).
4077
4078tuple_domain([], _).
4079tuple_domain([T|Ts], Relation0) :-
4080        maplist(list_first_rest, Relation0, Firsts, Relation1),
4081        (   var(T) ->
4082            (   Firsts = [Unique] -> T = Unique
4083            ;   list_to_domain(Firsts, FDom),
4084                fd_get(T, TDom, TPs),
4085                domains_intersection(TDom, FDom, TDom1),
4086                fd_put(T, TDom1, TPs)
4087            )
4088        ;   true
4089        ),
4090        tuple_domain(Ts, Relation1).
4091
4092tuple_freeze(Tuple, Relation) :-
4093        put_attr(R, clpfd_relation, Relation),
4094        make_propagator(rel_tuple(R, Tuple), Prop),
4095        tuple_freeze_(Tuple, Prop).
4096
4097tuple_freeze_([], _).
4098tuple_freeze_([T|Ts], Prop) :-
4099        (   var(T) ->
4100            init_propagator(T, Prop),
4101            trigger_prop(Prop)
4102        ;   true
4103        ),
4104        tuple_freeze_(Ts, Prop).
4105
4106relation_unifiable([], _, [], Changed, Changed).
4107relation_unifiable([R|Rs], Tuple, Us, Changed0, Changed) :-
4108        (   all_in_domain(R, Tuple) ->
4109            Us = [R|Rest],
4110            relation_unifiable(Rs, Tuple, Rest, Changed0, Changed)
4111        ;   relation_unifiable(Rs, Tuple, Us, true, Changed)
4112        ).
4113
4114all_in_domain([], []).
4115all_in_domain([A|As], [T|Ts]) :-
4116        (   fd_get(T, Dom, _) ->
4117            domain_contains(Dom, A)
4118        ;   T =:= A
4119        ),
4120        all_in_domain(As, Ts).
4121
4122%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4123
4124% trivial propagator, used only to remember pending constraints
4125run_propagator(presidual(_), _).
4126
4127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4128run_propagator(pdifferent(Left,Right,X,_), MState) :-
4129        run_propagator(pexclude(Left,Right,X), MState).
4130
4131run_propagator(weak_distinct(Left,Right,X,_), _MState) :-
4132        (   ground(X) ->
4133            disable_queue,
4134            exclude_fire(Left, Right, X),
4135            enable_queue
4136        ;   outof_reducer(Left, Right, X)
4137            %(   var(X) -> kill_if_isolated(Left, Right, X, MState)
4138            %;   true
4139            %)
4140        ).
4141
4142run_propagator(pexclude(Left,Right,X), _) :-
4143        (   ground(X) ->
4144            disable_queue,
4145            exclude_fire(Left, Right, X),
4146            enable_queue
4147        ;   true
4148        ).
4149
4150run_propagator(pdistinct(Ls), _MState) :-
4151        distinct(Ls).
4152
4153run_propagator(check_distinct(Left,Right,X), _) :-
4154        \+ list_contains(Left, X),
4155        \+ list_contains(Right, X).
4156
4157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4158
4159run_propagator(pelement(N, Is, V), MState) :-
4160        (   fd_get(N, NDom, _) ->
4161            (   fd_get(V, VDom, VPs) ->
4162                integers_remaining(Is, 1, NDom, empty, VDom1),
4163                domains_intersection(VDom, VDom1, VDom2),
4164                fd_put(V, VDom2, VPs)
4165            ;   true
4166            )
4167        ;   kill(MState), nth1(N, Is, V)
4168        ).
4169
4170%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4171
4172run_propagator(pgcc_single(Vs, Pairs), _) :- gcc_global(Vs, Pairs).
4173
4174run_propagator(pgcc_check_single(Pairs), _) :- gcc_check(Pairs).
4175
4176run_propagator(pgcc_check(Pairs), _) :- gcc_check(Pairs).
4177
4178run_propagator(pgcc(Vs, _, Pairs), _) :- gcc_global(Vs, Pairs).
4179
4180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4181
4182run_propagator(pcircuit(Vs), _MState) :-
4183        distinct(Vs),
4184        propagate_circuit(Vs).
4185
4186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4187run_propagator(pneq(A, B), MState) :-
4188        (   nonvar(A) ->
4189            (   nonvar(B) -> A =\= B, kill(MState)
4190            ;   fd_get(B, BD0, BExp0),
4191                domain_remove(BD0, A, BD1),
4192                kill(MState),
4193                fd_put(B, BD1, BExp0)
4194            )
4195        ;   nonvar(B) -> run_propagator(pneq(B, A), MState)
4196        ;   A \== B,
4197            fd_get(A, _, AI, AS, _), fd_get(B, _, BI, BS, _),
4198            (   AS cis_lt BI -> kill(MState)
4199            ;   AI cis_gt BS -> kill(MState)
4200            ;   true
4201            )
4202        ).
4203
4204%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4205run_propagator(pgeq(A,B), MState) :-
4206        (   A == B -> kill(MState)
4207        ;   nonvar(A) ->
4208            (   nonvar(B) -> kill(MState), A >= B
4209            ;   fd_get(B, BD, BPs),
4210                domain_remove_greater_than(BD, A, BD1),
4211                kill(MState),
4212                fd_put(B, BD1, BPs)
4213            )
4214        ;   nonvar(B) ->
4215            fd_get(A, AD, APs),
4216            domain_remove_smaller_than(AD, B, AD1),
4217            kill(MState),
4218            fd_put(A, AD1, APs)
4219        ;   fd_get(A, AD, AL, AU, APs),
4220            fd_get(B, _, BL, BU, _),
4221            AU cis_geq BL,
4222            (   AL cis_geq BU -> kill(MState)
4223            ;   AU == BL -> kill(MState), A = B
4224            ;   NAL cis max(AL,BL),
4225                domains_intersection(AD, from_to(NAL,AU), NAD),
4226                fd_put(A, NAD, APs),
4227                (   fd_get(B, BD2, BL2, BU2, BPs2) ->
4228                    NBU cis min(BU2, AU),
4229                    domains_intersection(BD2, from_to(BL2,NBU), NBD),
4230                    fd_put(B, NBD, BPs2)
4231                ;   true
4232                )
4233            )
4234        ).
4235
4236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4237
4238run_propagator(rel_tuple(R, Tuple), MState) :-
4239        get_attr(R, clpfd_relation, Relation),
4240        (   ground(Tuple) -> kill(MState), memberchk(Tuple, Relation)
4241        ;   relation_unifiable(Relation, Tuple, Us, false, Changed),
4242            Us = [_|_],
4243            (   Tuple = [First,Second], ( ground(First) ; ground(Second) ) ->
4244                kill(MState)
4245            ;   true
4246            ),
4247            (   Us = [Single] -> kill(MState), Single = Tuple
4248            ;   Changed ->
4249                put_attr(R, clpfd_relation, Us),
4250                disable_queue,
4251                tuple_domain(Tuple, Us),
4252                enable_queue
4253            ;   true
4254            )
4255        ).
4256
4257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4258
4259run_propagator(pserialized(S_I, D_I, S_J, D_J, _), MState) :-
4260        (   nonvar(S_I), nonvar(S_J) ->
4261            kill(MState),
4262            (   S_I + D_I =< S_J -> true
4263            ;   S_J + D_J =< S_I -> true
4264            ;   false
4265            )
4266        ;   serialize_lower_upper(S_I, D_I, S_J, D_J, MState),
4267            serialize_lower_upper(S_J, D_J, S_I, D_I, MState)
4268        ).
4269
4270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4271
4272% abs(X-Y) #\= C
4273run_propagator(absdiff_neq(X,Y,C), MState) :-
4274        (   C < 0 -> kill(MState)
4275        ;   nonvar(X) ->
4276            kill(MState),
4277            (   nonvar(Y) -> abs(X - Y) =\= C
4278            ;   V1 is X - C, neq_num(Y, V1),
4279                V2 is C + X, neq_num(Y, V2)
4280            )
4281        ;   nonvar(Y) -> kill(MState),
4282            V1 is C + Y, neq_num(X, V1),
4283            V2 is Y - C, neq_num(X, V2)
4284        ;   true
4285        ).
4286
4287% abs(X-Y) #>= C
4288run_propagator(absdiff_geq(X,Y,C), MState) :-
4289        (   C =< 0 -> kill(MState)
4290        ;   nonvar(X) ->
4291            kill(MState),
4292            (   nonvar(Y) -> abs(X-Y) >= C
4293            ;   P1 is X - C, P2 is X + C,
4294                Y in inf..P1 \/ P2..sup
4295            )
4296        ;   nonvar(Y) ->
4297            kill(MState),
4298            P1 is Y - C, P2 is Y + C,
4299            X in inf..P1 \/ P2..sup
4300        ;   true
4301        ).
4302
4303% X #\= Y + Z
4304run_propagator(x_neq_y_plus_z(X,Y,Z), MState) :-
4305        (   nonvar(X) ->
4306            (   nonvar(Y) ->
4307                (   nonvar(Z) -> kill(MState), X =\= Y + Z
4308                ;   kill(MState), XY is X - Y, neq_num(Z, XY)
4309                )
4310            ;   nonvar(Z) -> kill(MState), XZ is X - Z, neq_num(Y, XZ)
4311            ;   true
4312            )
4313        ;   nonvar(Y) ->
4314            (   nonvar(Z) ->
4315                kill(MState), YZ is Y + Z, neq_num(X, YZ)
4316            ;   Y =:= 0 -> kill(MState), neq(X, Z)
4317            ;   true
4318            )
4319        ;   Z == 0 -> kill(MState), neq(X, Y)
4320        ;   true
4321        ).
4322
4323% X #=< Y + C
4324run_propagator(x_leq_y_plus_c(X,Y,C), MState) :-
4325        (   nonvar(X) ->
4326            (   nonvar(Y) -> kill(MState), X =< Y + C
4327            ;   kill(MState),
4328                R is X - C,
4329                fd_get(Y, YD, YPs),
4330                domain_remove_smaller_than(YD, R, YD1),
4331                fd_put(Y, YD1, YPs)
4332            )
4333        ;   nonvar(Y) ->
4334            kill(MState),
4335            R is Y + C,
4336            fd_get(X, XD, XPs),
4337            domain_remove_greater_than(XD, R, XD1),
4338            fd_put(X, XD1, XPs)
4339        ;   (   X == Y -> C >= 0, kill(MState)
4340            ;   fd_get(Y, YD, _),
4341                (   domain_supremum(YD, n(YSup)) ->
4342                    YS1 is YSup + C,
4343                    fd_get(X, XD, XPs),
4344                    domain_remove_greater_than(XD, YS1, XD1),
4345                    fd_put(X, XD1, XPs)
4346                ;   true
4347                ),
4348                (   fd_get(X, XD2, _), domain_infimum(XD2, n(XInf)) ->
4349                    XI1 is XInf - C,
4350                    (   fd_get(Y, YD1, YPs1) ->
4351                        domain_remove_smaller_than(YD1, XI1, YD2),
4352                        (   domain_infimum(YD2, n(YInf)),
4353                            domain_supremum(XD2, n(XSup)),
4354                            XSup =< YInf + C ->
4355                            kill(MState)
4356                        ;   true
4357                        ),
4358                        fd_put(Y, YD2, YPs1)
4359                    ;   true
4360                    )
4361                ;   true
4362                )
4363            )
4364        ).
4365
4366run_propagator(scalar_product_neq(Cs0,Vs0,P0), MState) :-
4367        coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I),
4368        P is P0 - I,
4369        (   Vs = [] -> kill(MState), P =\= 0
4370        ;   Vs = [V], Cs = [C] ->
4371            kill(MState),
4372            (   C =:= 1 -> neq_num(V, P)
4373            ;   C*V #\= P
4374            )
4375        ;   Cs == [1,-1] -> kill(MState), Vs = [A,B], x_neq_y_plus_z(A, B, P)
4376        ;   Cs == [-1,1] -> kill(MState), Vs = [A,B], x_neq_y_plus_z(B, A, P)
4377        ;   P =:= 0, Cs = [1,1,-1] ->
4378            kill(MState), Vs = [A,B,C], x_neq_y_plus_z(C, A, B)
4379        ;   P =:= 0, Cs = [1,-1,1] ->
4380            kill(MState), Vs = [A,B,C], x_neq_y_plus_z(B, A, C)
4381        ;   P =:= 0, Cs = [-1,1,1] ->
4382            kill(MState), Vs = [A,B,C], x_neq_y_plus_z(A, B, C)
4383        ;   true
4384        ).
4385
4386run_propagator(scalar_product_leq(Cs0,Vs0,P0), MState) :-
4387        coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I),
4388        P is P0 - I,
4389        (   Vs = [] -> kill(MState), P >= 0
4390        ;   sum_finite_domains(Cs, Vs, Infs, Sups, 0, 0, Inf, Sup),
4391            D1 is P - Inf,
4392            disable_queue,
4393            (   Infs == [], Sups == [] ->
4394                Inf =< P,
4395                (   Sup =< P -> kill(MState)
4396                ;   remove_dist_upper_leq(Cs, Vs, D1)
4397                )
4398            ;   Infs == [] -> Inf =< P, remove_dist_upper(Sups, D1)
4399            ;   Sups = [_], Infs = [_] ->
4400                remove_upper(Infs, D1)
4401            ;   Infs = [_] -> remove_upper(Infs, D1)
4402            ;   true
4403            ),
4404            enable_queue
4405        ).
4406
4407run_propagator(scalar_product_eq(Cs0,Vs0,P0), MState) :-
4408        coeffs_variables_const(Cs0, Vs0, Cs, Vs, 0, I),
4409        P is P0 - I,
4410        (   Vs = [] -> kill(MState), P =:= 0
4411        ;   Vs = [V], Cs = [C] -> kill(MState), P mod C =:= 0, V is P // C
4412        ;   Cs == [1,1] -> kill(MState), Vs = [A,B], A + B #= P
4413        ;   Cs == [1,-1] -> kill(MState), Vs = [A,B], A #= P + B
4414        ;   Cs == [-1,1] -> kill(MState), Vs = [A,B], B #= P + A
4415        ;   Cs == [-1,-1] -> kill(MState), Vs = [A,B], P1 is -P, A + B #= P1
4416        ;   P =:= 0, Cs == [1,1,-1] -> kill(MState), Vs = [A,B,C], A + B #= C
4417        ;   P =:= 0, Cs == [1,-1,1] -> kill(MState), Vs = [A,B,C], A + C #= B
4418        ;   P =:= 0, Cs == [-1,1,1] -> kill(MState), Vs = [A,B,C], B + C #= A
4419        ;   sum_finite_domains(Cs, Vs, Infs, Sups, 0, 0, Inf, Sup),
4420            % nl, writeln(Infs-Sups-Inf-Sup),
4421            D1 is P - Inf,
4422            D2 is Sup - P,
4423            disable_queue,
4424            (   Infs == [], Sups == [] ->
4425                between(Inf, Sup, P),
4426                remove_dist_upper_lower(Cs, Vs, D1, D2)
4427            ;   Sups = [] -> P =< Sup, remove_dist_lower(Infs, D2)
4428            ;   Infs = [] -> Inf =< P, remove_dist_upper(Sups, D1)
4429            ;   Sups = [_], Infs = [_] ->
4430                remove_lower(Sups, D2),
4431                remove_upper(Infs, D1)
4432            ;   Infs = [_] -> remove_upper(Infs, D1)
4433            ;   Sups = [_] -> remove_lower(Sups, D2)
4434            ;   true
4435            ),
4436            enable_queue
4437        ).
4438
4439% X + Y = Z
4440run_propagator(pplus(X,Y,Z), MState) :-
4441        (   nonvar(X) ->
4442            (   X =:= 0 -> kill(MState), Y = Z
4443            ;   Y == Z -> kill(MState), X =:= 0
4444            ;   nonvar(Y) -> kill(MState), Z is X + Y
4445            ;   nonvar(Z) -> kill(MState), Y is Z - X
4446            ;   fd_get(Z, ZD, ZPs),
4447                fd_get(Y, YD, _),
4448                domain_shift(YD, X, Shifted_YD),
4449                domains_intersection(ZD, Shifted_YD, ZD1),
4450                fd_put(Z, ZD1, ZPs),
4451                (   fd_get(Y, YD1, YPs) ->
4452                    O is -X,
4453                    domain_shift(ZD1, O, YD2),
4454                    domains_intersection(YD1, YD2, YD3),
4455                    fd_put(Y, YD3, YPs)
4456                ;   true
4457                )
4458            )
4459        ;   nonvar(Y) -> run_propagator(pplus(Y,X,Z), MState)
4460        ;   nonvar(Z) ->
4461            (   X == Y -> kill(MState), even(Z), X is Z // 2
4462            ;   fd_get(X, XD, _),
4463                fd_get(Y, YD, YPs),
4464                domain_negate(XD, XDN),
4465                domain_shift(XDN, Z, YD1),
4466                domains_intersection(YD, YD1, YD2),
4467                fd_put(Y, YD2, YPs),
4468                (   fd_get(X, XD1, XPs) ->
4469                    domain_negate(YD2, YD2N),
4470                    domain_shift(YD2N, Z, XD2),
4471                    domains_intersection(XD1, XD2, XD3),
4472                    fd_put(X, XD3, XPs)
4473                ;   true
4474                )
4475            )
4476        ;   (   X == Y -> kill(MState), 2*X #= Z
4477            ;   X == Z -> kill(MState), Y = 0
4478            ;   Y == Z -> kill(MState), X = 0
4479            ;   fd_get(X, XD, XL, XU, XPs),
4480                fd_get(Y, _, YL, YU, _),
4481                fd_get(Z, _, ZL, ZU, _),
4482                NXL cis max(XL, ZL-YU),
4483                NXU cis min(XU, ZU-YL),
4484                update_bounds(X, XD, XPs, XL, XU, NXL, NXU),
4485                (   fd_get(Y, YD2, YL2, YU2, YPs2) ->
4486                    NYL cis max(YL2, ZL-NXU),
4487                    NYU cis min(YU2, ZU-NXL),
4488                    update_bounds(Y, YD2, YPs2, YL2, YU2, NYL, NYU)
4489                ;   NYL = n(Y), NYU = n(Y)
4490                ),
4491                (   fd_get(Z, ZD2, ZL2, ZU2, ZPs2) ->
4492                    NZL cis max(ZL2,NXL+NYL),
4493                    NZU cis min(ZU2,NXU+NYU),
4494                    update_bounds(Z, ZD2, ZPs2, ZL2, ZU2, NZL, NZU)
4495                ;   true
4496                )
4497            )
4498        ).
4499
4500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4501
4502run_propagator(ptimes(X,Y,Z), MState) :-
4503        (   nonvar(X) ->
4504            (   nonvar(Y) -> kill(MState), Z is X * Y
4505            ;   X =:= 0 -> kill(MState), Z = 0
4506            ;   X =:= 1 -> kill(MState), Z = Y
4507            ;   nonvar(Z) -> kill(MState), 0 =:= Z mod X, Y is Z // X
4508            ;   (   Y == Z -> kill(MState), Y = 0
4509                ;   fd_get(Y, YD, _),
4510                    fd_get(Z, ZD, ZPs),
4511                    domain_expand(YD, X, Scaled_YD),
4512                    domains_intersection(ZD, Scaled_YD, ZD1),
4513                    fd_put(Z, ZD1, ZPs),
4514                    (   fd_get(Y, YDom2, YPs2) ->
4515                        domain_contract(ZD1, X, Contract),
4516                        domains_intersection(YDom2, Contract, NYDom),
4517                        fd_put(Y, NYDom, YPs2)
4518                    ;   kill(MState), Z is X * Y
4519                    )
4520                )
4521            )
4522        ;   nonvar(Y) -> run_propagator(ptimes(Y,X,Z), MState)
4523        ;   nonvar(Z) ->
4524            (   X == Y ->
4525                kill(MState),
4526                integer_kth_root(Z, 2, R),
4527                NR is -R,
4528                X in NR \/ R
4529            ;   fd_get(X, XD, XL, XU, XPs),
4530                fd_get(Y, YD, YL, YU, _),
4531                min_max_factor(n(Z), n(Z), YL, YU, XL, XU, NXL, NXU),
4532                update_bounds(X, XD, XPs, XL, XU, NXL, NXU),
4533                (   fd_get(Y, YD2, YL2, YU2, YPs2) ->
4534                    min_max_factor(n(Z), n(Z), NXL, NXU, YL2, YU2, NYL, NYU),
4535                    update_bounds(Y, YD2, YPs2, YL2, YU2, NYL, NYU)
4536                ;   (   Y =\= 0 -> 0 =:= Z mod Y, kill(MState), X is Z // Y
4537                    ;   kill(MState), Z = 0
4538                    )
4539                ),
4540                (   Z =:= 0 ->
4541                    (   \+ domain_contains(XD, 0) -> kill(MState), Y = 0
4542                    ;   \+ domain_contains(YD, 0) -> kill(MState), X = 0
4543                    ;   true
4544                    )
4545                ;  neq_num(X, 0), neq_num(Y, 0)
4546                )
4547            )
4548        ;   (   X == Y -> kill(MState), X^2 #= Z
4549            ;   fd_get(X, XD, XL, XU, XPs),
4550                fd_get(Y, _, YL, YU, _),
4551                fd_get(Z, ZD, ZL, ZU, _),
4552                (   Y == Z, \+ domain_contains(ZD, 0) -> kill(MState), X = 1
4553                ;   X == Z, \+ domain_contains(ZD, 0) -> kill(MState), Y = 1
4554                ;   min_max_factor(ZL, ZU, YL, YU, XL, XU, NXL, NXU),
4555                    update_bounds(X, XD, XPs, XL, XU, NXL, NXU),
4556                    (   fd_get(Y, YD2, YL2, YU2, YPs2) ->
4557                        min_max_factor(ZL, ZU, NXL, NXU, YL2, YU2, NYL, NYU),
4558                        update_bounds(Y, YD2, YPs2, YL2, YU2, NYL, NYU)
4559                    ;   NYL = n(Y), NYU = n(Y)
4560                    ),
4561                    (   fd_get(Z, ZD2, ZL2, ZU2, ZPs2) ->
4562                        min_product(NXL, NXU, NYL, NYU, NZL),
4563                        max_product(NXL, NXU, NYL, NYU, NZU),
4564                        (   NZL cis_leq ZL2, NZU cis_geq ZU2 -> ZD3 = ZD2
4565                        ;   domains_intersection(ZD2, from_to(NZL,NZU), ZD3),
4566                            fd_put(Z, ZD3, ZPs2)
4567                        ),
4568                        (   domain_contains(ZD3, 0) ->  true
4569                        ;   neq_num(X, 0), neq_num(Y, 0)
4570                        )
4571                    ;   true
4572                    )
4573                )
4574            )
4575        ).
4576
4577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4578
4579% X div Y = Z
4580run_propagator(pdiv(X,Y,Z), MState) :- kill(MState), Z #= (X-(X mod Y)) // Y.
4581
4582% X rdiv Y = Z
4583run_propagator(prdiv(X,Y,Z), MState) :- kill(MState), Z*Y #= X.
4584
4585% X // Y = Z (round towards zero)
4586run_propagator(ptzdiv(X,Y,Z), MState) :-
4587        (   nonvar(X) ->
4588            (   nonvar(Y) -> kill(MState), Y =\= 0, Z is X // Y
4589            ;   fd_get(Y, YD, YL, YU, YPs),
4590                (   nonvar(Z) ->
4591                    (   Z =:= 0 ->
4592                        NYL is -abs(X) - 1,
4593                        NYU is abs(X) + 1,
4594                        domains_intersection(YD, split(0, from_to(inf,n(NYL)),
4595                                                       from_to(n(NYU), sup)),
4596                                             NYD),
4597                        fd_put(Y, NYD, YPs)
4598                    ;   (   sign(X) =:= sign(Z) ->
4599                            NYL cis max(n(X) // (n(Z)+sign(n(Z))) + n(1), YL),
4600                            NYU cis min(n(X) // n(Z), YU)
4601                        ;   NYL cis max(n(X) // n(Z), YL),
4602                            NYU cis min(n(X) // (n(Z)+sign(n(Z))) - n(1), YU)
4603                        ),
4604                        update_bounds(Y, YD, YPs, YL, YU, NYL, NYU)
4605                    )
4606                ;   fd_get(Z, ZD, ZL, ZU, ZPs),
4607                    (   X >= 0, ( YL cis_gt n(0) ; YU cis_lt n(0) )->
4608                        NZL cis max(n(X)//YU, ZL),
4609                        NZU cis min(n(X)//YL, ZU)
4610                    ;   X < 0, ( YL cis_gt n(0) ; YU cis_lt n(0) ) ->
4611                        NZL cis max(n(X)//YL, ZL),
4612                        NZU cis min(n(X)//YU, ZU)
4613                    ;   % TODO: more stringent bounds, cover Y
4614                        NZL cis max(-abs(n(X)), ZL),
4615                        NZU cis min(abs(n(X)), ZU)
4616                    ),
4617                    update_bounds(Z, ZD, ZPs, ZL, ZU, NZL, NZU),
4618                    (   X >= 0, NZL cis_gt n(0), fd_get(Y, YD1, YPs1) ->
4619                        NYL cis n(X) // (NZU + n(1)) + n(1),
4620                        NYU cis n(X) // NZL,
4621                        domains_intersection(YD1, from_to(NYL, NYU), NYD1),
4622                        fd_put(Y, NYD1, YPs1)
4623                    ;   true
4624                    )
4625                )
4626            )
4627        ;   nonvar(Y) ->
4628            Y =\= 0,
4629            (   Y =:= 1 -> kill(MState), X = Z
4630            ;   Y =:= -1 -> kill(MState), Z #= -X
4631            ;   fd_get(X, XD, XL, XU, XPs),
4632                (   nonvar(Z) ->
4633                    kill(MState),
4634                    (   sign(Z) =:= sign(Y) ->
4635                        NXL cis max(n(Z)*n(Y), XL),
4636                        NXU cis min((abs(n(Z))+n(1))*abs(n(Y))-n(1), XU)
4637                    ;   Z =:= 0 ->
4638                        NXL cis max(-abs(n(Y)) + n(1), XL),
4639                        NXU cis min(abs(n(Y)) - n(1), XU)
4640                    ;   NXL cis max((n(Z)+sign(n(Z)))*n(Y)+n(1), XL),
4641                        NXU cis min(n(Z)*n(Y), XU)
4642                    ),
4643                    update_bounds(X, XD, XPs, XL, XU, NXL, NXU)
4644                ;   fd_get(Z, ZD, ZPs),
4645                    domain_contract_less(XD, Y, Contracted),
4646                    domains_intersection(ZD, Contracted, NZD),
4647                    fd_put(Z, NZD, ZPs),
4648                    (   fd_get(X, XD2, XPs2) ->
4649                        domain_expand_more(NZD, Y, Expanded),
4650                        domains_intersection(XD2, Expanded, NXD2),
4651                        fd_put(X, NXD2, XPs2)
4652                    ;   true
4653                    )
4654                )
4655            )
4656        ;   nonvar(Z) ->
4657            fd_get(X, XD, XL, XU, XPs),
4658            fd_get(Y, _, YL, YU, _),
4659            (   YL cis_geq n(0), XL cis_geq n(0) ->
4660                NXL cis max(YL*n(Z), XL),
4661                NXU cis min(YU*(n(Z)+n(1))-n(1), XU)
4662            ;   %TODO: cover more cases
4663                NXL = XL, NXU = XU
4664            ),
4665            update_bounds(X, XD, XPs, XL, XU, NXL, NXU)
4666        ;   (   X == Y -> kill(MState), Z = 1
4667            ;   fd_get(X, _, XL, XU, _),
4668                fd_get(Y, _, YL, _, _),
4669                fd_get(Z, ZD, ZPs),
4670                NZU cis max(abs(XL), XU),
4671                NZL cis -NZU,
4672                domains_intersection(ZD, from_to(NZL,NZU), NZD0),
4673                (   XL cis_geq n(0), YL cis_geq n(0) ->
4674                    domain_remove_smaller_than(NZD0, 0, NZD1)
4675                ;   % TODO: cover more cases
4676                    NZD1 = NZD0
4677                ),
4678                fd_put(Z, NZD1, ZPs)
4679            )
4680        ).
4681
4682
4683%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4684% Y = abs(X)
4685
4686run_propagator(pabs(X,Y), MState) :-
4687        (   nonvar(X) -> kill(MState), Y is abs(X)
4688        ;   nonvar(Y) ->
4689            kill(MState),
4690            Y >= 0,
4691            YN is -Y,
4692            X in YN \/ Y
4693        ;   fd_get(X, XD, XPs),
4694            fd_get(Y, YD, _),
4695            domain_negate(YD, YDNegative),
4696            domains_union(YD, YDNegative, XD1),
4697            domains_intersection(XD, XD1, XD2),
4698            fd_put(X, XD2, XPs),
4699            (   fd_get(Y, YD1, YPs1) ->
4700                domain_negate(XD2, XD2Neg),
4701                domains_union(XD2, XD2Neg, YD2),
4702                domain_remove_smaller_than(YD2, 0, YD3),
4703                domains_intersection(YD1, YD3, YD4),
4704                fd_put(Y, YD4, YPs1)
4705            ;   true
4706            )
4707        ).
4708%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4709% Z = X mod Y
4710
4711run_propagator(pmod(X,Y,Z), MState) :-
4712        (   nonvar(X) ->
4713            (   nonvar(Y) -> kill(MState), Y =\= 0, Z is X mod Y
4714            ;   true
4715            )
4716        ;   nonvar(Y) ->
4717            Y =\= 0,
4718            (   abs(Y) =:= 1 -> kill(MState), Z = 0
4719            ;   var(Z) ->
4720                YP is abs(Y) - 1,
4721                (   Y > 0, fd_get(X, _, n(XL), n(XU), _) ->
4722                    (   XL >= 0, XU < Y ->
4723                        kill(MState), Z = X, ZL = XL, ZU = XU
4724                    ;   ZL = 0, ZU = YP
4725                    )
4726                ;   Y > 0 -> ZL = 0, ZU = YP
4727                ;   YN is -YP, ZL = YN, ZU = 0
4728                ),
4729                (   fd_get(Z, ZD, ZPs) ->
4730                    domains_intersection(ZD, from_to(n(ZL), n(ZU)), ZD1),
4731                    domain_infimum(ZD1, n(ZMin)),
4732                    domain_supremum(ZD1, n(ZMax)),
4733                    fd_put(Z, ZD1, ZPs)
4734                ;   ZMin = Z, ZMax = Z
4735                ),
4736                (   fd_get(X, XD, XPs), domain_infimum(XD, n(XMin)) ->
4737                    Z1 is XMin mod Y,
4738                    (   between(ZMin, ZMax, Z1) -> true
4739                    ;   Y > 0 ->
4740                        Next is ((XMin - ZMin + Y - 1) div Y)*Y + ZMin,
4741                        domain_remove_smaller_than(XD, Next, XD1),
4742                        fd_put(X, XD1, XPs)
4743                    ;   neq_num(X, XMin)
4744                    )
4745                ;   true
4746                ),
4747                (   fd_get(X, XD2, XPs2), domain_supremum(XD2, n(XMax)) ->
4748                    Z2 is XMax mod Y,
4749                    (   between(ZMin, ZMax, Z2) -> true
4750                    ;   Y > 0 ->
4751                        Prev is ((XMax - ZMin) div Y)*Y + ZMax,
4752                        domain_remove_greater_than(XD2, Prev, XD3),
4753                        fd_put(X, XD3, XPs2)
4754                    ;   neq_num(X, XMax)
4755                    )
4756                ;   true
4757                )
4758            ;   fd_get(X, XD, XPs),
4759                % if possible, propagate at the boundaries
4760                (   domain_infimum(XD, n(Min)) ->
4761                    (   Min mod Y =:= Z -> true
4762                    ;   Y > 0 ->
4763                        Next is ((Min - Z + Y - 1) div Y)*Y + Z,
4764                        domain_remove_smaller_than(XD, Next, XD1),
4765                        fd_put(X, XD1, XPs)
4766                    ;   neq_num(X, Min)
4767                    )
4768                ;   true
4769                ),
4770                (   fd_get(X, XD2, XPs2) ->
4771                    (   domain_supremum(XD2, n(Max)) ->
4772                        (   Max mod Y =:= Z -> true
4773                        ;   Y > 0 ->
4774                            Prev is ((Max - Z) div Y)*Y + Z,
4775                            domain_remove_greater_than(XD2, Prev, XD3),
4776                            fd_put(X, XD3, XPs2)
4777                        ;   neq_num(X, Max)
4778                        )
4779                    ;   true
4780                    )
4781                ;   true
4782                )
4783            )
4784        ;   X == Y -> kill(MState), Z = 0
4785        ;   true % TODO: propagate more
4786        ).
4787
4788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4789% Z = X rem Y
4790
4791run_propagator(prem(X,Y,Z), MState) :-
4792        (   nonvar(X) ->
4793            (   nonvar(Y) -> kill(MState), Y =\= 0, Z is X rem Y
4794            ;   U is abs(X),
4795                fd_get(Y, YD, _),
4796                (   X >=0, domain_infimum(YD, n(Min)), Min >= 0 -> L = 0
4797                ;   L is -U
4798                ),
4799                Z in L..U
4800            )
4801        ;   nonvar(Y) ->
4802            Y =\= 0,
4803            (   abs(Y) =:= 1 -> kill(MState), Z = 0
4804            ;   var(Z) ->
4805                YP is abs(Y) - 1,
4806                YN is -YP,
4807                (   Y > 0, fd_get(X, _, n(XL), n(XU), _) ->
4808                    (   abs(XL) < Y, XU < Y -> kill(MState), Z = X, ZL = XL
4809                    ;   XL < 0, abs(XL) < Y -> ZL = XL
4810                    ;   XL >= 0 -> ZL = 0
4811                    ;   ZL = YN
4812                    ),
4813                    (   XU > 0, XU < Y -> ZU = XU
4814                    ;   XU < 0 -> ZU = 0
4815                    ;   ZU = YP
4816                    )
4817                ;   ZL = YN, ZU = YP
4818                ),
4819                (   fd_get(Z, ZD, ZPs) ->
4820                    domains_intersection(ZD, from_to(n(ZL), n(ZU)), ZD1),
4821                    fd_put(Z, ZD1, ZPs)
4822                ;   ZD1 = from_to(n(Z), n(Z))
4823                ),
4824                (   fd_get(X, XD, _), domain_infimum(XD, n(Min)) ->
4825                    Z1 is Min rem Y,
4826                    (   domain_contains(ZD1, Z1) -> true
4827                    ;   neq_num(X, Min)
4828                    )
4829                ;   true
4830                ),
4831                (   fd_get(X, XD1, _), domain_supremum(XD1, n(Max)) ->
4832                    Z2 is Max rem Y,
4833                    (   domain_contains(ZD1, Z2) -> true
4834                    ;   neq_num(X, Max)
4835                    )
4836                ;   true
4837                )
4838            ;   fd_get(X, XD1, XPs1),
4839                % if possible, propagate at the boundaries
4840                (   domain_infimum(XD1, n(Min)) ->
4841                    (   Min rem Y =:= Z -> true
4842                    ;   Y > 0, Min > 0 ->
4843                        Next is ((Min - Z + Y - 1) div Y)*Y + Z,
4844                        domain_remove_smaller_than(XD1, Next, XD2),
4845                        fd_put(X, XD2, XPs1)
4846                    ;   % TODO: bigger steps in other cases as well
4847                        neq_num(X, Min)
4848                    )
4849                ;   true
4850                ),
4851                (   fd_get(X, XD3, XPs3) ->
4852                    (   domain_supremum(XD3, n(Max)) ->
4853                        (   Max rem Y =:= Z -> true
4854                        ;   Y > 0, Max > 0  ->
4855                            Prev is ((Max - Z) div Y)*Y + Z,
4856                            domain_remove_greater_than(XD3, Prev, XD4),
4857                            fd_put(X, XD4, XPs3)
4858                        ;   % TODO: bigger steps in other cases as well
4859                            neq_num(X, Max)
4860                        )
4861                    ;   true
4862                    )
4863                ;   true
4864                )
4865            )
4866        ;   X == Y -> kill(MState), Z = 0
4867        ;   fd_get(Z, ZD, ZPs) ->
4868            fd_get(Y, _, YInf, YSup, _),
4869            fd_get(X, _, XInf, XSup, _),
4870            M cis max(abs(YInf),YSup),
4871            (   XInf cis_geq n(0) -> Inf0 = n(0)
4872            ;   Inf0 = XInf
4873            ),
4874            (   XSup cis_leq n(0) -> Sup0 = n(0)
4875            ;   Sup0 = XSup
4876            ),
4877            NInf cis max(max(Inf0, -M + n(1)), min(XInf,-XSup)),
4878            NSup cis min(min(Sup0, M - n(1)), max(abs(XInf),XSup)),
4879            domains_intersection(ZD, from_to(NInf,NSup), ZD1),
4880            fd_put(Z, ZD1, ZPs)
4881        ;   true % TODO: propagate more
4882        ).
4883
4884%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885% Z = max(X,Y)
4886
4887run_propagator(pmax(X,Y,Z), MState) :-
4888        (   nonvar(X) ->
4889            (   nonvar(Y) -> kill(MState), Z is max(X,Y)
4890            ;   nonvar(Z) ->
4891                (   Z =:= X -> kill(MState), X #>= Y
4892                ;   Z > X -> Z = Y
4893                ;   false % Z < X
4894                )
4895            ;   fd_get(Y, _, YInf, YSup, _),
4896                (   YInf cis_gt n(X) -> Z = Y
4897                ;   YSup cis_lt n(X) -> Z = X
4898                ;   YSup = n(M) ->
4899                    fd_get(Z, ZD, ZPs),
4900                    domain_remove_greater_than(ZD, M, ZD1),
4901                    fd_put(Z, ZD1, ZPs)
4902                ;   true
4903                )
4904            )
4905        ;   nonvar(Y) -> run_propagator(pmax(Y,X,Z), MState)
4906        ;   fd_get(Z, ZD, ZPs) ->
4907            fd_get(X, _, XInf, XSup, _),
4908            fd_get(Y, _, YInf, YSup, _),
4909            (   YInf cis_gt YSup -> kill(MState), Z = Y
4910            ;   YSup cis_lt XInf -> kill(MState), Z = X
4911            ;   n(M) cis max(XSup, YSup) ->
4912                domain_remove_greater_than(ZD, M, ZD1),
4913                fd_put(Z, ZD1, ZPs)
4914            ;   true
4915            )
4916        ;   true
4917        ).
4918
4919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4920% Z = min(X,Y)
4921
4922run_propagator(pmin(X,Y,Z), MState) :-
4923        (   nonvar(X) ->
4924            (   nonvar(Y) -> kill(MState), Z is min(X,Y)
4925            ;   nonvar(Z) ->
4926                (   Z =:= X -> kill(MState), X #=< Y
4927                ;   Z < X -> Z = Y
4928                ;   false % Z > X
4929                )
4930            ;   fd_get(Y, _, YInf, YSup, _),
4931                (   YSup cis_lt n(X) -> Z = Y
4932                ;   YInf cis_gt n(X) -> Z = X
4933                ;   YInf = n(M) ->
4934                    fd_get(Z, ZD, ZPs),
4935                    domain_remove_smaller_than(ZD, M, ZD1),
4936                    fd_put(Z, ZD1, ZPs)
4937                ;   true
4938                )
4939            )
4940        ;   nonvar(Y) -> run_propagator(pmin(Y,X,Z), MState)
4941        ;   fd_get(Z, ZD, ZPs) ->
4942            fd_get(X, _, XInf, XSup, _),
4943            fd_get(Y, _, YInf, YSup, _),
4944            (   YSup cis_lt YInf -> kill(MState), Z = Y
4945            ;   YInf cis_gt XSup -> kill(MState), Z = X
4946            ;   n(M) cis min(XInf, YInf) ->
4947                domain_remove_smaller_than(ZD, M, ZD1),
4948                fd_put(Z, ZD1, ZPs)
4949            ;   true
4950            )
4951        ;   true
4952        ).
4953%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4954% Z = X ^ Y
4955
4956run_propagator(pexp(X,Y,Z), MState) :-
4957        (   X == 1 -> kill(MState), Z = 1
4958        ;   X == 0 -> kill(MState), Z in 0..1, Z #<==> Y #= 0
4959        ;   Y == 0 -> kill(MState), Z = 1
4960        ;   Y == 1 -> kill(MState), Z = X
4961        ;   nonvar(X) ->
4962            (   nonvar(Y) ->
4963                (   Y >= 0 -> true ; X =:= -1 ),
4964                kill(MState),
4965                Z is X^Y
4966            ;   nonvar(Z) ->
4967                (   Z > 1 ->
4968                    kill(MState),
4969                    integer_log_b(Z, X, 1, Y)
4970                ;   true
4971                )
4972            ;   fd_get(Y, _, YL, YU, _),
4973                fd_get(Z, ZD, ZPs),
4974                (   X > 0, YL cis_geq n(0) ->
4975                    NZL cis n(X)^YL,
4976                    NZU cis n(X)^YU,
4977                    domains_intersection(ZD, from_to(NZL,NZU), NZD),
4978                    fd_put(Z, NZD, ZPs)
4979                ;   true
4980                ),
4981                (   X > 0,
4982                    fd_get(Z, _, _, n(ZMax), _),
4983                    ZMax > 0 ->
4984                    floor_integer_log_b(ZMax, X, 1, YCeil),
4985                    Y in inf..YCeil
4986                ;   true
4987                )
4988            )
4989        ;   nonvar(Z) ->
4990            (   nonvar(Y) ->
4991                integer_kth_root(Z, Y, R),
4992                kill(MState),
4993                (   even(Y) ->
4994                    N is -R,
4995                    X in N \/ R
4996                ;   X = R
4997                )
4998            ;   fd_get(X, _, n(NXL), _, _), NXL > 1 ->
4999                (   Z > 1, between(NXL, Z, Exp), NXL^Exp > Z ->
5000                    Exp1 is Exp - 1,
5001                    fd_get(Y, YD, YPs),
5002                    domains_intersection(YD, from_to(n(1),n(Exp1)), YD1),
5003                    fd_put(Y, YD1, YPs),
5004                    (   fd_get(X, XD, XPs) ->
5005                        domain_infimum(YD1, n(YL)),
5006                        integer_kth_root_leq(Z, YL, RU),
5007                        domains_intersection(XD, from_to(n(NXL),n(RU)), XD1),
5008                        fd_put(X, XD1, XPs)
5009                    ;   true
5010                    )
5011                ;   true
5012                )
5013            ;   true
5014            )
5015        ;   nonvar(Y), Y > 0 ->
5016            (   even(Y) ->
5017                geq(Z, 0)
5018            ;   true
5019            ),
5020            (   fd_get(X, XD, XL, XU, _), fd_get(Z, ZD, ZL, ZU, ZPs) ->
5021                (   domain_contains(ZD, 0) -> XD1 = XD
5022                ;   domain_remove(XD, 0, XD1)
5023                ),
5024                (   domain_contains(XD, 0) -> ZD1 = ZD
5025                ;   domain_remove(ZD, 0, ZD1)
5026                ),
5027                (   even(Y) ->
5028                    (   XL cis_geq n(0) ->
5029                        NZL cis XL^n(Y)
5030                    ;   XU cis_leq n(0) ->
5031                        NZL cis XU^n(Y)
5032                    ;   NZL = n(0)
5033                    ),
5034                    NZU cis max(abs(XL),abs(XU))^n(Y),
5035                    domains_intersection(ZD1, from_to(NZL,NZU), ZD2)
5036                ;   (   finite(XL) ->
5037                        NZL cis XL^n(Y),
5038                        NZU cis XU^n(Y),
5039                        domains_intersection(ZD1, from_to(NZL,NZU), ZD2)
5040                    ;   ZD2 = ZD1
5041                    )
5042                ),
5043                fd_put(Z, ZD2, ZPs),
5044                (   even(Y), ZU = n(Num) ->
5045                    integer_kth_root_leq(Num, Y, RU),
5046                    (   XL cis_geq n(0), ZL = n(Num1) ->
5047                        integer_kth_root_leq(Num1, Y, RL0),
5048                        (   RL0^Y < Num1 -> RL is RL0 + 1
5049                        ;   RL = RL0
5050                        )
5051                    ;   RL is -RU
5052                    ),
5053                    RL =< RU,
5054                    NXD = from_to(n(RL),n(RU))
5055                ;   odd(Y), ZL cis_geq n(0), ZU = n(Num) ->
5056                    integer_kth_root_leq(Num, Y, RU),
5057                    ZL = n(Num1),
5058                    integer_kth_root_leq(Num1, Y, RL0),
5059                    (   RL0^Y < Num1 -> RL is RL0 + 1
5060                    ;   RL = RL0
5061                    ),
5062                    RL =< RU,
5063                    NXD = from_to(n(RL),n(RU))
5064                ;   NXD = XD1   % TODO: propagate more
5065                ),
5066                (   fd_get(X, XD2, XPs) ->
5067                    domains_intersection(XD2, XD1, XD3),
5068                    domains_intersection(XD3, NXD, XD4),
5069                    fd_put(X, XD4, XPs)
5070                ;   true
5071                )
5072            ;   true
5073            )
5074        ;   fd_get(X, _, XL, _, _),
5075            XL cis_gt n(0),
5076            fd_get(Y, _, YL, _, _),
5077            YL cis_gt n(0),
5078            fd_get(Z, ZD, ZPs) ->
5079            n(NZL) cis XL^YL,
5080            domain_remove_smaller_than(ZD, NZL, ZD1),
5081            fd_put(Z, ZD1, ZPs)
5082        ;   true
5083        ).
5084
5085%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5086run_propagator(pzcompare(Order, A, B), MState) :-
5087        (   A == B -> kill(MState), Order = (=)
5088        ;   (   nonvar(A) ->
5089                (   nonvar(B) ->
5090                    kill(MState),
5091                    (   A > B -> Order = (>)
5092                    ;   Order = (<)
5093                    )
5094                ;   fd_get(B, _, BL, BU, _),
5095                    (   BL cis_gt n(A) -> kill(MState), Order = (<)
5096                    ;   BU cis_lt n(A) -> kill(MState), Order = (>)
5097                    ;   true
5098                    )
5099                )
5100            ;   nonvar(B) ->
5101                fd_get(A, _, AL, AU, _),
5102                (   AL cis_gt n(B) -> kill(MState), Order = (>)
5103                ;   AU cis_lt n(B) -> kill(MState), Order = (<)
5104                ;   true
5105                )
5106            ;   fd_get(A, _, AL, AU, _),
5107                fd_get(B, _, BL, BU, _),
5108                (   AL cis_gt BU -> kill(MState), Order = (>)
5109                ;   AU cis_lt BL -> kill(MState), Order = (<)
5110                ;   true
5111                )
5112            )
5113        ).
5114
5115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5116
5117% reified constraints
5118
5119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5120
5121run_propagator(reified_in(V,Dom,B), MState) :-
5122        (   integer(V) ->
5123            kill(MState),
5124            (   domain_contains(Dom, V) -> B = 1
5125            ;   B = 0
5126            )
5127        ;   B == 1 -> kill(MState), domain(V, Dom)
5128        ;   B == 0 -> kill(MState), domain_complement(Dom, C), domain(V, C)
5129        ;   fd_get(V, VD, _),
5130            (   domains_intersection(VD, Dom, I) ->
5131                (   I == VD -> kill(MState), B = 1
5132                ;   true
5133                )
5134            ;   kill(MState), B = 0
5135            )
5136        ).
5137
5138run_propagator(reified_tuple_in(Tuple, R, B), MState) :-
5139        get_attr(R, clpfd_relation, Relation),
5140        (   B == 1 -> kill(MState), tuples_in([Tuple], Relation)
5141        ;   (   ground(Tuple) ->
5142                kill(MState),
5143                (   memberchk(Tuple, Relation) -> B = 1
5144                ;   B = 0
5145                )
5146            ;   relation_unifiable(Relation, Tuple, Us, _, _),
5147                (   Us = [] -> kill(MState), B = 0
5148                ;   true
5149                )
5150            )
5151        ).
5152
5153run_propagator(tuples_not_in(Tuples, Relation, B), MState) :-
5154        (   B == 0 ->
5155            kill(MState),
5156            tuples_in_conjunction(Tuples, Relation, Conj),
5157            #\ Conj
5158        ;   true
5159        ).
5160
5161run_propagator(kill_reified_tuples(B, Ps, Bs), _) :-
5162        (   B == 0 ->
5163            maplist(kill_entailed, Ps),
5164            phrase(as(Bs), As),
5165            maplist(kill_entailed, As)
5166        ;   true
5167        ).
5168
5169run_propagator(reified_fd(V,B), MState) :-
5170        (   fd_inf(V, I), I \== inf, fd_sup(V, S), S \== sup ->
5171            kill(MState),
5172            B = 1
5173        ;   B == 0 ->
5174            (   fd_inf(V, inf) -> true
5175            ;   fd_sup(V, sup) -> true
5176            ;   false
5177            )
5178        ;   true
5179        ).
5180
5181% The result of X/Y, X mod Y, and X rem Y is undefined iff Y is 0.
5182
5183run_propagator(pskeleton(X,Y,D,Skel,Z,_), MState) :-
5184        (   Y == 0 -> kill(MState), D = 0
5185        ;   D == 1 -> kill(MState), neq_num(Y, 0), skeleton([X,Y,Z], Skel)
5186        ;   integer(Y), Y =\= 0 -> kill(MState), D = 1, skeleton([X,Y,Z], Skel)
5187        ;   fd_get(Y, YD, _), \+ domain_contains(YD, 0) ->
5188            kill(MState),
5189            D = 1, skeleton([X,Y,Z], Skel)
5190        ;   true
5191        ).
5192
5193/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5194   Propagators for arithmetic functions that only propagate
5195   functionally. These are currently the bitwise operations.
5196- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5197
5198run_propagator(pfunction(Op,A,B,R), MState) :-
5199        (   integer(A), integer(B) ->
5200            kill(MState),
5201            Expr =.. [Op,A,B],
5202            R is Expr
5203        ;   true
5204        ).
5205run_propagator(pfunction(Op,A,R), MState) :-
5206        (   integer(A) ->
5207            kill(MState),
5208            Expr =.. [Op,A],
5209            R is Expr
5210        ;   true
5211        ).
5212
5213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5214
5215run_propagator(reified_geq(DX,X,DY,Y,Ps,B), MState) :-
5216        (   DX == 0 -> kill(MState, Ps), B = 0
5217        ;   DY == 0 -> kill(MState, Ps), B = 0
5218        ;   B == 1 -> kill(MState), DX = 1, DY = 1, geq(X, Y)
5219        ;   DX == 1, DY == 1 ->
5220            (   var(B) ->
5221                (   nonvar(X) ->
5222                    (   nonvar(Y) ->
5223                        kill(MState),
5224                        (   X >= Y -> B = 1 ; B = 0 )
5225                    ;   fd_get(Y, _, YL, YU, _),
5226                        (   n(X) cis_geq YU -> kill(MState, Ps), B = 1
5227                        ;   n(X) cis_lt YL -> kill(MState, Ps), B = 0
5228                        ;   true
5229                        )
5230                    )
5231                ;   nonvar(Y) ->
5232                    fd_get(X, _, XL, XU, _),
5233                    (   XL cis_geq n(Y) -> kill(MState, Ps), B = 1
5234                    ;   XU cis_lt n(Y) -> kill(MState, Ps), B = 0
5235                    ;   true
5236                    )
5237                ;   X == Y -> kill(MState, Ps), B = 1
5238                ;   fd_get(X, _, XL, XU, _),
5239                    fd_get(Y, _, YL, YU, _),
5240                    (   XL cis_geq YU -> kill(MState, Ps), B = 1
5241                    ;   XU cis_lt YL -> kill(MState, Ps), B = 0
5242                    ;   true
5243                    )
5244                )
5245            ;   B =:= 0 -> kill(MState), X #< Y
5246            ;   true
5247            )
5248        ;   true
5249        ).
5250
5251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5252run_propagator(reified_eq(DX,X,DY,Y,Ps,B), MState) :-
5253        (   DX == 0 -> kill(MState, Ps), B = 0
5254        ;   DY == 0 -> kill(MState, Ps), B = 0
5255        ;   B == 1 -> kill(MState), DX = 1, DY = 1, X = Y
5256        ;   DX == 1, DY == 1 ->
5257            (   var(B) ->
5258                (   nonvar(X) ->
5259                    (   nonvar(Y) ->
5260                        kill(MState),
5261                        (   X =:= Y -> B = 1 ; B = 0)
5262                    ;   fd_get(Y, YD, _),
5263                        (   domain_contains(YD, X) -> true
5264                        ;   kill(MState, Ps), B = 0
5265                        )
5266                    )
5267                ;   nonvar(Y) -> run_propagator(reified_eq(DY,Y,DX,X,Ps,B), MState)
5268                ;   X == Y -> kill(MState), B = 1
5269                ;   fd_get(X, _, XL, XU, _),
5270                    fd_get(Y, _, YL, YU, _),
5271                    (   XL cis_gt YU -> kill(MState, Ps), B = 0
5272                    ;   YL cis_gt XU -> kill(MState, Ps), B = 0
5273                    ;   true
5274                    )
5275                )
5276            ;   B =:= 0 -> kill(MState), X #\= Y
5277            ;   true
5278            )
5279        ;   true
5280        ).
5281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5282run_propagator(reified_neq(DX,X,DY,Y,Ps,B), MState) :-
5283        (   DX == 0 -> kill(MState, Ps), B = 0
5284        ;   DY == 0 -> kill(MState, Ps), B = 0
5285        ;   B == 1 -> kill(MState), DX = 1, DY = 1, X #\= Y
5286        ;   DX == 1, DY == 1 ->
5287            (   var(B) ->
5288                (   nonvar(X) ->
5289                    (   nonvar(Y) ->
5290                        kill(MState),
5291                        (   X =\= Y -> B = 1 ; B = 0)
5292                    ;   fd_get(Y, YD, _),
5293                        (   domain_contains(YD, X) -> true
5294                        ;   kill(MState, Ps), B = 1
5295                        )
5296                    )
5297                ;   nonvar(Y) -> run_propagator(reified_neq(DY,Y,DX,X,Ps,B), MState)
5298                ;   X == Y -> kill(MState), B = 0
5299                ;   fd_get(X, _, XL, XU, _),
5300                    fd_get(Y, _, YL, YU, _),
5301                    (   XL cis_gt YU -> kill(MState, Ps), B = 1
5302                    ;   YL cis_gt XU -> kill(MState, Ps), B = 1
5303                    ;   true
5304                    )
5305                )
5306            ;   B =:= 0 -> kill(MState), X = Y
5307            ;   true
5308            )
5309        ;   true
5310        ).
5311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5312run_propagator(reified_and(X,Ps1,Y,Ps2,B), MState) :-
5313        (   nonvar(X) ->
5314            kill(MState),
5315            (   X =:= 0 -> maplist(kill_entailed, Ps2), B = 0
5316            ;   B = Y
5317            )
5318        ;   nonvar(Y) -> run_propagator(reified_and(Y,Ps2,X,Ps1,B), MState)
5319        ;   B == 1 -> kill(MState), X = 1, Y = 1
5320        ;   true
5321        ).
5322
5323%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5324run_propagator(reified_or(X,Ps1,Y,Ps2,B), MState) :-
5325        (   nonvar(X) ->
5326            kill(MState),
5327            (   X =:= 1 -> maplist(kill_entailed, Ps2), B = 1
5328            ;   B = Y
5329            )
5330        ;   nonvar(Y) -> run_propagator(reified_or(Y,Ps2,X,Ps1,B), MState)
5331        ;   B == 0 -> kill(MState), X = 0, Y = 0
5332        ;   true
5333        ).
5334
5335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5336run_propagator(reified_not(X,Y), MState) :-
5337        (   X == 0 -> kill(MState), Y = 1
5338        ;   X == 1 -> kill(MState), Y = 0
5339        ;   Y == 0 -> kill(MState), X = 1
5340        ;   Y == 1 -> kill(MState), X = 0
5341        ;   true
5342        ).
5343
5344%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5345run_propagator(pimpl(X, Y, Ps), MState) :-
5346        (   nonvar(X) ->
5347            kill(MState),
5348            (   X =:= 1 -> Y = 1
5349            ;   maplist(kill_entailed, Ps)
5350            )
5351        ;   nonvar(Y) ->
5352            kill(MState),
5353            (   Y =:= 0 -> X = 0
5354            ;   maplist(kill_entailed, Ps)
5355            )
5356        ;   true
5357        ).
5358
5359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5360%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5361
5362update_bounds(X, XD, XPs, XL, XU, NXL, NXU) :-
5363        (   NXL == XL, NXU == XU -> true
5364        ;   domains_intersection(XD, from_to(NXL, NXU), NXD),
5365            fd_put(X, NXD, XPs)
5366        ).
5367
5368min_product(L1, U1, L2, U2, Min) :-
5369        Min cis min(min(L1*L2,L1*U2),min(U1*L2,U1*U2)).
5370max_product(L1, U1, L2, U2, Max) :-
5371        Max cis max(max(L1*L2,L1*U2),max(U1*L2,U1*U2)).
5372
5373finite(n(_)).
5374
5375in_(L, U, X) :-
5376        fd_get(X, XD, XPs),
5377        domains_intersection(XD, from_to(L,U), NXD),
5378        fd_put(X, NXD, XPs).
5379
5380min_max_factor(L1, U1, L2, U2, L3, U3, Min, Max) :-
5381        (   U1 cis_lt n(0),
5382            L2 cis_lt n(0), U2 cis_gt n(0),
5383            L3 cis_lt n(0), U3 cis_gt n(0) ->
5384            maplist(in_(L1,U1), [Z1,Z2]),
5385            in_(L2, n(-1), X1), in_(n(1), U3, Y1),
5386            (   X1*Y1 #= Z1 ->
5387                (   fd_get(Y1, _, Inf1, Sup1, _) -> true
5388                ;   Inf1 = n(Y1), Sup1 = n(Y1)
5389                )
5390            ;   Inf1 = inf, Sup1 = n(-1)
5391            ),
5392            in_(n(1), U2, X2), in_(L3, n(-1), Y2),
5393            (   X2*Y2 #= Z2 ->
5394                (   fd_get(Y2, _, Inf2, Sup2, _) -> true
5395                ;   Inf2 = n(Y2), Sup2 = n(Y2)
5396                )
5397            ;   Inf2 = n(1), Sup2 = sup
5398            ),
5399            Min cis max(min(Inf1,Inf2), L3),
5400            Max cis min(max(Sup1,Sup2), U3)
5401        ;   L1 cis_gt n(0),
5402            L2 cis_lt n(0), U2 cis_gt n(0),
5403            L3 cis_lt n(0), U3 cis_gt n(0) ->
5404            maplist(in_(L1,U1), [Z1,Z2]),
5405            in_(L2, n(-1), X1), in_(L3, n(-1), Y1),
5406            (   X1*Y1 #= Z1 ->
5407                (   fd_get(Y1, _, Inf1, Sup1, _) -> true
5408                ;   Inf1 = n(Y1), Sup1 = n(Y1)
5409                )
5410            ;   Inf1 = n(1), Sup1 = sup
5411            ),
5412            in_(n(1), U2, X2), in_(n(1), U3, Y2),
5413            (   X2*Y2 #= Z2 ->
5414                (   fd_get(Y2, _, Inf2, Sup2, _) -> true
5415                ;   Inf2 = n(Y2), Sup2 = n(Y2)
5416                )
5417            ;   Inf2 = inf, Sup2 = n(-1)
5418            ),
5419            Min cis max(min(Inf1,Inf2), L3),
5420            Max cis min(max(Sup1,Sup2), U3)
5421        ;   min_factor(L1, U1, L2, U2, Min0),
5422            Min cis max(L3,Min0),
5423            max_factor(L1, U1, L2, U2, Max0),
5424            Max cis min(U3,Max0)
5425        ).
5426
5427min_factor(L1, U1, L2, U2, Min) :-
5428        (   L1 cis_geq n(0), L2 cis_gt n(0), finite(U2) ->
5429            Min cis div(L1+U2-n(1),U2)
5430        ;   L1 cis_gt n(0), U2 cis_lt n(0) -> Min cis div(U1,U2)
5431        ;   L1 cis_gt n(0), L2 cis_geq n(0) -> Min = n(1)
5432        ;   L1 cis_gt n(0) -> Min cis -U1
5433        ;   U1 cis_lt n(0), U2 cis_leq n(0) ->
5434            (   finite(L2) -> Min cis div(U1+L2+n(1),L2)
5435            ;   Min = n(1)
5436            )
5437        ;   U1 cis_lt n(0), L2 cis_geq n(0) -> Min cis div(L1,L2)
5438        ;   U1 cis_lt n(0) -> Min = L1
5439        ;   L2 cis_leq n(0), U2 cis_geq n(0) -> Min = inf
5440        ;   Min cis min(min(div(L1,L2),div(L1,U2)),min(div(U1,L2),div(U1,U2)))
5441        ).
5442max_factor(L1, U1, L2, U2, Max) :-
5443        (   L1 cis_geq n(0), L2 cis_geq n(0) -> Max cis div(U1,L2)
5444        ;   L1 cis_gt n(0), U2 cis_leq n(0) ->
5445            (   finite(L2) -> Max cis div(L1-L2-n(1),L2)
5446            ;   Max = n(-1)
5447            )
5448        ;   L1 cis_gt n(0) -> Max = U1
5449        ;   U1 cis_lt n(0), U2 cis_lt n(0) -> Max cis div(L1,U2)
5450        ;   U1 cis_lt n(0), L2 cis_geq n(0) ->
5451            (   finite(U2) -> Max cis div(U1-U2+n(1),U2)
5452            ;   Max = n(-1)
5453            )
5454        ;   U1 cis_lt n(0) -> Max cis -L1
5455        ;   L2 cis_leq n(0), U2 cis_geq n(0) -> Max = sup
5456        ;   Max cis max(max(div(L1,L2),div(L1,U2)),max(div(U1,L2),div(U1,U2)))
5457        ).
5458
5459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5460/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5461   J-C. Régin: "A filtering algorithm for constraints of difference in
5462   CSPs", AAAI-94, Seattle, WA, USA, pp 362--367, 1994
5463- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5464
5465distinct_attach([], _, _).
5466distinct_attach([X|Xs], Prop, Right) :-
5467        (   var(X) ->
5468            init_propagator(X, Prop),
5469            make_propagator(pexclude(Xs,Right,X), P1),
5470            init_propagator(X, P1),
5471            trigger_prop(P1)
5472        ;   exclude_fire(Xs, Right, X)
5473        ),
5474        distinct_attach(Xs, Prop, [X|Right]).
5475
5476/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5477   For each integer of the union of domains, an attributed variable is
5478   introduced, to benefit from constant-time access. Attributes are:
5479
5480   value ... integer corresponding to the node
5481   free  ... whether this (right) node is still free
5482   edges ... [flow_from(F,From)] and [flow_to(F,To)] where F has an
5483             attribute "flow" that is either 0 or 1 and an attribute "used"
5484             if it is part of a maximum matching
5485   parent ... used in breadth-first search
5486   g0_edges ... [flow_to(F,To)] as above
5487   visited ... true if node was visited in DFS
5488   index, in_stack, lowlink ... used in Tarjan's SCC algorithm
5489- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5490
5491difference_arcs(Vars, FreeLeft, FreeRight) :-
5492        empty_assoc(E),
5493        phrase(difference_arcs(Vars, FreeLeft), [E], [NumVar]),
5494        assoc_to_list(NumVar, LsNumVar),
5495        pairs_values(LsNumVar, FreeRight).
5496
5497domain_to_list(Domain, List) :- phrase(domain_to_list(Domain), List).
5498
5499domain_to_list(split(_, Left, Right)) -->
5500        domain_to_list(Left), domain_to_list(Right).
5501domain_to_list(empty)                 --> [].
5502domain_to_list(from_to(n(F),n(T)))    --> { numlist(F, T, Ns) }, list(Ns).
5503
5504difference_arcs([], []) --> [].
5505difference_arcs([V|Vs], FL0) -->
5506        (   { fd_get(V, Dom, _),
5507              finite_domain(Dom) } ->
5508            { FL0 = [V|FL],
5509              domain_to_list(Dom, Ns) },
5510            enumerate(Ns, V),
5511            difference_arcs(Vs, FL)
5512        ;   difference_arcs(Vs, FL0)
5513        ).
5514
5515enumerate([], _) --> [].
5516enumerate([N|Ns], V) -->
5517        state(NumVar0, NumVar),
5518        { (   get_assoc(N, NumVar0, Y) -> NumVar0 = NumVar
5519          ;   put_assoc(N, NumVar0, Y, NumVar),
5520              put_attr(Y, value, N)
5521          ),
5522          put_attr(F, flow, 0),
5523          append_edge(Y, edges, flow_from(F,V)),
5524          append_edge(V, edges, flow_to(F,Y)) },
5525        enumerate(Ns, V).
5526
5527append_edge(V, Attr, E) :-
5528        (   get_attr(V, Attr, Es) ->
5529            put_attr(V, Attr, [E|Es])
5530        ;   put_attr(V, Attr, [E])
5531        ).
5532
5533/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5534   Strategy: Breadth-first search until we find a free right vertex in
5535   the value graph, then find an augmenting path in reverse.
5536- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5537
5538clear_parent(V) :- del_attr(V, parent).
5539
5540maximum_matching([]).
5541maximum_matching([FL|FLs]) :-
5542        augmenting_path_to([[FL]], Levels, To),
5543        phrase(augmenting_path(FL, To), Path),
5544        maplist(maplist(clear_parent), Levels),
5545        del_attr(To, free),
5546        adjust_alternate_1(Path),
5547        maximum_matching(FLs).
5548
5549reachables([]) --> [].
5550reachables([V|Vs]) -->
5551        { get_attr(V, edges, Es) },
5552        reachables_(Es, V),
5553        reachables(Vs).
5554
5555reachables_([], _) --> [].
5556reachables_([E|Es], V) -->
5557        edge_reachable(E, V),
5558        reachables_(Es, V).
5559
5560edge_reachable(flow_to(F,To), V) -->
5561        (   { get_attr(F, flow, 0),
5562              \+ get_attr(To, parent, _) } ->
5563            { put_attr(To, parent, V-F) },
5564            [To]
5565        ;   []
5566        ).
5567edge_reachable(flow_from(F,From), V) -->
5568        (   { get_attr(F, flow, 1),
5569              \+ get_attr(From, parent, _) } ->
5570            { put_attr(From, parent, V-F) },
5571            [From]
5572        ;   []
5573        ).
5574
5575augmenting_path_to(Levels0, Levels, Right) :-
5576        Levels0 = [Vs|_],
5577        Levels1 = [Tos|Levels0],
5578        phrase(reachables(Vs), Tos),
5579        Tos = [_|_],
5580        (   member(Right, Tos), get_attr(Right, free, true) ->
5581            Levels = Levels1
5582        ;   augmenting_path_to(Levels1, Levels, Right)
5583        ).
5584
5585augmenting_path(S, V) -->
5586        (   { V == S } -> []
5587        ;   { get_attr(V, parent, V1-Augment) },
5588            [Augment],
5589            augmenting_path(S, V1)
5590        ).
5591
5592adjust_alternate_1([A|Arcs]) :-
5593        put_attr(A, flow, 1),
5594        adjust_alternate_0(Arcs).
5595
5596adjust_alternate_0([]).
5597adjust_alternate_0([A|Arcs]) :-
5598        put_attr(A, flow, 0),
5599        adjust_alternate_1(Arcs).
5600
5601% Instead of applying Berge's property directly, we can translate the
5602% problem in such a way, that we have to search for the so-called
5603% strongly connected components of the graph.
5604
5605g_g0(V) :-
5606        get_attr(V, edges, Es),
5607        maplist(g_g0_(V), Es).
5608
5609g_g0_(V, flow_to(F,To)) :-
5610        (   get_attr(F, flow, 1) ->
5611            append_edge(V, g0_edges, flow_to(F,To))
5612        ;   append_edge(To, g0_edges, flow_to(F,V))
5613        ).
5614
5615
5616g0_successors(V, Tos) :-
5617        (   get_attr(V, g0_edges, Tos0) ->
5618            maplist(arg(2), Tos0, Tos)
5619        ;   Tos = []
5620        ).
5621
5622put_free(F) :- put_attr(F, free, true).
5623
5624free_node(F) :- get_attr(F, free, true).
5625
5626del_vars_attr(Vars, Attr) :- maplist(del_attr_(Attr), Vars).
5627
5628del_attr_(Attr, Var) :- del_attr(Var, Attr).
5629
5630with_local_attributes(Vars, Attrs, Goal, Result) :-
5631        catch((maplist(del_vars_attr(Vars), Attrs),
5632               Goal,
5633               maplist(del_attrs, Vars),
5634               % reset all attributes, only the result matters
5635               throw(local_attributes(Result,Vars))),
5636              local_attributes(Result,Vars),
5637              true).
5638
5639distinct(Vars) :-
5640        with_local_attributes(Vars, [edges,parent,g0_edges,index,visited],
5641              (difference_arcs(Vars, FreeLeft, FreeRight0),
5642               length(FreeLeft, LFL),
5643               length(FreeRight0, LFR),
5644               LFL =< LFR,
5645               maplist(put_free, FreeRight0),
5646               maximum_matching(FreeLeft),
5647               include(free_node, FreeRight0, FreeRight),
5648               maplist(g_g0, FreeLeft),
5649               scc(FreeLeft, g0_successors),
5650               maplist(dfs_used, FreeRight),
5651               phrase(distinct_goals(FreeLeft), Gs)), Gs),
5652        disable_queue,
5653        maplist(call, Gs),
5654        enable_queue.
5655
5656distinct_goals([]) --> [].
5657distinct_goals([V|Vs]) -->
5658        { get_attr(V, edges, Es) },
5659        distinct_goals_(Es, V),
5660        distinct_goals(Vs).
5661
5662distinct_goals_([], _) --> [].
5663distinct_goals_([flow_to(F,To)|Es], V) -->
5664        (   { get_attr(F, flow, 0),
5665              \+ get_attr(F, used, true),
5666              get_attr(V, lowlink, L1),
5667              get_attr(To, lowlink, L2),
5668              L1 =\= L2 } ->
5669            { get_attr(To, value, N) },
5670            [neq_num(V, N)]
5671        ;   []
5672        ),
5673        distinct_goals_(Es, V).
5674
5675/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5676   Mark used edges.
5677- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5678
5679dfs_used(V) :-
5680        (   get_attr(V, visited, true) -> true
5681        ;   put_attr(V, visited, true),
5682            (   get_attr(V, g0_edges, Es) ->
5683                dfs_used_edges(Es)
5684            ;   true
5685            )
5686        ).
5687
5688dfs_used_edges([]).
5689dfs_used_edges([flow_to(F,To)|Es]) :-
5690        put_attr(F, used, true),
5691        dfs_used(To),
5692        dfs_used_edges(Es).
5693
5694/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5695   Tarjan's strongly connected components algorithm.
5696
5697   DCGs are used to implicitly pass around the global index, stack
5698   and the predicate relating a vertex to its successors.
5699
5700   For more information about this technique, see:
5701
5702                 https://www.metalevel.at/prolog/dcg
5703                 ===================================
5704
5705   A Prolog implementation of this algorithm is also available as a
5706   standalone library from:
5707
5708                   https://www.metalevel.at/scc.pl
5709- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5710
5711scc(Vs, Succ) :- phrase(scc(Vs), [s(0,[],Succ)], _).
5712
5713scc([])     --> [].
5714scc([V|Vs]) -->
5715        (   vindex_defined(V) -> scc(Vs)
5716        ;   scc_(V), scc(Vs)
5717        ).
5718
5719vindex_defined(V) --> { get_attr(V, index, _) }.
5720
5721vindex_is_index(V) -->
5722        state(s(Index,_,_)),
5723        { put_attr(V, index, Index) }.
5724
5725vlowlink_is_index(V) -->
5726        state(s(Index,_,_)),
5727        { put_attr(V, lowlink, Index) }.
5728
5729index_plus_one -->
5730        state(s(I,Stack,Succ), s(I1,Stack,Succ)),
5731        { I1 is I+1 }.
5732
5733s_push(V)  -->
5734        state(s(I,Stack,Succ), s(I,[V|Stack],Succ)),
5735        { put_attr(V, in_stack, true) }.
5736
5737vlowlink_min_lowlink(V, VP) -->
5738        { get_attr(V, lowlink, VL),
5739          get_attr(VP, lowlink, VPL),
5740          VL1 is min(VL, VPL),
5741          put_attr(V, lowlink, VL1) }.
5742
5743successors(V, Tos) --> state(s(_,_,Succ)), { call(Succ, V, Tos) }.
5744
5745scc_(V) -->
5746        vindex_is_index(V),
5747        vlowlink_is_index(V),
5748        index_plus_one,
5749        s_push(V),
5750        successors(V, Tos),
5751        each_edge(Tos, V),
5752        (   { get_attr(V, index, VI),
5753              get_attr(V, lowlink, VI) } -> pop_stack_to(V, VI)
5754        ;   []
5755        ).
5756
5757pop_stack_to(V, N) -->
5758        state(s(I,[First|Stack],Succ), s(I,Stack,Succ)),
5759        { del_attr(First, in_stack) },
5760        (   { First == V } -> []
5761        ;   { put_attr(First, lowlink, N) },
5762            pop_stack_to(V, N)
5763        ).
5764
5765each_edge([], _) --> [].
5766each_edge([VP|VPs], V) -->
5767        (   vindex_defined(VP) ->
5768            (   v_in_stack(VP) ->
5769                vlowlink_min_lowlink(V, VP)
5770            ;   []
5771            )
5772        ;   scc_(VP),
5773            vlowlink_min_lowlink(V, VP)
5774        ),
5775        each_edge(VPs, V).
5776
5777state(S), [S] --> [S].
5778
5779state(S0, S), [S] --> [S0].
5780
5781v_in_stack(V) --> { get_attr(V, in_stack, true) }.
5782
5783/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5784   Weak arc consistent constraint of difference, currently only
5785   available internally. Candidate for all_different/2 option.
5786
5787   See Neng-Fa Zhou: "Programming Finite-Domain Constraint Propagators
5788   in Action Rules", Theory and Practice of Logic Programming, Vol.6,
5789   No.5, pp 483-508, 2006
5790- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
5791
5792weak_arc_all_distinct(Ls) :-
5793        must_be(list, Ls),
5794        Orig = original_goal(_, weak_arc_all_distinct(Ls)),
5795        all_distinct(Ls, [], Orig),
5796        do_queue.
5797
5798all_distinct([], _, _).
5799all_distinct([X|Right], Left, Orig) :-
5800        %\+ list_contains(Right, X),
5801        (   var(X) ->
5802            make_propagator(weak_distinct(Left,Right,X,Orig), Prop),
5803            init_propagator(X, Prop),
5804            trigger_prop(Prop)
5805%             make_propagator(check_distinct(Left,Right,X), Prop2),
5806%             init_propagator(X, Prop2),
5807%             trigger_prop(Prop2)
5808        ;   exclude_fire(Left, Right, X)
5809        ),
5810        outof_reducer(Left, Right, X),
5811        all_distinct(Right, [X|Left], Orig).
5812
5813exclude_fire(Left, Right, E) :-
5814        all_neq(Left, E),
5815        all_neq(Right, E).
5816
5817list_contains([X|Xs], Y) :-
5818        (   X == Y -> true
5819        ;   list_contains(Xs, Y)
5820        ).
5821
5822kill_if_isolated(Left, Right, X, MState) :-
5823        append(Left, Right, Others),
5824        fd_get(X, XDom, _),
5825        (   all_empty_intersection(Others, XDom) -> kill(MState)
5826        ;   true
5827        ).
5828
5829all_empty_intersection([], _).
5830all_empty_intersection([V|Vs], XDom) :-
5831        (   fd_get(V, VDom, _) ->
5832            domains_intersection_(VDom, XDom, empty),
5833            all_empty_intersection(Vs, XDom)
5834        ;   all_empty_intersection(Vs, XDom)
5835        ).
5836
5837outof_reducer(Left, Right, Var) :-
5838        (   fd_get(Var, Dom, _) ->
5839            append(Left, Right, Others),
5840            domain_num_elements(Dom, N),
5841            num_subsets(Others, Dom, 0, Num, NonSubs),
5842            (   n(Num) cis_geq N -> false
5843            ;   n(Num) cis N - n(1) ->
5844                reduce_from_others(NonSubs, Dom)
5845            ;   true
5846            )
5847        ;   %\+ list_contains(Right, Var),
5848            %\+ list_contains(Left, Var)
5849            true
5850        ).
5851
5852reduce_from_others([], _).
5853reduce_from_others([X|Xs], Dom) :-
5854        (   fd_get(X, XDom, XPs) ->
5855            domain_subtract(XDom, Dom, NXDom),
5856            fd_put(X, NXDom, XPs)
5857        ;   true
5858        ),
5859        reduce_from_others(Xs, Dom).
5860
5861num_subsets([], _Dom, Num, Num, []).
5862num_subsets([S|Ss], Dom, Num0, Num, NonSubs) :-
5863        (   fd_get(S, SDom, _) ->
5864            (   domain_subdomain(Dom, SDom) ->
5865                Num1 is Num0 + 1,
5866                num_subsets(Ss, Dom, Num1, Num, NonSubs)
5867            ;   NonSubs = [S|Rest],
5868                num_subsets(Ss, Dom, Num0, Num, Rest)
5869            )
5870        ;   num_subsets(Ss, Dom, Num0, Num, NonSubs)
5871        ).
5872
5873%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5874
5875%%  serialized(+Starts, +Durations)
5876%
5877%   Describes a set of non-overlapping tasks.
5878%   Starts = [S_1,...,S_n], is a list of variables or integers,
5879%   Durations = [D_1,...,D_n] is a list of non-negative integers.
5880%   Constrains Starts and Durations to denote a set of
5881%   non-overlapping tasks, i.e.: S_i + D_i =< S_j or S_j + D_j =<
5882%   S_i for all 1 =< i < j =< n. Example:
5883%
5884%   ==
5885%   ?- length(Vs, 3),
5886%      Vs ins 0..3,
5887%      serialized(Vs, [1,2,3]),
5888%      label(Vs).
5889%   Vs = [0, 1, 3] ;
5890%   Vs = [2, 0, 3] ;
5891%   false.
5892%   ==
5893%
5894%  @see Dorndorf et al. 2000, "Constraint Propagation Techniques for the
5895%       Disjunctive Scheduling Problem"
5896
5897serialized(Starts, Durations) :-
5898        must_be(list(integer), Durations),
5899        pairs_keys_values(SDs, Starts, Durations),
5900        Orig = original_goal(_, serialized(Starts, Durations)),
5901        serialize(SDs, Orig).
5902
5903serialize([], _).
5904serialize([S-D|SDs], Orig) :-
5905        D >= 0,
5906        serialize(SDs, S, D, Orig),
5907        serialize(SDs, Orig).
5908
5909serialize([], _, _, _).
5910serialize([S-D|Rest], S0, D0, Orig) :-
5911        D >= 0,
5912        propagator_init_trigger([S0,S], pserialized(S,D,S0,D0,Orig)),
5913        serialize(Rest, S0, D0, Orig).
5914
5915% consistency check / propagation
5916% Currently implements 2-b-consistency
5917
5918earliest_start_time(Start, EST) :-
5919        (   fd_get(Start, D, _) ->
5920            domain_infimum(D, EST)
5921        ;   EST = n(Start)
5922        ).
5923
5924latest_start_time(Start, LST) :-
5925        (   fd_get(Start, D, _) ->
5926            domain_supremum(D, LST)
5927        ;   LST = n(Start)
5928        ).
5929
5930serialize_lower_upper(S_I, D_I, S_J, D_J, MState) :-
5931        (   var(S_I) ->
5932            serialize_lower_bound(S_I, D_I, S_J, D_J, MState),
5933            (   var(S_I) -> serialize_upper_bound(S_I, D_I, S_J, D_J, MState)
5934            ;   true
5935            )
5936        ;   true
5937        ).
5938
5939serialize_lower_bound(I, D_I, J, D_J, MState) :-
5940        fd_get(I, DomI, Ps),
5941        (   domain_infimum(DomI, n(EST_I)),
5942            latest_start_time(J, n(LST_J)),
5943            EST_I + D_I > LST_J,
5944            earliest_start_time(J, n(EST_J)) ->
5945            (   nonvar(J) -> kill(MState)
5946            ;   true
5947            ),
5948            EST is EST_J+D_J,
5949            domain_remove_smaller_than(DomI, EST, DomI1),
5950            fd_put(I, DomI1, Ps)
5951        ;   true
5952        ).
5953
5954serialize_upper_bound(I, D_I, J, D_J, MState) :-
5955        fd_get(I, DomI, Ps),
5956        (   domain_supremum(DomI, n(LST_I)),
5957            earliest_start_time(J, n(EST_J)),
5958            EST_J + D_J > LST_I,
5959            latest_start_time(J, n(LST_J)) ->
5960            (   nonvar(J) -> kill(MState)
5961            ;   true
5962            ),
5963            LST is LST_J-D_I,
5964            domain_remove_greater_than(DomI, LST, DomI1),
5965            fd_put(I, DomI1, Ps)
5966        ;   true
5967        ).
5968
5969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5970
5971%%    element(?N, +Vs, ?V)
5972%
5973%     The N-th element of the list of finite domain variables Vs is V.
5974%     Analogous to nth1/3.
5975
5976element(N, Is, V) :-
5977        must_be(list, Is),
5978        length(Is, L),
5979        N in 1..L,
5980        element_(Is, 1, N, V),
5981        propagator_init_trigger([N|Is], pelement(N,Is,V)).
5982
5983element_domain(V, VD) :-
5984        (   fd_get(V, VD, _) -> true
5985        ;   VD = from_to(n(V), n(V))
5986        ).
5987
5988element_([], _, _, _).
5989element_([I|Is], N0, N, V) :-
5990        ?(I) #\= ?(V) #==> ?(N) #\= N0,
5991        N1 is N0 + 1,
5992        element_(Is, N1, N, V).
5993
5994integers_remaining([], _, _, D, D).
5995integers_remaining([V|Vs], N0, Dom, D0, D) :-
5996        (   domain_contains(Dom, N0) ->
5997            element_domain(V, VD),
5998            domains_union(D0, VD, D1)
5999        ;   D1 = D0
6000        ),
6001        N1 is N0 + 1,
6002        integers_remaining(Vs, N1, Dom, D1, D).
6003
6004%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6005
6006%%    global_cardinality(+Vs, +Pairs)
6007%
6008%     Global Cardinality constraint. Equivalent to
6009%     global_cardinality(Vs, Pairs, []). See global_cardinality/3.
6010%
6011%     Example:
6012%
6013%     ==
6014%     ?- Vs = [_,_,_], global_cardinality(Vs, [1-2,3-_]), label(Vs).
6015%     Vs = [1, 1, 3] ;
6016%     Vs = [1, 3, 1] ;
6017%     Vs = [3, 1, 1].
6018%     ==
6019
6020global_cardinality(Xs, Pairs) :- global_cardinality(Xs, Pairs, []).
6021
6022%%    global_cardinality(+Vs, +Pairs, +Options)
6023%
6024%     Global Cardinality constraint. Vs  is  a   list  of  finite domain
6025%     variables, Pairs is a list  of  Key-Num   pairs,  where  Key is an
6026%     integer and Num is a finite  domain variable. The constraint holds
6027%     iff each V in Vs is equal to   some key, and for each Key-Num pair
6028%     in Pairs, the number of occurrences of   Key in Vs is Num. Options
6029%     is a list of options. Supported options are:
6030%
6031%     * consistency(value)
6032%     A weaker form of consistency is used.
6033%
6034%     * cost(Cost, Matrix)
6035%     Matrix is a list of rows, one for each variable, in the order
6036%     they occur in Vs. Each of these rows is a list of integers, one
6037%     for each key, in the order these keys occur in Pairs. When
6038%     variable v_i is assigned the value of key k_j, then the
6039%     associated cost is Matrix_{ij}. Cost is the sum of all costs.
6040
6041global_cardinality(Xs, Pairs, Options) :-
6042        must_be(list(list), [Xs,Pairs,Options]),
6043        maplist(fd_variable, Xs),
6044        maplist(gcc_pair, Pairs),
6045        pairs_keys_values(Pairs, Keys, Nums),
6046        (   sort(Keys, Keys1), same_length(Keys, Keys1) -> true
6047        ;   domain_error(gcc_unique_key_pairs, Pairs)
6048        ),
6049        length(Xs, L),
6050        Nums ins 0..L,
6051        list_to_drep(Keys, Drep),
6052        Xs ins Drep,
6053        gcc_pairs(Pairs, Xs, Pairs1),
6054        % pgcc_check must be installed before triggering other
6055        % propagators
6056        propagator_init_trigger(Xs, pgcc_check(Pairs1)),
6057        propagator_init_trigger(Nums, pgcc_check_single(Pairs1)),
6058        (   member(OD, Options), OD == consistency(value) -> true
6059        ;   propagator_init_trigger(Nums, pgcc_single(Xs, Pairs1)),
6060            propagator_init_trigger(Xs, pgcc(Xs, Pairs, Pairs1))
6061        ),
6062        (   member(OC, Options), functor(OC, cost, 2) ->
6063            OC = cost(Cost, Matrix),
6064            must_be(list(list(integer)), Matrix),
6065            maplist(keys_costs(Keys), Xs, Matrix, Costs),
6066            sum(Costs, #=, Cost)
6067        ;   true
6068        ).
6069
6070keys_costs(Keys, X, Row, C) :-
6071        element(N, Keys, X),
6072        element(N, Row, C).
6073
6074gcc_pair(Pair) :-
6075        (   Pair = Key-Val ->
6076            must_be(integer, Key),
6077            fd_variable(Val)
6078        ;   domain_error(gcc_pair, Pair)
6079        ).
6080
6081/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6082   For each Key-Num0 pair, we introduce an auxiliary variable Num and
6083   attach the following attributes to it:
6084
6085   clpfd_gcc_num: equal Num0, the user-visible counter variable
6086   clpfd_gcc_vs: the remaining variables in the constraint that can be
6087   equal Key.
6088   clpfd_gcc_occurred: stores how often Key already occurred in vs.
6089- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6090
6091gcc_pairs([], _, []).
6092gcc_pairs([Key-Num0|KNs], Vs, [Key-Num|Rest]) :-
6093        put_attr(Num, clpfd_gcc_num, Num0),
6094        put_attr(Num, clpfd_gcc_vs, Vs),
6095        put_attr(Num, clpfd_gcc_occurred, 0),
6096        gcc_pairs(KNs, Vs, Rest).
6097
6098/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6099    J.-C. Régin: "Generalized Arc Consistency for Global Cardinality
6100    Constraint", AAAI-96 Portland, OR, USA, pp 209--215, 1996
6101- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6102
6103gcc_global(Vs, KNs) :-
6104        gcc_check(KNs),
6105        % reach fix-point: all elements of clpfd_gcc_vs must be variables
6106        do_queue,
6107        with_local_attributes(Vs, [edges,parent,index],
6108              (gcc_arcs(KNs, S, Vals),
6109               variables_with_num_occurrences(Vs, VNs),
6110               maplist(target_to_v(T), VNs),
6111               (   get_attr(S, edges, Es) ->
6112                   put_attr(S, parent, none), % Mark S as seen to avoid going back to S.
6113                   feasible_flow(Es, S, T), % First construct a feasible flow (if any)
6114                   maximum_flow(S, T),      % only then, maximize it.
6115                   gcc_consistent(T),
6116                   scc(Vals, gcc_successors),
6117                   phrase(gcc_goals(Vals), Gs)
6118               ;   Gs = [] )), Gs),
6119        disable_queue,
6120        maplist(call, Gs),
6121        enable_queue.
6122
6123gcc_consistent(T) :-
6124        get_attr(T, edges, Es),
6125        maplist(saturated_arc, Es).
6126
6127saturated_arc(arc_from(_,U,_,Flow)) :- get_attr(Flow, flow, U).
6128
6129gcc_goals([]) --> [].
6130gcc_goals([Val|Vals]) -->
6131        { get_attr(Val, edges, Es) },
6132        gcc_edges_goals(Es, Val),
6133        gcc_goals(Vals).
6134
6135gcc_edges_goals([], _) --> [].
6136gcc_edges_goals([E|Es], Val) -->
6137        gcc_edge_goal(E, Val),
6138        gcc_edges_goals(Es, Val).
6139
6140gcc_edge_goal(arc_from(_,_,_,_), _) --> [].
6141gcc_edge_goal(arc_to(_,_,V,F), Val) -->
6142        (   { get_attr(F, flow, 0),
6143              get_attr(V, lowlink, L1),
6144              get_attr(Val, lowlink, L2),
6145              L1 =\= L2,
6146              get_attr(Val, value, Value) } ->
6147            [neq_num(V, Value)]
6148        ;   []
6149        ).
6150
6151/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6152   Like in all_distinct/1, first use breadth-first search, then
6153   construct an augmenting path in reverse.
6154- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6155
6156maximum_flow(S, T) :-
6157        (   gcc_augmenting_path([[S]], Levels, T) ->
6158            phrase(augmenting_path(S, T), Path),
6159            Path = [augment(_,First,_)|Rest],
6160            path_minimum(Rest, First, Min),
6161            maplist(gcc_augment(Min), Path),
6162            maplist(maplist(clear_parent), Levels),
6163            maximum_flow(S, T)
6164        ;   true
6165        ).
6166
6167feasible_flow([], _, _).
6168feasible_flow([A|As], S, T) :-
6169        make_arc_feasible(A, S, T),
6170        feasible_flow(As, S, T).
6171
6172make_arc_feasible(A, S, T) :-
6173        A = arc_to(L,_,V,F),
6174        get_attr(F, flow, Flow),
6175        (   Flow >= L -> true
6176        ;   Diff is L - Flow,
6177            put_attr(V, parent, S-augment(F,Diff,+)),
6178            gcc_augmenting_path([[V]], Levels, T),
6179            phrase(augmenting_path(S, T), Path),
6180            path_minimum(Path, Diff, Min),
6181            maplist(gcc_augment(Min), Path),
6182            maplist(maplist(clear_parent), Levels),
6183            make_arc_feasible(A, S, T)
6184        ).
6185
6186gcc_augmenting_path(Levels0, Levels, T) :-
6187        Levels0 = [Vs|_],
6188        Levels1 = [Tos|Levels0],
6189        phrase(gcc_reachables(Vs), Tos),
6190        Tos = [_|_],
6191        (   member(To, Tos), To == T -> Levels = Levels1
6192        ;   gcc_augmenting_path(Levels1, Levels, T)
6193        ).
6194
6195gcc_reachables([])     --> [].
6196gcc_reachables([V|Vs]) -->
6197        { get_attr(V, edges, Es) },
6198        gcc_reachables_(Es, V),
6199        gcc_reachables(Vs).
6200
6201gcc_reachables_([], _)     --> [].
6202gcc_reachables_([E|Es], V) -->
6203        gcc_reachable(E, V),
6204        gcc_reachables_(Es, V).
6205
6206gcc_reachable(arc_from(_,_,V,F), P) -->
6207        (   { \+ get_attr(V, parent, _),
6208              get_attr(F, flow, Flow),
6209              Flow > 0 } ->
6210            { put_attr(V, parent, P-augment(F,Flow,-)) },
6211            [V]
6212        ;   []
6213        ).
6214gcc_reachable(arc_to(_L,U,V,F), P) -->
6215        (   { \+ get_attr(V, parent, _),
6216              get_attr(F, flow, Flow),
6217              Flow < U } ->
6218            { Diff is U - Flow,
6219              put_attr(V, parent, P-augment(F,Diff,+)) },
6220            [V]
6221        ;   []
6222        ).
6223
6224
6225path_minimum([], Min, Min).
6226path_minimum([augment(_,A,_)|As], Min0, Min) :-
6227        Min1 is min(Min0,A),
6228        path_minimum(As, Min1, Min).
6229
6230gcc_augment(Min, augment(F,_,Sign)) :-
6231        get_attr(F, flow, Flow0),
6232        gcc_flow_(Sign, Flow0, Min, Flow),
6233        put_attr(F, flow, Flow).
6234
6235gcc_flow_(+, F0, A, F) :- F is F0 + A.
6236gcc_flow_(-, F0, A, F) :- F is F0 - A.
6237
6238/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6239   Build value network for global cardinality constraint.
6240- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6241
6242gcc_arcs([], _, []).
6243gcc_arcs([Key-Num0|KNs], S, Vals) :-
6244        (   get_attr(Num0, clpfd_gcc_vs, Vs) ->
6245            get_attr(Num0, clpfd_gcc_num, Num),
6246            get_attr(Num0, clpfd_gcc_occurred, Occ),
6247            (   nonvar(Num) -> U is Num - Occ, U = L
6248            ;   fd_get(Num, _, n(L0), n(U0), _),
6249                L is L0 - Occ, U is U0 - Occ
6250            ),
6251            put_attr(Val, value, Key),
6252            Vals = [Val|Rest],
6253            put_attr(F, flow, 0),
6254            append_edge(S, edges, arc_to(L, U, Val, F)),
6255            put_attr(Val, edges, [arc_from(L, U, S, F)]),
6256            variables_with_num_occurrences(Vs, VNs),
6257            maplist(val_to_v(Val), VNs)
6258        ;   Vals = Rest
6259        ),
6260        gcc_arcs(KNs, S, Rest).
6261
6262variables_with_num_occurrences(Vs0, VNs) :-
6263        include(var, Vs0, Vs1),
6264        msort(Vs1, Vs),
6265        (   Vs == [] -> VNs = []
6266        ;   Vs = [V|Rest],
6267            variables_with_num_occurrences(Rest, V, 1, VNs)
6268        ).
6269
6270variables_with_num_occurrences([], Prev, Count, [Prev-Count]).
6271variables_with_num_occurrences([V|Vs], Prev, Count0, VNs) :-
6272        (   V == Prev ->
6273            Count1 is Count0 + 1,
6274            variables_with_num_occurrences(Vs, Prev, Count1, VNs)
6275        ;   VNs = [Prev-Count0|Rest],
6276            variables_with_num_occurrences(Vs, V, 1, Rest)
6277        ).
6278
6279
6280target_to_v(T, V-Count) :-
6281        put_attr(F, flow, 0),
6282        append_edge(V, edges, arc_to(0, Count, T, F)),
6283        append_edge(T, edges, arc_from(0, Count, V, F)).
6284
6285val_to_v(Val, V-Count) :-
6286        put_attr(F, flow, 0),
6287        append_edge(V, edges, arc_from(0, Count, Val, F)),
6288        append_edge(Val, edges, arc_to(0, Count, V, F)).
6289
6290
6291gcc_successors(V, Tos) :-
6292        get_attr(V, edges, Tos0),
6293        phrase(gcc_successors_(Tos0), Tos).
6294
6295gcc_successors_([])     --> [].
6296gcc_successors_([E|Es]) --> gcc_succ_edge(E), gcc_successors_(Es).
6297
6298gcc_succ_edge(arc_to(_,U,V,F)) -->
6299        (   { get_attr(F, flow, Flow),
6300              Flow < U } -> [V]
6301        ;   []
6302        ).
6303gcc_succ_edge(arc_from(_,_,V,F)) -->
6304        (   { get_attr(F, flow, Flow),
6305              Flow > 0 } -> [V]
6306        ;   []
6307        ).
6308
6309/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6310   Simple consistency check, run before global propagation.
6311   Importantly, it removes all ground values from clpfd_gcc_vs.
6312
6313   The pgcc_check/1 propagator in itself suffices to ensure
6314   consistency.
6315- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6316
6317gcc_check(Pairs) :-
6318        disable_queue,
6319        gcc_check_(Pairs),
6320        enable_queue.
6321
6322gcc_done(Num) :-
6323        del_attr(Num, clpfd_gcc_vs),
6324        del_attr(Num, clpfd_gcc_num),
6325        del_attr(Num, clpfd_gcc_occurred).
6326
6327gcc_check_([]).
6328gcc_check_([Key-Num0|KNs]) :-
6329        (   get_attr(Num0, clpfd_gcc_vs, Vs) ->
6330            get_attr(Num0, clpfd_gcc_num, Num),
6331            get_attr(Num0, clpfd_gcc_occurred, Occ0),
6332            vs_key_min_others(Vs, Key, 0, Min, Os),
6333            put_attr(Num0, clpfd_gcc_vs, Os),
6334            put_attr(Num0, clpfd_gcc_occurred, Occ1),
6335            Occ1 is Occ0 + Min,
6336            geq(Num, Occ1),
6337            % The queue is disabled for efficiency here in any case.
6338            % If it were enabled, make sure to retain the invariant
6339            % that gcc_global is never triggered during an
6340            % inconsistent state (after gcc_done/1 but before all
6341            % relevant constraints are posted).
6342            (   Occ1 == Num -> all_neq(Os, Key), gcc_done(Num0)
6343            ;   Os == [] -> gcc_done(Num0), Num = Occ1
6344            ;   length(Os, L),
6345                Max is Occ1 + L,
6346                geq(Max, Num),
6347                (   nonvar(Num) -> Diff is Num - Occ1
6348                ;   fd_get(Num, ND, _),
6349                    domain_infimum(ND, n(NInf)),
6350                    Diff is NInf - Occ1
6351                ),
6352                L >= Diff,
6353                (   L =:= Diff ->
6354                    Num is Occ1 + Diff,
6355                    maplist(=(Key), Os),
6356                    gcc_done(Num0)
6357                ;   true
6358                )
6359            )
6360        ;   true
6361        ),
6362        gcc_check_(KNs).
6363
6364vs_key_min_others([], _, Min, Min, []).
6365vs_key_min_others([V|Vs], Key, Min0, Min, Others) :-
6366        (   fd_get(V, VD, _) ->
6367            (   domain_contains(VD, Key) ->
6368                Others = [V|Rest],
6369                vs_key_min_others(Vs, Key, Min0, Min, Rest)
6370            ;   vs_key_min_others(Vs, Key, Min0, Min, Others)
6371            )
6372        ;   (   V =:= Key ->
6373                Min1 is Min0 + 1,
6374                vs_key_min_others(Vs, Key, Min1, Min, Others)
6375            ;   vs_key_min_others(Vs, Key, Min0, Min, Others)
6376            )
6377        ).
6378
6379all_neq([], _).
6380all_neq([X|Xs], C) :-
6381        neq_num(X, C),
6382        all_neq(Xs, C).
6383
6384%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6385
6386%%    circuit(+Vs)
6387%
6388%     True iff the list Vs of finite domain variables induces a
6389%     Hamiltonian circuit. The k-th element of Vs denotes the
6390%     successor of node k. Node indexing starts with 1. Examples:
6391%
6392%     ==
6393%     ?- length(Vs, _), circuit(Vs), label(Vs).
6394%     Vs = [] ;
6395%     Vs = [1] ;
6396%     Vs = [2, 1] ;
6397%     Vs = [2, 3, 1] ;
6398%     Vs = [3, 1, 2] ;
6399%     Vs = [2, 3, 4, 1] .
6400%     ==
6401
6402circuit(Vs) :-
6403        must_be(list, Vs),
6404        maplist(fd_variable, Vs),
6405        length(Vs, L),
6406        Vs ins 1..L,
6407        (   L =:= 1 -> true
6408        ;   neq_index(Vs, 1),
6409            make_propagator(pcircuit(Vs), Prop),
6410            distinct_attach(Vs, Prop, []),
6411            trigger_once(Prop)
6412        ).
6413
6414neq_index([], _).
6415neq_index([X|Xs], N) :-
6416        neq_num(X, N),
6417        N1 is N + 1,
6418        neq_index(Xs, N1).
6419
6420/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6421   Necessary condition for existence of a Hamiltonian circuit: The
6422   graph has a single strongly connected component. If the list is
6423   ground, the condition is also sufficient.
6424
6425   Ts are used as temporary variables to attach attributes:
6426
6427   lowlink, index: used for SCC
6428   [arc_to(V)]: possible successors
6429- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6430
6431propagate_circuit(Vs) :-
6432        with_local_attributes([], [],
6433            (same_length(Vs, Ts),
6434             circuit_graph(Vs, Ts, Ts),
6435             scc(Ts, circuit_successors),
6436             maplist(single_component, Ts)), _).
6437
6438single_component(V) :- get_attr(V, lowlink, 0).
6439
6440circuit_graph([], _, _).
6441circuit_graph([V|Vs], Ts0, [T|Ts]) :-
6442        (   nonvar(V) -> Ns = [V]
6443        ;   fd_get(V, Dom, _),
6444            domain_to_list(Dom, Ns)
6445        ),
6446        phrase(circuit_edges(Ns, Ts0), Es),
6447        put_attr(T, edges, Es),
6448        circuit_graph(Vs, Ts0, Ts).
6449
6450circuit_edges([], _) --> [].
6451circuit_edges([N|Ns], Ts) -->
6452        { nth1(N, Ts, T) },
6453        [arc_to(T)],
6454        circuit_edges(Ns, Ts).
6455
6456circuit_successors(V, Tos) :-
6457        get_attr(V, edges, Tos0),
6458        maplist(arg(1), Tos0, Tos).
6459
6460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6461
6462%% cumulative(+Tasks)
6463%
6464%  Equivalent to cumulative(Tasks, [limit(1)]). See cumulative/2.
6465
6466cumulative(Tasks) :- cumulative(Tasks, [limit(1)]).
6467
6468%% cumulative(+Tasks, +Options)
6469%
6470%  Schedule with a limited resource. Tasks is a list of tasks, each of
6471%  the form task(S_i, D_i, E_i, C_i, T_i). S_i denotes the start time,
6472%  D_i the positive duration, E_i the end time, C_i the non-negative
6473%  resource consumption, and T_i the task identifier. Each of these
6474%  arguments must be a finite domain variable with bounded domain, or
6475%  an integer. The constraint holds iff at each time slot during the
6476%  start and end of each task, the total resource consumption of all
6477%  tasks running at that time does not exceed the global resource
6478%  limit. Options is a list of options. Currently, the only supported
6479%  option is:
6480%
6481%    * limit(L)
6482%      The integer L is the global resource limit. Default is 1.
6483%
6484%  For example, given the following predicate that relates three tasks
6485%  of durations 2 and 3 to a list containing their starting times:
6486%
6487%  ==
6488%  tasks_starts(Tasks, [S1,S2,S3]) :-
6489%          Tasks = [task(S1,3,_,1,_),
6490%                   task(S2,2,_,1,_),
6491%                   task(S3,2,_,1,_)].
6492%  ==
6493%
6494%  We can use cumulative/2 as follows, and obtain a schedule:
6495%
6496%  ==
6497%  ?- tasks_starts(Tasks, Starts), Starts ins 0..10,
6498%     cumulative(Tasks, [limit(2)]), label(Starts).
6499%  Tasks = [task(0, 3, 3, 1, _G36), task(0, 2, 2, 1, _G45), ...],
6500%  Starts = [0, 0, 2] .
6501%  ==
6502
6503cumulative(Tasks, Options) :-
6504        must_be(list(list), [Tasks,Options]),
6505        (   Options = [] -> L = 1
6506        ;   Options = [limit(L)] -> must_be(integer, L)
6507        ;   domain_error(cumulative_options_empty_or_limit, Options)
6508        ),
6509        (   Tasks = [] -> true
6510        ;   fully_elastic_relaxation(Tasks, L),
6511            maplist(task_bs, Tasks, Bss),
6512            maplist(arg(1), Tasks, Starts),
6513            maplist(fd_inf, Starts, MinStarts),
6514            maplist(arg(3), Tasks, Ends),
6515            maplist(fd_sup, Ends, MaxEnds),
6516            min_list(MinStarts, Start),
6517            max_list(MaxEnds, End),
6518            resource_limit(Start, End, Tasks, Bss, L)
6519        ).
6520
6521/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6522   Trivial lower and upper bounds, assuming no gaps and not necessarily
6523   retaining the rectangular shape of each task.
6524- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6525
6526fully_elastic_relaxation(Tasks, Limit) :-
6527        maplist(task_duration_consumption, Tasks, Ds, Cs),
6528        maplist(area, Ds, Cs, As),
6529        sum(As, #=, ?(Area)),
6530        ?(MinTime) #= (Area + Limit - 1) // Limit,
6531        tasks_minstart_maxend(Tasks, MinStart, MaxEnd),
6532        MaxEnd #>= MinStart + MinTime.
6533
6534task_duration_consumption(task(_,D,_,C,_), D, C).
6535
6536area(X, Y, Area) :- ?(Area) #= ?(X) * ?(Y).
6537
6538tasks_minstart_maxend(Tasks, Start, End) :-
6539        maplist(task_start_end, Tasks, [Start0|Starts], [End0|Ends]),
6540        foldl(min_, Starts, Start0, Start),
6541        foldl(max_, Ends, End0, End).
6542
6543max_(E, M0, M) :- ?(M) #= max(E, M0).
6544
6545min_(E, M0, M) :- ?(M) #= min(E, M0).
6546
6547task_start_end(task(Start,_,End,_,_), ?(Start), ?(End)).
6548
6549/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6550   All time slots must respect the resource limit.
6551- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
6552
6553resource_limit(T, T, _, _, _) :- !.
6554resource_limit(T0, T, Tasks, Bss, L) :-
6555        maplist(contribution_at(T0), Tasks, Bss, Cs),
6556        sum(Cs, #=<, L),
6557        T1 is T0 + 1,
6558        resource_limit(T1, T, Tasks, Bss, L).
6559
6560task_bs(Task, InfStart-Bs) :-
6561        Task = task(Start,D,End,_,_Id),
6562        ?(D) #> 0,
6563        ?(End) #= ?(Start) + ?(D),
6564        maplist(must_be_finite_fdvar, [End,Start,D]),
6565        fd_inf(Start, InfStart),
6566        fd_sup(End, SupEnd),
6567        L is SupEnd - InfStart,
6568        length(Bs, L),
6569        task_running(Bs, Start, End, InfStart).
6570
6571task_running([], _, _, _).
6572task_running([B|Bs], Start, End, T) :-
6573        ((T #>= Start) #/\ (T #< End)) #<==> ?(B),
6574        T1 is T + 1,
6575        task_running(Bs, Start, End, T1).
6576
6577contribution_at(T, Task, Offset-Bs, Contribution) :-
6578        Task = task(Start,_,End,C,_),
6579        ?(C) #>= 0,
6580        fd_inf(Start, InfStart),
6581        fd_sup(End, SupEnd),
6582        (   T < InfStart -> Contribution = 0
6583        ;   T >= SupEnd -> Contribution = 0
6584        ;   Index is T - Offset,
6585            nth0(Index, Bs, B),
6586            ?(Contribution) #= B*C
6587        ).
6588
6589%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6590
6591%% disjoint2(+Rectangles)
6592%
6593%  True iff Rectangles are not overlapping. Rectangles is a list of
6594%  terms of the form F(X_i, W_i, Y_i, H_i), where F is any functor,
6595%  and the arguments are finite domain variables or integers that
6596%  denote, respectively, the X coordinate, width, Y coordinate and
6597%  height of each rectangle.
6598
6599disjoint2(Rs0) :-
6600        must_be(list, Rs0),
6601        maplist(=.., Rs0, Rs),
6602        non_overlapping(Rs).
6603
6604non_overlapping([]).
6605non_overlapping([R|Rs]) :-
6606        maplist(non_overlapping_(R), Rs),
6607        non_overlapping(Rs).
6608
6609non_overlapping_(A, B) :-
6610        a_not_in_b(A, B),
6611        a_not_in_b(B, A).
6612
6613a_not_in_b([_,AX,AW,AY,AH], [_,BX,BW,BY,BH]) :-
6614        ?(AX) #=< ?(BX) #/\ ?(BX) #< ?(AX) + ?(AW) #==>
6615                   ?(AY) + ?(AH) #=< ?(BY) #\/ ?(BY) + ?(BH) #=< ?(AY),
6616        ?(AY) #=< ?(BY) #/\ ?(BY) #< ?(AY) + ?(AH) #==>
6617                   ?(AX) + ?(AW) #=< ?(BX) #\/ ?(BX) + ?(BW) #=< ?(AX).
6618
6619%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6620
6621%% automaton(+Vs, +Nodes, +Arcs)
6622%
6623%  Describes a list of finite domain variables with a finite
6624%  automaton. Equivalent to automaton(Vs, _, Vs, Nodes, Arcs,
6625%  [], [], _), a common use case of automaton/8. In the following
6626%  example, a list of binary finite domain variables is constrained to
6627%  contain at least two consecutive ones:
6628%
6629%  ==
6630%  two_consecutive_ones(Vs) :-
6631%          automaton(Vs, [source(a),sink(c)],
6632%                    [arc(a,0,a), arc(a,1,b),
6633%                     arc(b,0,a), arc(b,1,c),
6634%                     arc(c,0,c), arc(c,1,c)]).
6635%  ==
6636%
6637%  Example query:
6638%
6639%  ==
6640%  ?- length(Vs, 3), two_consecutive_ones(Vs), label(Vs).
6641%  Vs = [0, 1, 1] ;
6642%  Vs = [1, 1, 0] ;
6643%  Vs = [1, 1, 1].
6644%  ==
6645
6646automaton(Sigs, Ns, As) :- automaton(_, _, Sigs, Ns, As, [], [], _).
6647
6648
6649%% automaton(+Sequence, ?Template, +Signature, +Nodes, +Arcs, +Counters, +Initials, ?Finals)
6650%
6651%  Describes a list of finite domain variables with a finite
6652%  automaton. True iff the finite automaton induced by Nodes and Arcs
6653%  (extended with Counters) accepts Signature. Sequence is a list of
6654%  terms, all of the same shape. Additional constraints must link
6655%  Sequence to Signature, if necessary. Nodes is a list of
6656%  source(Node) and sink(Node) terms. Arcs is a list of
6657%  arc(Node,Integer,Node) and arc(Node,Integer,Node,Exprs) terms that
6658%  denote the automaton's transitions. Each node is represented by an
6659%  arbitrary term. Transitions that are not mentioned go to an
6660%  implicit failure node. `Exprs` is a list of arithmetic expressions,
6661%  of the same length as Counters. In each expression, variables
6662%  occurring in Counters symbolically refer to previous counter
6663%  values, and variables occurring in Template refer to the current
6664%  element of Sequence. When a transition containing arithmetic
6665%  expressions is taken, each counter is updated according to the
6666%  result of the corresponding expression. When a transition without
6667%  arithmetic expressions is taken, all counters remain unchanged.
6668%  Counters is a list of variables. Initials is a list of finite
6669%  domain variables or integers denoting, in the same order, the
6670%  initial value of each counter. These values are related to Finals
6671%  according to the arithmetic expressions of the taken transitions.
6672%
6673%  The following example is taken from Beldiceanu, Carlsson, Debruyne
6674%  and Petit: "Reformulation of Global Constraints Based on
6675%  Constraints Checkers", Constraints 10(4), pp 339-362 (2005). It
6676%  relates a sequence of integers and finite domain variables to its
6677%  number of inflexions, which are switches between strictly ascending
6678%  and strictly descending subsequences:
6679%
6680%  ==
6681%  sequence_inflexions(Vs, N) :-
6682%          variables_signature(Vs, Sigs),
6683%          automaton(Sigs, _, Sigs,
6684%                    [source(s),sink(i),sink(j),sink(s)],
6685%                    [arc(s,0,s), arc(s,1,j), arc(s,2,i),
6686%                     arc(i,0,i), arc(i,1,j,[C+1]), arc(i,2,i),
6687%                     arc(j,0,j), arc(j,1,j),
6688%                     arc(j,2,i,[C+1])],
6689%                    [C], [0], [N]).
6690%
6691%  variables_signature([], []).
6692%  variables_signature([V|Vs], Sigs) :-
6693%          variables_signature_(Vs, V, Sigs).
6694%
6695%  variables_signature_([], _, []).
6696%  variables_signature_([V|Vs], Prev, [S|Sigs]) :-
6697%          V #= Prev #<==> S #= 0,
6698%          Prev #< V #<==> S #= 1,
6699%          Prev #> V #<==> S #= 2,
6700%          variables_signature_(Vs, V, Sigs).
6701%  ==
6702%
6703%  Example queries:
6704%
6705%  ==
6706%  ?- sequence_inflexions([1,2,3,3,2,1,3,0], N).
6707%  N = 3.
6708%
6709%  ?- length(Ls, 5), Ls ins 0..1,
6710%     sequence_inflexions(Ls, 3), label(Ls).
6711%  Ls = [0, 1, 0, 1, 0] ;
6712%  Ls = [1, 0, 1, 0, 1].
6713%  ==
6714
6715template_var_path(V, Var, []) :- var(V), !, V == Var.
6716template_var_path(T, Var, [N|Ns]) :-
6717        arg(N, T, Arg),
6718        template_var_path(Arg, Var, Ns).
6719
6720path_term_variable([], V, V).
6721path_term_variable([P|Ps], T, V) :-
6722        arg(P, T, Arg),
6723        path_term_variable(Ps, Arg, V).
6724
6725initial_expr(_, []-1).
6726
6727automaton(Seqs, Template, Sigs, Ns, As0, Cs, Is, Fs) :-
6728        must_be(list(list), [Sigs,Ns,As0,Cs,Is]),
6729        (   var(Seqs) ->
6730            (   current_prolog_flag(clpfd_monotonic, true) ->
6731                instantiation_error(Seqs)
6732            ;   Seqs = Sigs
6733            )
6734        ;   must_be(list, Seqs)
6735        ),
6736        maplist(monotonic, Cs, CsM),
6737        maplist(arc_normalized(CsM), As0, As),
6738        include_args1(sink, Ns, Sinks),
6739        include_args1(source, Ns, Sources),
6740        maplist(initial_expr, Cs, Exprs0),
6741        phrase((arcs_relation(As, Relation),
6742                nodes_nums(Sinks, SinkNums0),
6743                nodes_nums(Sources, SourceNums0)),
6744               [s([]-0, Exprs0)], [s(_,Exprs1)]),
6745        maplist(expr0_expr, Exprs1, Exprs),
6746        phrase(transitions(Seqs, Template, Sigs, Start, End, Exprs, Cs, Is, Fs), Tuples),
6747        list_to_drep(SourceNums0, SourceDrep),
6748        Start in SourceDrep,
6749        list_to_drep(SinkNums0, SinkDrep),
6750        End in SinkDrep,
6751        tuples_in(Tuples, Relation).
6752
6753expr0_expr(Es0-_, Es) :-
6754        pairs_keys(Es0, Es1),
6755        reverse(Es1, Es).
6756
6757transitions([], _, [], S, S, _, _, Cs, Cs) --> [].
6758transitions([Seq|Seqs], Template, [Sig|Sigs], S0, S, Exprs, Counters, Cs0, Cs) -->
6759        [[S0,Sig,S1|Is]],
6760        { phrase(exprs_next(Exprs, Is, Cs1), [s(Seq,Template,Counters,Cs0)], _) },
6761        transitions(Seqs, Template, Sigs, S1, S, Exprs, Counters, Cs1, Cs).
6762
6763exprs_next([], [], []) --> [].
6764exprs_next([Es|Ess], [I|Is], [C|Cs]) -->
6765        exprs_values(Es, Vs),
6766        { element(I, Vs, C) },
6767        exprs_next(Ess, Is, Cs).
6768
6769exprs_values([], []) --> [].
6770exprs_values([E0|Es], [V|Vs]) -->
6771        { term_variables(E0, EVs0),
6772          copy_term(E0, E),
6773          term_variables(E, EVs),
6774          ?(V) #= E },
6775        match_variables(EVs0, EVs),
6776        exprs_values(Es, Vs).
6777
6778match_variables([], _) --> [].
6779match_variables([V0|Vs0], [V|Vs]) -->
6780        state(s(Seq,Template,Counters,Cs0)),
6781        { (   template_var_path(Template, V0, Ps) ->
6782              path_term_variable(Ps, Seq, V)
6783          ;   template_var_path(Counters, V0, Ps) ->
6784              path_term_variable(Ps, Cs0, V)
6785          ;   domain_error(variable_from_template_or_counters, V0)
6786          ) },
6787        match_variables(Vs0, Vs).
6788
6789nodes_nums([], []) --> [].
6790nodes_nums([Node|Nodes], [Num|Nums]) -->
6791        node_num(Node, Num),
6792        nodes_nums(Nodes, Nums).
6793
6794arcs_relation([], []) --> [].
6795arcs_relation([arc(S0,L,S1,Es)|As], [[From,L,To|Ns]|Rs]) -->
6796        node_num(S0, From),
6797        node_num(S1, To),
6798        state(s(Nodes, Exprs0), s(Nodes, Exprs)),
6799        { exprs_nums(Es, Ns, Exprs0, Exprs) },
6800        arcs_relation(As, Rs).
6801
6802exprs_nums([], [], [], []).
6803exprs_nums([E|Es], [N|Ns], [Ex0-C0|Exs0], [Ex-C|Exs]) :-
6804        (   member(Exp-N, Ex0), Exp == E -> C = C0, Ex = Ex0
6805        ;   N = C0, C is C0 + 1, Ex = [E-C0|Ex0]
6806        ),
6807        exprs_nums(Es, Ns, Exs0, Exs).
6808
6809node_num(Node, Num) -->
6810        state(s(Nodes0-C0, Exprs), s(Nodes-C, Exprs)),
6811        { (   member(N-Num, Nodes0), N == Node -> C = C0, Nodes = Nodes0
6812          ;   Num = C0, C is C0 + 1, Nodes = [Node-C0|Nodes0]
6813          )
6814        }.
6815
6816include_args1(Goal, Ls0, As) :-
6817        include(Goal, Ls0, Ls),
6818        maplist(arg(1), Ls, As).
6819
6820source(source(_)).
6821
6822sink(sink(_)).
6823
6824monotonic(Var, ?(Var)).
6825
6826arc_normalized(Cs, Arc0, Arc) :- arc_normalized_(Arc0, Cs, Arc).
6827
6828arc_normalized_(arc(S0,L,S,Cs), _, arc(S0,L,S,Cs)).
6829arc_normalized_(arc(S0,L,S), Cs, arc(S0,L,S,Cs)).
6830
6831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6832
6833%% transpose(+Matrix, ?Transpose)
6834%
6835%  Transpose a list of lists of the same length. Example:
6836%
6837%  ==
6838%  ?- transpose([[1,2,3],[4,5,6],[7,8,9]], Ts).
6839%  Ts = [[1, 4, 7], [2, 5, 8], [3, 6, 9]].
6840%  ==
6841%
6842%  This predicate is useful in many constraint programs. Consider for
6843%  instance Sudoku:
6844%
6845%  ==
6846%  sudoku(Rows) :-
6847%          length(Rows, 9), maplist(same_length(Rows), Rows),
6848%          append(Rows, Vs), Vs ins 1..9,
6849%          maplist(all_distinct, Rows),
6850%          transpose(Rows, Columns),
6851%          maplist(all_distinct, Columns),
6852%          Rows = [As,Bs,Cs,Ds,Es,Fs,Gs,Hs,Is],
6853%          blocks(As, Bs, Cs), blocks(Ds, Es, Fs), blocks(Gs, Hs, Is).
6854%
6855%  blocks([], [], []).
6856%  blocks([N1,N2,N3|Ns1], [N4,N5,N6|Ns2], [N7,N8,N9|Ns3]) :-
6857%          all_distinct([N1,N2,N3,N4,N5,N6,N7,N8,N9]),
6858%          blocks(Ns1, Ns2, Ns3).
6859%
6860%  problem(1, [[_,_,_,_,_,_,_,_,_],
6861%              [_,_,_,_,_,3,_,8,5],
6862%              [_,_,1,_,2,_,_,_,_],
6863%              [_,_,_,5,_,7,_,_,_],
6864%              [_,_,4,_,_,_,1,_,_],
6865%              [_,9,_,_,_,_,_,_,_],
6866%              [5,_,_,_,_,_,_,7,3],
6867%              [_,_,2,_,1,_,_,_,_],
6868%              [_,_,_,_,4,_,_,_,9]]).
6869%  ==
6870%
6871%  Sample query:
6872%
6873%  ==
6874%  ?- problem(1, Rows), sudoku(Rows), maplist(portray_clause, Rows).
6875%  [9, 8, 7, 6, 5, 4, 3, 2, 1].
6876%  [2, 4, 6, 1, 7, 3, 9, 8, 5].
6877%  [3, 5, 1, 9, 2, 8, 7, 4, 6].
6878%  [1, 2, 8, 5, 3, 7, 6, 9, 4].
6879%  [6, 3, 4, 8, 9, 2, 1, 5, 7].
6880%  [7, 9, 5, 4, 6, 1, 8, 3, 2].
6881%  [5, 1, 9, 2, 8, 6, 4, 7, 3].
6882%  [4, 7, 2, 3, 1, 9, 5, 6, 8].
6883%  [8, 6, 3, 7, 4, 5, 2, 1, 9].
6884%  Rows = [[9, 8, 7, 6, 5, 4, 3, 2|...], ... , [...|...]].
6885%  ==
6886
6887transpose(Ls, Ts) :-
6888        must_be(list(list), Ls),
6889        lists_transpose(Ls, Ts).
6890
6891lists_transpose([], []).
6892lists_transpose([L|Ls], Ts) :-
6893        maplist(same_length(L), Ls),
6894        foldl(transpose_, L, Ts, [L|Ls], _).
6895
6896transpose_(_, Fs, Lists0, Lists) :-
6897        maplist(list_first_rest, Lists0, Fs, Lists).
6898
6899list_first_rest([L|Ls], L, Ls).
6900
6901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6902
6903%% zcompare(?Order, ?A, ?B)
6904%
6905% Analogous to compare/3, with finite domain variables A and B.
6906%
6907% Think of zcompare/3 as _reifying_ an arithmetic comparison of two
6908% integers. This means that we can explicitly reason about the
6909% different cases _within_ our programs. As in compare/3, the atoms
6910% =|<|=, =|>|= and =|=|= denote the different cases of the
6911% trichotomy. In contrast to compare/3 though, zcompare/3 works
6912% correctly for _all modes_, also if only a subset of the arguments is
6913% instantiated. This allows you to make several predicates over
6914% integers deterministic while preserving their generality and
6915% completeness.  For example:
6916%
6917% ==
6918% n_factorial(N, F) :-
6919%         zcompare(C, N, 0),
6920%         n_factorial_(C, N, F).
6921%
6922% n_factorial_(=, _, 1).
6923% n_factorial_(>, N, F) :-
6924%         F #= F0*N,
6925%         N1 #= N - 1,
6926%         n_factorial(N1, F0).
6927% ==
6928%
6929% This version of n_factorial/2 is deterministic if the first argument
6930% is instantiated, because argument indexing can distinguish the
6931% different clauses that reflect the possible and admissible outcomes
6932% of a comparison of `N` against 0. Example:
6933%
6934% ==
6935% ?- n_factorial(30, F).
6936% F = 265252859812191058636308480000000.
6937% ==
6938%
6939% Since there is no clause for =|<|=, the predicate automatically
6940% _fails_ if `N` is less than 0. The predicate can still be used in
6941% all directions, including the most general query:
6942%
6943% ==
6944% ?- n_factorial(N, F).
6945% N = 0,
6946% F = 1 ;
6947% N = F, F = 1 ;
6948% N = F, F = 2 .
6949% ==
6950%
6951% In this case, all clauses are tried on backtracking, and zcompare/3
6952% ensures that the respective ordering between N and 0 holds in each
6953% case.
6954%
6955% The truth value of a comparison can also be reified with (#<==>)/2
6956% in combination with one of the [_arithmetic
6957% constraints_](<#clpfd-arith-constraints>). See
6958% [reification](<#clpfd-reification>). However, zcompare/3 lets you
6959% more conveniently distinguish the cases.
6960
6961zcompare(Order, A, B) :-
6962        (   nonvar(Order) ->
6963            zcompare_(Order, A, B)
6964        ;   integer(A), integer(B) ->
6965            compare(Order, A, B)
6966        ;   freeze(Order, zcompare_(Order, A, B)),
6967            fd_variable(A),
6968            fd_variable(B),
6969            propagator_init_trigger([A,B], pzcompare(Order, A, B))
6970        ).
6971
6972zcompare_(=, A, B) :- ?(A) #= ?(B).
6973zcompare_(<, A, B) :- ?(A) #< ?(B).
6974zcompare_(>, A, B) :- ?(A) #> ?(B).
6975
6976%% chain(+Zs, +Relation)
6977%
6978% Zs form a chain with respect to Relation. Zs is a list of finite
6979% domain variables that are a chain with respect to the partial order
6980% Relation, in the order they appear in the list. Relation must be #=,
6981% #=<, #>=, #< or #>. For example:
6982%
6983% ==
6984% ?- chain([X,Y,Z], #>=).
6985% X#>=Y,
6986% Y#>=Z.
6987% ==
6988
6989chain(Zs, Relation) :-
6990        must_be(list, Zs),
6991        maplist(fd_variable, Zs),
6992        must_be(ground, Relation),
6993        (   chain_relation(Relation) -> true
6994        ;   domain_error(chain_relation, Relation)
6995        ),
6996        chain_(Zs, Relation).
6997
6998chain_([], _).
6999chain_([X|Xs], Relation) :- foldl(chain(Relation), Xs, X, _).
7000
7001chain_relation(#=).
7002chain_relation(#<).
7003chain_relation(#=<).
7004chain_relation(#>).
7005chain_relation(#>=).
7006
7007chain(Relation, X, Prev, X) :- call(Relation, ?(Prev), ?(X)).
7008
7009%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
7010/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7011   Reflection predicates
7012- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7013
7014%% fd_var(+Var)
7015%
7016%  True iff Var is a CLP(FD) variable.
7017
7018fd_var(X) :- get_attr(X, clpfd, _).
7019
7020%% fd_inf(+Var, -Inf)
7021%
7022%  Inf is the infimum of the current domain of Var.
7023
7024fd_inf(X, Inf) :-
7025        (   fd_get(X, XD, _) ->
7026            domain_infimum(XD, Inf0),
7027            bound_portray(Inf0, Inf)
7028        ;   must_be(integer, X),
7029            Inf = X
7030        ).
7031
7032%% fd_sup(+Var, -Sup)
7033%
7034%  Sup is the supremum of the current domain of Var.
7035
7036fd_sup(X, Sup) :-
7037        (   fd_get(X, XD, _) ->
7038            domain_supremum(XD, Sup0),
7039            bound_portray(Sup0, Sup)
7040        ;   must_be(integer, X),
7041            Sup = X
7042        ).
7043
7044%% fd_size(+Var, -Size)
7045%
7046%  Reflect the current size of a domain. Size is the number of
7047%  elements of the current domain of Var, or the atom *sup* if the
7048%  domain is unbounded.
7049
7050fd_size(X, S) :-
7051        (   fd_get(X, XD, _) ->
7052            domain_num_elements(XD, S0),
7053            bound_portray(S0, S)
7054        ;   must_be(integer, X),
7055            S = 1
7056        ).
7057
7058%% fd_dom(+Var, -Dom)
7059%
7060%  Dom is the current domain (see in/2) of Var. This predicate is
7061%  useful if you want to reason about domains. It is _not_ needed if
7062%  you only want to display remaining domains; instead, separate your
7063%  model from the search part and let the toplevel display this
7064%  information via residual goals.
7065%
7066%  For example, to implement a custom labeling strategy, you may need
7067%  to inspect the current domain of a finite domain variable. With the
7068%  following code, you can convert a _finite_ domain to a list of
7069%  integers:
7070%
7071%  ==
7072%  dom_integers(D, Is) :- phrase(dom_integers_(D), Is).
7073%
7074%  dom_integers_(I)      --> { integer(I) }, [I].
7075%  dom_integers_(L..U)   --> { numlist(L, U, Is) }, Is.
7076%  dom_integers_(D1\/D2) --> dom_integers_(D1), dom_integers_(D2).
7077%  ==
7078%
7079%  Example:
7080%
7081%  ==
7082%  ?- X in 1..5, X #\= 4, fd_dom(X, D), dom_integers(D, Is).
7083%  D = 1..3\/5,
7084%  Is = [1,2,3,5],
7085%  X in 1..3\/5.
7086%  ==
7087
7088fd_dom(X, Drep) :-
7089        (   fd_get(X, XD, _) ->
7090            domain_to_drep(XD, Drep)
7091        ;   must_be(integer, X),
7092            Drep = X..X
7093        ).
7094
7095/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7096   Entailment detection. Subject to change.
7097
7098   Currently, Goals entail E if posting ({#\ E} U Goals), then
7099   labeling all variables, fails. E must be reifiable. Examples:
7100
7101   %?- clpfd:goals_entail([X#>2], X #> 3).
7102   %@ false.
7103
7104   %?- clpfd:goals_entail([X#>1, X#<3], X #= 2).
7105   %@ true.
7106
7107   %?- clpfd:goals_entail([X#=Y+1], X #= Y+1).
7108   %@ ERROR: Arguments are not sufficiently instantiated
7109   %@    Exception: (15) throw(error(instantiation_error, _G2680)) ?
7110
7111   %?- clpfd:goals_entail([[X,Y] ins 0..10, X#=Y+1], X #= Y+1).
7112   %@ true.
7113
7114- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7115
7116goals_entail(Goals, E) :-
7117        must_be(list, Goals),
7118        \+ (   maplist(call, Goals), #\ E,
7119               term_variables(Goals-E, Vs),
7120               label(Vs)
7121           ).
7122
7123/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7124   Unification hook and constraint projection
7125- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7126
7127attr_unify_hook(clpfd_attr(_,_,_,Dom,Ps), Other) :-
7128        (   nonvar(Other) ->
7129            (   integer(Other) -> true
7130            ;   type_error(integer, Other)
7131            ),
7132            domain_contains(Dom, Other),
7133            trigger_props(Ps),
7134            do_queue
7135        ;   fd_get(Other, OD, OPs),
7136            domains_intersection(OD, Dom, Dom1),
7137            append_propagators(Ps, OPs, Ps1),
7138            fd_put(Other, Dom1, Ps1),
7139            trigger_props(Ps1),
7140            do_queue
7141        ).
7142
7143append_propagators(fd_props(Gs0,Bs0,Os0), fd_props(Gs1,Bs1,Os1), fd_props(Gs,Bs,Os)) :-
7144        maplist(append, [Gs0,Bs0,Os0], [Gs1,Bs1,Os1], [Gs,Bs,Os]).
7145
7146bound_portray(inf, inf).
7147bound_portray(sup, sup).
7148bound_portray(n(N), N).
7149
7150list_to_drep(List, Drep) :-
7151        list_to_domain(List, Dom),
7152        domain_to_drep(Dom, Drep).
7153
7154domain_to_drep(Dom, Drep) :-
7155        domain_intervals(Dom, [A0-B0|Rest]),
7156        bound_portray(A0, A),
7157        bound_portray(B0, B),
7158        (   A == B -> Drep0 = A
7159        ;   Drep0 = A..B
7160        ),
7161        intervals_to_drep(Rest, Drep0, Drep).
7162
7163intervals_to_drep([], Drep, Drep).
7164intervals_to_drep([A0-B0|Rest], Drep0, Drep) :-
7165        bound_portray(A0, A),
7166        bound_portray(B0, B),
7167        (   A == B -> D1 = A
7168        ;   D1 = A..B
7169        ),
7170        intervals_to_drep(Rest, Drep0 \/ D1, Drep).
7171
7172attribute_goals(X) -->
7173        % { get_attr(X, clpfd, Attr), format("A: ~w\n", [Attr]) },
7174        { get_attr(X, clpfd, clpfd_attr(_,_,_,Dom,fd_props(Gs,Bs,Os))),
7175          append(Gs, Bs, Ps0),
7176          append(Ps0, Os, Ps),
7177          domain_to_drep(Dom, Drep) },
7178        (   { default_domain(Dom), \+ all_dead_(Ps) } -> []
7179        ;   [clpfd:(X in Drep)]
7180        ),
7181        attributes_goals(Ps).
7182
7183clpfd_aux:attribute_goals(_) --> [].
7184clpfd_aux:attr_unify_hook(_,_) :- false.
7185
7186clpfd_gcc_vs:attribute_goals(_) --> [].
7187clpfd_gcc_vs:attr_unify_hook(_,_) :- false.
7188
7189clpfd_gcc_num:attribute_goals(_) --> [].
7190clpfd_gcc_num:attr_unify_hook(_,_) :- false.
7191
7192clpfd_gcc_occurred:attribute_goals(_) --> [].
7193clpfd_gcc_occurred:attr_unify_hook(_,_) :- false.
7194
7195clpfd_relation:attribute_goals(_) --> [].
7196clpfd_relation:attr_unify_hook(_,_) :- false.
7197
7198attributes_goals([]) --> [].
7199attributes_goals([propagator(P, State)|As]) -->
7200        (   { ground(State) } -> []
7201        ;   { phrase(attribute_goal_(P), Gs) } ->
7202            { del_attr(State, clpfd_aux), State = processed,
7203              (   current_prolog_flag(clpfd_monotonic, true) ->
7204                  maplist(unwrap_with(bare_integer), Gs, Gs1)
7205              ;   maplist(unwrap_with(=), Gs, Gs1)
7206              ),
7207              maplist(with_clpfd, Gs1, Gs2) },
7208            list(Gs2)
7209        ;   [P] % possibly user-defined constraint
7210        ),
7211        attributes_goals(As).
7212
7213with_clpfd(G, clpfd:G).
7214
7215unwrap_with(_, V, V)           :- var(V), !.
7216unwrap_with(Goal, ?(V0), V)    :- !, call(Goal, V0, V).
7217unwrap_with(Goal, Term0, Term) :-
7218        Term0 =.. [F|Args0],
7219        maplist(unwrap_with(Goal), Args0, Args),
7220        Term =.. [F|Args].
7221
7222bare_integer(V0, V)    :- ( integer(V0) -> V = V0 ; V = #(V0) ).
7223
7224attribute_goal_(presidual(Goal))       --> [Goal].
7225attribute_goal_(pgeq(A,B))             --> [?(A) #>= ?(B)].
7226attribute_goal_(pplus(X,Y,Z))          --> [?(X) + ?(Y) #= ?(Z)].
7227attribute_goal_(pneq(A,B))             --> [?(A) #\= ?(B)].
7228attribute_goal_(ptimes(X,Y,Z))         --> [?(X) * ?(Y) #= ?(Z)].
7229attribute_goal_(absdiff_neq(X,Y,C))    --> [abs(?(X) - ?(Y)) #\= C].
7230attribute_goal_(absdiff_geq(X,Y,C))    --> [abs(?(X) - ?(Y)) #>= C].
7231attribute_goal_(x_neq_y_plus_z(X,Y,Z)) --> [?(X) #\= ?(Y) + ?(Z)].
7232attribute_goal_(x_leq_y_plus_c(X,Y,C)) --> [?(X) #=< ?(Y) + C].
7233attribute_goal_(ptzdiv(X,Y,Z))         --> [?(X) // ?(Y) #= ?(Z)].
7234attribute_goal_(pdiv(X,Y,Z))           --> [?(X) div ?(Y) #= ?(Z)].
7235attribute_goal_(prdiv(X,Y,Z))          --> [?(X) rdiv ?(Y) #= ?(Z)].
7236attribute_goal_(pexp(X,Y,Z))           --> [?(X) ^ ?(Y) #= ?(Z)].
7237attribute_goal_(pabs(X,Y))             --> [?(Y) #= abs(?(X))].
7238attribute_goal_(pmod(X,M,K))           --> [?(X) mod ?(M) #= ?(K)].
7239attribute_goal_(prem(X,Y,Z))           --> [?(X) rem ?(Y) #= ?(Z)].
7240attribute_goal_(pmax(X,Y,Z))           --> [?(Z) #= max(?(X),?(Y))].
7241attribute_goal_(pmin(X,Y,Z))           --> [?(Z) #= min(?(X),?(Y))].
7242attribute_goal_(scalar_product_neq(Cs,Vs,C)) -->
7243        [Left #\= Right],
7244        { scalar_product_left_right([-1|Cs], [C|Vs], Left, Right) }.
7245attribute_goal_(scalar_product_eq(Cs,Vs,C)) -->
7246        [Left #= Right],
7247        { scalar_product_left_right([-1|Cs], [C|Vs], Left, Right) }.
7248attribute_goal_(scalar_product_leq(Cs,Vs,C)) -->
7249        [Left #=< Right],
7250        { scalar_product_left_right([-1|Cs], [C|Vs], Left, Right) }.
7251attribute_goal_(pdifferent(_,_,_,O))    --> original_goal(O).
7252attribute_goal_(weak_distinct(_,_,_,O)) --> original_goal(O).
7253attribute_goal_(pdistinct(Vs))          --> [all_distinct(Vs)].
7254attribute_goal_(pexclude(_,_,_))  --> [].
7255attribute_goal_(pelement(N,Is,V)) --> [element(N, Is, V)].
7256attribute_goal_(pgcc(Vs, Pairs, _))   --> [global_cardinality(Vs, Pairs)].
7257attribute_goal_(pgcc_single(_,_))     --> [].
7258attribute_goal_(pgcc_check_single(_)) --> [].
7259attribute_goal_(pgcc_check(_))        --> [].
7260attribute_goal_(pcircuit(Vs))       --> [circuit(Vs)].
7261attribute_goal_(pserialized(_,_,_,_,O)) --> original_goal(O).
7262attribute_goal_(rel_tuple(R, Tuple)) -->
7263        { get_attr(R, clpfd_relation, Rel) },
7264        [tuples_in([Tuple], Rel)].
7265attribute_goal_(pzcompare(O,A,B)) --> [zcompare(O,A,B)].
7266% reified constraints
7267attribute_goal_(reified_in(V, D, B)) -->
7268        [V in Drep #<==> ?(B)],
7269        { domain_to_drep(D, Drep) }.
7270attribute_goal_(reified_tuple_in(Tuple, R, B)) -->
7271        { get_attr(R, clpfd_relation, Rel) },
7272        [tuples_in([Tuple], Rel) #<==> ?(B)].
7273attribute_goal_(kill_reified_tuples(_,_,_)) --> [].
7274attribute_goal_(tuples_not_in(_,_,_)) --> [].
7275attribute_goal_(reified_fd(V,B)) --> [finite_domain(V) #<==> ?(B)].
7276attribute_goal_(pskeleton(X,Y,D,_,Z,F)) -->
7277        { Prop =.. [F,X,Y,Z],
7278          phrase(attribute_goal_(Prop), Goals), list_goal(Goals, Goal) },
7279        [?(D) #= 1 #==> Goal, ?(Y) #\= 0 #==> ?(D) #= 1].
7280attribute_goal_(reified_neq(DX,X,DY,Y,_,B)) -->
7281        conjunction(DX, DY, ?(X) #\= ?(Y), B).
7282attribute_goal_(reified_eq(DX,X,DY,Y,_,B))  -->
7283        conjunction(DX, DY, ?(X) #= ?(Y), B).
7284attribute_goal_(reified_geq(DX,X,DY,Y,_,B)) -->
7285        conjunction(DX, DY, ?(X) #>= ?(Y), B).
7286attribute_goal_(reified_and(X,_,Y,_,B))    --> [?(X) #/\ ?(Y) #<==> ?(B)].
7287attribute_goal_(reified_or(X, _, Y, _, B)) --> [?(X) #\/ ?(Y) #<==> ?(B)].
7288attribute_goal_(reified_not(X, Y))         --> [#\ ?(X) #<==> ?(Y)].
7289attribute_goal_(pimpl(X, Y, _))            --> [?(X) #==> ?(Y)].
7290attribute_goal_(pfunction(Op, A, B, R)) -->
7291        { Expr =.. [Op,?(A),?(B)] },
7292        [?(R) #= Expr].
7293attribute_goal_(pfunction(Op, A, R)) -->
7294        { Expr =.. [Op,?(A)] },
7295        [?(R) #= Expr].
7296
7297conjunction(A, B, G, D) -->
7298        (   { A == 1, B == 1 } -> [G #<==> ?(D)]
7299        ;   { A == 1 } -> [(?(B) #/\ G) #<==> ?(D)]
7300        ;   { B == 1 } -> [(?(A) #/\ G) #<==> ?(D)]
7301        ;   [(?(A) #/\ ?(B) #/\ G) #<==> ?(D)]
7302        ).
7303
7304original_goal(original_goal(State, Goal)) -->
7305        (   { var(State) } ->
7306            { State = processed },
7307            [Goal]
7308        ;   []
7309        ).
7310
7311/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7312   Projection of scalar product.
7313- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7314
7315scalar_product_left_right(Cs, Vs, Left, Right) :-
7316        pairs_keys_values(Pairs0, Cs, Vs),
7317        partition(ground, Pairs0, Grounds, Pairs),
7318        maplist(pair_product, Grounds, Prods),
7319        sum_list(Prods, Const),
7320        NConst is -Const,
7321        partition(compare_coeff0, Pairs, Negatives, _, Positives),
7322        maplist(negate_coeff, Negatives, Rights),
7323        scalar_plusterm(Rights, Right0),
7324        scalar_plusterm(Positives, Left0),
7325        (   Const =:= 0 -> Left = Left0, Right = Right0
7326        ;   Right0 == 0 -> Left = Left0, Right = NConst
7327        ;   Left0 == 0 ->  Left = Const, Right = Right0
7328        ;   (   Const < 0 ->
7329                Left = Left0,       Right = Right0+NConst
7330            ;   Left = Left0+Const, Right = Right0
7331            )
7332        ).
7333
7334negate_coeff(A0-B, A-B) :- A is -A0.
7335
7336pair_product(A-B, Prod) :- Prod is A*B.
7337
7338compare_coeff0(Coeff-_, Compare) :- compare(Compare, Coeff, 0).
7339
7340scalar_plusterm([], 0).
7341scalar_plusterm([CV|CVs], T) :-
7342        coeff_var_term(CV, T0),
7343        foldl(plusterm_, CVs, T0, T).
7344
7345plusterm_(CV, T0, T0+T) :- coeff_var_term(CV, T).
7346
7347coeff_var_term(C-V, T) :- ( C =:= 1 -> T = ?(V) ; T = C * ?(V) ).
7348
7349/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7350   Generated predicates
7351- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7352
7353:- discontiguous term_expansion/2.
7354
7355term_expansion(make_parse_clpfd, Clauses)   :- make_parse_clpfd(Clauses).
7356term_expansion(make_parse_reified, Clauses) :- make_parse_reified(Clauses).
7357term_expansion(make_matches, Clauses)       :- make_matches(Clauses).
7358
7359make_parse_clpfd.
7360make_parse_reified.
7361make_matches.
7362
7363/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7364   Global variables
7365- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7366
7367make_clpfd_var('$clpfd_queue') :-
7368        make_queue.
7369make_clpfd_var('$clpfd_current_propagator') :-
7370        nb_setval('$clpfd_current_propagator', []).
7371make_clpfd_var('$clpfd_queue_status') :-
7372        nb_setval('$clpfd_queue_status', enabled).
7373
7374:- multifile user:exception/3.
7375
7376user:exception(undefined_global_variable, Name, retry) :-
7377        make_clpfd_var(Name), !.
7378
7379warn_if_bounded_arithmetic :-
7380        (   current_prolog_flag(bounded, true) ->
7381            print_message(warning, clpfd(bounded))
7382        ;   true
7383        ).
7384
7385:- initialization(warn_if_bounded_arithmetic).
7386
7387
7388/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7389   Messages
7390- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7391
7392:- multifile prolog:message//1.
7393
7394prolog:message(clpfd(bounded)) -->
7395        ['Using CLP(FD) with bounded arithmetic may yield wrong results.'-[]].
7396
7397
7398		 /*******************************
7399		 *	      SANDBOX		*
7400		 *******************************/
7401
7402/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7403The clpfd library cannot  be   analysed  completely by library(sandbox).
7404However, the API does not provide any  meta predicates. It provides some
7405unification hooks, but put_attr/3 does not  allow injecting in arbitrary
7406attributes.
7407- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
7408
7409:- multifile
7410	sandbox:safe_primitive/1.
7411
7412safe_api(Name/Arity, sandbox:safe_primitive(clpfd:Head)) :-
7413	functor(Head, Name, Arity).
7414
7415term_expansion(safe_api, Clauses) :-
7416	module_property(clpfd, exports(API)),
7417	maplist(safe_api, API, Clauses).
7418
7419safe_api.
7420% Support clpfd goal expansion.
7421sandbox:safe_primitive(clpfd:clpfd_equal(_,_)).
7422sandbox:safe_primitive(clpfd:clpfd_geq(_,_)).
7423sandbox:safe_primitive(clpfd:clpfd_in(_,_)).
7424% Enabling monotonic CLP(FD) is safe.
7425sandbox:safe_primitive(set_prolog_flag(clpfd_monotonic, _)).
7426