## 7.2 Example: Pythagoras

Not all propagators exploit coreferences in products (e.g. ). For the example of this section it will be essential to exploit such coreferences, and you will learn how to do it.

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.

### Problem Specification

How many triples exist such that\ and ?

### Model

The model has three variables , , and . Each variable is constrained to the finite domain . The model imposes the constraints and .

The script will also create a propagator for the redundant constraint .

### Distribution Strategy

We distribute on the variables , , using the standard first-fail strategy.

  `proc {Square X S}
  {FD.times X X S}
  end`

  `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`

Figure 7.2: A script that enumerates Pythagoras triples.

### Script

Given the script in Figure 7.2, we can compute the number of different triples with the statement

  `{Browse {Length {SearchAll Pythagoras}}}`

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`

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.

statistics

To find out about this, pop up the 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`

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.