<!--
  - Authors:
  -   Christian Schulte <schulte@ps.uni-sb.de>
  -   Gert Smolka <smolka@dfki.de>
  -   Jörg Würtz
  -
  - Contributors:
  -   Daniel Simon <dansim@ps.uni-sb.de>
  -   Andy Walter <anwalt@ps.uni-sb.de>
  -   
  - Copyright:
  -   Christian Schulte, 1998
  -   Gert Smolka, 1998
  -   Jörg Würtz, 1997
  -
  - Last change:
  -   $Date: 1999-06-09 16:47:47 +0200 (Wed, 09 Jun 1999) $ by $Author: schulte $
  -   $Revision: 11476 $
  -
  - This file is part of Mozart, an implementation
  - of Oz 3
  -    http://www.mozart-oz.org
  -
  - See the file "LICENSE" or
  -    http://www.mozart-oz.org/LICENSE.html
  - for information on usage and redistribution
  - of this file, and for a DISCLAIMER OF ALL
  - WARRANTIES.
  -
  -->

<chapter id="chapter.propagators">
<title/Propagators for Redundant Constraints/
<p>

For some problems, the performance of a script
can be drastically improved by introducing
propagators for redundant constraints.  <def/Redundant constraints/
 are constraints that are
entailed by the constraints specifying the
problem.  Additional propagators for redundant
constraints may decrease the size of the search
tree by strengthening the propagation component
of the script.  They may also reduce the number
of propagation steps needed to reach stability.


<section id="section.propagators.fractions"><title/Example: Fractions/

<subsection class=unnumbered>
  <title/Problem Specification/

<p>
The Fractions Puzzle consists in finding distinct
nonzero digits such that the following equation
holds:
<math display/
{A\over{BC}} + 
{D\over{EF}} + 
{G\over{HI}}
=
1
/

<subsection class=unnumbered>
<title/Model/

<p>
We have a variable for every letter, similar as
in the Send More Money Puzzle.  Since the three
fractions are symmetric, we can impose the order
<math display/
{A\over{BC}} \ge
{D\over{EF}} \ge
{G\over{HI}}
/
From the order constraints we obtain the redundant
constraints
<math display/
3{A\over{BC}}\ge1
\qquad
\hbox{and}
\qquad
3{G\over{HI}}\le1
/
The order constraints together with the redundant
constraints reduce the size of the search tree by
one order of magnitude.

<subsection class=unnumbered>
<title/Distribution Strategy/

<p>
We distribute on the list of letters using the
standard first-fail strategy.

<figure id="ProgFractions">
<caption/A script for the Fractions Puzzle./
<chunk class=anonymous><title/Fractions/
proc {Fractions Root}
   sol(a:A b:B c:C d:D e:E f:F g:G h:H i:I) = Root
   BC = {FD.decl}
   EF = {FD.decl}
   HI = {FD.decl}
in
   Root ::: 1#9
   {FD.distinct Root}
   BC =: 10*B + C
   EF =: 10*E + F
   HI =: 10*H + I 
   A*EF*HI + D*BC*HI + G*BC*EF =: BC*EF*HI
   %% impose canonical order
   A*EF >=: D*BC    
   D*HI >=: G*EF
   %% redundant constraints
   3*A >=: BC
   3*G =<: HI
   {FD.distribute ff Root}
end
</chunk>
</figure>

<subsection class=unnumbered>
<title/Script/

<p>
The script in <Ptr to="ProgFractions"> constrains
its root variable to a record having a field for
every letter.  Since Oz has no finite domain
propagators for fractions, we eliminate the fractions
by multiplying with the denominators.  For every
denominator we introduce an auxiliary variable.
Since a finite domain propagator starts its work only
after all variables of the constraint implemented by
the propagator are constrained to finite domains in
the constraint store, the script constrains the
auxiliary variables for the denominators to the
maximal finite domain using the procedure <<FD.decl>>.
</section>


<section id="section.propagators.pythagoras">
  <title/Example: Pythagoras/

<p>
Not all propagators exploit coreferences in
products (&eg; <math/x\cdot x + y\cdot y = z\cdot
z/).  For the example of this section it will be
essential to exploit such coreferences, and you
will learn how to do it.

<p>
The example also illustrates the case where a
propagator for a redundant constraint improves
the performance of a script by decreasing the
number of necessary propagation steps, but
without significantly changing the search tree.

<subsection class=unnumbered>
<title/Problem Specification/

<p>
How many triples <math/(A,B,C)/ exist such that\
<math/A^2+B^2=C^2/ and <math/A\le B\le C\le 1000/?

<subsection class=unnumbered>
<title/Model/

<p>
The model has three variables <math/A/, <math/B/, and <math/C/.
Each variable is constrained to the finite
domain <math/1\#1000/.  The model imposes the
constraints <math/A^2+B^2=C^2/ and <math/A\le B\le C/.

<p>
The script will also create a propagator for the
redundant constraint <math/2\cdot B^2\ge C^2/.

<subsection class=unnumbered>
<title/Distribution Strategy/

<p>
We distribute on the variables <math/A/, <math/B/, <math/C/
using the standard first-fail strategy.
<p>

<figure id="ProgPythagoras" class="Figure">
<caption/A script that enumerates Pythagoras triples./
<p>
<chunk class=anonymous><title/Definition of Square/
proc {Square X S}
   {FD.times X X S}
end
</chunk>
<chunk class=anonymous><title/Pythagoras/
proc {Pythagoras Root}
   [A B C] = Root
   AA BB CC
in
   Root ::: 1#1000
   AA = {Square A}
   BB = {Square B}
   CC = {Square C}
   AA + BB =: CC
   A =<: B
   B =<: C
   2*BB >=: CC  % redundant constraint
   {FD.distribute ff Root}
end
</chunk>
</p>
</figure>

<subsection class=unnumbered>
<title/Script/

<p>
Given the script in <Ptr to="ProgPythagoras">,
we can compute the number of different triples
with the statement
<chunk class=anonymous><title/{SearchAll Pythagoras}/
{Browse {Length {SearchAll Pythagoras}}}
</chunk>

The script introduces a defined constraint
<<<
{Square X S}
>>>
saying that <<S>> is the square of <<X>>.  This
constraint is implemented with a propagator
provided by
<<<
{FD.times X X S}
>>>
This propagator will start propagating as soon as
the store constrains <<X>> to a finite domain.
This in contrast to the propagator created by
<<X*X=:S>>, which will start work only after both
<<X>> and <<S>> are constrained to finite domains
in the constraint store.  To define <<Square>>
with this constraint, we would have to write
<<<
proc {Square X S}
   {FD.decl S}
   X*X =: S
end
>>>
<p>
The propagator for the redundant constraint does
not significantly reduce the size of the search
tree.  However, it reduces the number of
propagation steps from about 1000000 to
about 500000, which makes computation
twice as fast.
<para class=apropos><title/statistics/
To find out about this, pop
up the <ref.extern to="ozdoc:panel"/Oz Panel/ and
reset the statistics.  Also 
switch on the status message feature and pop up
the emulator buffer.  Now enter the statement
<<<
{Browse {Length {SearchAll Pythagoras}}}
>>>
and print the statistics after the execution of
the statement has finished.  This will show
something like
<<<
solutions: 881       Variables created:      3
clones:    1488      Propagators created:    7
failures:  608       Propagator invocations: 490299
>>>
in the emulator buffer.  Now remove the
propagator for the redundant constraint from the
definition of the script, redefine it, reset the
statistics, run the statement, and print the
statistics.  This time you will see something
like
<<<
solutions: 881       Variables created:      3
clones:    1878      Propagators created:    6
failures:  998       Propagator invocations: 1190397
>>>
<p>
If we drop the redundant constraint, it seems
sensible to not have separate propagators for
the squares but simply have one propagator
created with
<<<
A*A + B*B =: C*C
>>>
Unfortunately, this will dramatically increase
the size of the search tree.  The reason for
this increase is the fact that the created
propagator does not realize the coreferences in
the constraint it implements, that is, it treats
the two occurrences of <<A>>, say, as if they
were independent variables.
</section>

<section id="section.propagators.squares">
  <title/Example: Magic Squares/

<p>
This example shows a smart representation of a
matrix and a concomitant defined constraint of
higher order.  The model will eliminate
symmetries by imposing order constraints.
Propagation will be drastically improved by
exploiting a redundant constraint.

<subsection class=unnumbered>
<title/Problem Specification/

<p>
The Magic Square Puzzle consists in finding for
given <math/N/ an <math/N\times N/-matrix such that:
<list>
<item>
Every field of the matrix is an integer between
<math/1/ and <math/N^2/.
<item>
The fields of the matrix are pairwise distinct.
<item>
The sums of the rows, columns, and the two main
diagonals are all equal.
</list>
A magic square for <math/N=3/ looks as follows:
<math display/
\begin{array}{ccc}
2&7&6\\
9&5&1\\
4&3&8
\end{array}
/

p>
The Magic Square Puzzle is extremely hard for
large <math/N/.  Even for <math/{N=5}/, our script will
have to explore almost 8000 nodes to find a
solution.

<subsection class=unnumbered>
<title/Model/

<p>
We model the problem by having a variable
<math/F_{ij}/ for every field <math/(i,j)/ of the matrix.
Moreover, we have one additional variable <math/S/ and
require that the sum of every row, column, and
main diagonal equals <math/S/.
<p>
Without loss of generality, we can impose the
following order constraints eliminating
symmetries:
<math display/
F_{11}<F_{NN},
\qquad
F_{N1}<F_{1N},
\qquad
F_{11}<F_{N1}.
/
<p>
Since the sum of the sums of the rows must equal
the sum of all fields, we have the redundant
constraint
<math display/
{N^2\over 2}\cdot(N^2+1) = N\cdot S
/
To see this, note that sum of all fields equals
<math display/
1+2+\ldots+N^2 = {N^2\over 2}\cdot(N^2+1)
/<p>
and that the sum of each of the <math/N/ rows must be
<math/S/.

<subsection class=unnumbered>
<title/Distribution Strategy/

<p>
We distribute on the variables <math/F_{11},\ldots,
F_{NN}/ with a first-fail strategy splitting the
domain of the selected variable and trying the
lower half first.


<figure class="Figure" id="ProgMagicSquare">
<caption/A script for the Magic Square Puzzle./

<chunk class=anonymous><title/MagicSquare/
fun {MagicSquare N}
   NN  = N*N
   L1N = {List.number 1 N 1}  % [1 2 3 ... N]
in
   proc {$ Square}
      fun {Field I J}
	 Square.((I-1)*N + J)
      end
      proc {Assert F}
         % {F 1} + {F 2} + ... + {F N} =: Sum
	 {FD.sum {Map L1N F} '=:' Sum}
      end
      Sum = {FD.decl}
   in
      {FD.tuple square NN 1#NN Square}
      {FD.distinct Square}
      %% Diagonals
      {Assert fun {$ I} {Field I I} end}
      {Assert fun {$ I} {Field I N+1-I} end}
      %% Columns
      {For 1 N 1
       proc {$ I} {Assert fun {$ J} {Field I J} end} end}
      %% Rows
      {For 1 N 1
       proc {$ J} {Assert fun {$ I} {Field I J} end} end}
      %% Eliminate symmetries
      {Field 1 1} <: {Field N N}
      {Field N 1} <: {Field 1 N}
      {Field 1 1} <: {Field N 1}
      %% Redundant: sum of all fields = (number rows) * Sum
      NN*(NN+1) div 2 =: N*Sum
      %%
      {FD.distribute split Square}
   end
end
</chunk>

</figure>

<subsection class=unnumbered>
  <title/Script/

<p>
<Ptr to="ProgMagicSquare"> shows a script
realizing the model and distribution strategy just
discussed.  The actual script is created by a
procedure <<MagicSquare>> taking <<N>> as parameter.
<p>
The script represents the matrix as a tuple with
<math/N^2/ elements.  The tuple is the value of the
root variable <<Square>>.  The function
<<<
{Field I J}
>>>
returns the component of <<Square>> that represents
the field at position <<(I,J)>>.  The variable
<<Sum>> takes the sum of the rows, columns, and
main diagonals as value.  The procedure
<<<
{Assert ?{F}}
>>>
takes a function ?{F} and posts the constraint
<<<
{?{F} 1} + {?{F} 2} + ... + {?{F} N} = Sum
>>>
Obviously, <<{Assert F}>> is a defined constraint
of higher order.  With the help of this defined
constraint it is straightforward to state that
the sums of the rows, columns, and main diagonals
are all equal to <<Sum>>.

<p>
With the Explorer you can find out that for <<N=3>>
there is exactly one magic square satisfying the
ordering constraints of our model.  Without the
ordering constraints there are 8 different
solutions.  Omitting the propagator for the
redundant constraint will increase the search
tree by an order of magnitude.
<p>

<section id="section.propagators.exercises">
  <title/Exercises/
 
<exercise id=propagators.ex.a>
<p.silent//
<para class=apropos><title/Magic Sequence/
A magic sequence of length <math/n/ is a sequence
<math display/
x_0,\;x_1,\;\ldots\;,\;x_{n-1}
/
of integers such that for every <math/i=0,\ldots,n-1/
<list>
<item>
<math/x_i/ is an integer between <math/0/ and <math/n-1/.
<item>
the number <math/i/ occurs exactly <math/x_i/ times in the
sequence.
</list>

<p>
Write a parameterized script that, given <math/n/, can
enumerate all magic sequences of length <math/n/. 

<p> 
The script should use the procedure
<<<
{FD.exactly ?{K} ?{S} ?{I}}
>>>
that creates a propagator for the constraint
saying that exactly ?{K} fields of the record
?{S} are equal to the integer ?{I}.

<p>
You can drastically reduce the search space of
the script by having propagators for the
redundant constraints
<math display/
x_0\;+\;\ldots\;+\;x_{n-1}\;=\;n
/
and
<math display/
(-1)\cdot x_0\;+\;\ldots\;+\;(n-2)\cdot
x_{n-1}\;=\;0
/
Explain why these constraints are redundant.
</exercise>


<answer to="propagators.ex.a">
The first redundant constraint follows from the
fact that the total number of occurrences in the
sequence is <math/n/, and that no numbers but those
between <math/0/ and <math/n-1/ occur in the sequence.

<p>
The second redundant constraint follows from the
fact that
<math display/
0\cdot x_0\;+\;\ldots\;+\;
(n-1)\cdot x_{n-1}
\;=\;
x_0\;+\;\ldots\;+\;x_{n-1}
/

<P>
Here is a parametrized script for the Magic
Sequence Puzzle:
<chunk class=anonymous><title/MagicSequence/
fun {MagicSequence N}
   Cs = {List.number ~1 N-2 1}
in
   proc {$ S}
      {FD.tuple sequence N 0#N-1 S}
      {For 0 N-1 1 
       proc {$ I} {FD.exactly S.(I+1) S I} end}
      %% redundant constraints
      {FD.sum S '=:' N}
      {FD.sumC Cs S '=:' 0}
      %%
      {FD.distribute ff S}
   end
end
</chunk>
</answer>

</section>

<![ %EXTRA; [
<section><title/NONE/
<p>
<chunk><title/EXAMPLES/
%%%
%%% Chapter: Propagators for Redundant Constraints
%%%

%%
%% Example: Fractions
%%

declare
<chunk.ref/Fractions/

{ExploreAll Fractions}



%%
%% Example: Pythagoras
%%

declare
local
   <chunk.ref/Definition of Square/
in
   <chunk.ref/Pythagoras/
end

{ExploreOne Pythagoras}

<chunk.ref/{SearchAll Pythagoras}/



%%
%% Example: Magic Squares
%%

declare
<chunk.ref/MagicSquare/

{ExploreOne {MagicSquare 4}}



</chunk>
<chunk><title/ANSWERS/
%%%
%%% Chapter: Propagators for Redundant Constraints
%%%

%%
%% Magic Sequence
%%

declare
<chunk.ref/MagicSequence/

{ExploreAll {MagicSequence 14}}



</chunk>
]]>

</chapter>