224 lines
7.9 KiB
ReStructuredText
224 lines
7.9 KiB
ReStructuredText
.. _sec-sat:
|
|
|
|
Boolean Satisfiability Modelling in MiniZinc
|
|
============================================
|
|
|
|
MiniZinc can be used to model Boolean satisfiability
|
|
problems where the variables are restricted to be Boolean (:mzn:`bool`).
|
|
MiniZinc can be used with efficient Boolean satisfiability
|
|
solvers to solve the resulting models efficiently.
|
|
|
|
Modelling Integers
|
|
------------------
|
|
|
|
Many times although we wish to use a Boolean satisfiability solver we may
|
|
need to model some integer parts of our problem.
|
|
|
|
There are three common ways of modelling an integer variables
|
|
:math:`I` in the range :math:`0 \dots m` where :math:`m = 2^{k}-1`
|
|
using Boolean
|
|
variables.
|
|
|
|
- Binary: :math:`I` is represented by :math:`k` binary variables
|
|
:math:`i_0, \ldots, i_{k-1}` where
|
|
:math:`I = 2^{k-1} i_{k-1} + 2^{k-2} i_{k-2} + \cdots + 2 i_1 + i_0`.
|
|
This can be represented in MiniZinc as
|
|
|
|
.. code-block:: minizinc
|
|
|
|
array[0..k-1] of var bool: i;
|
|
var 0..pow(2,k)-1: I = sum(j in 0..k-1)(bool2int(i[j])*pow(2,j));
|
|
|
|
- Unary: where :math:`I` is represented by :math:`m` binary variables
|
|
:math:`i_1, \ldots, i_m`
|
|
and :math:`i = \sum_{j=1}^m \mathtt{bool2int}(i_j)`. Since there is massive redundancy in
|
|
the unary representation we usually require that
|
|
:math:`i_j \rightarrow i_{j-1}, 1 < j \leq m`. This can be represented in MiniZinc as
|
|
|
|
.. code-block:: minizinc
|
|
|
|
array[1..m] of var bool: i;
|
|
constraint forall(j in 2..m)(i[j] -> i[j-1]);
|
|
var 0..m: I = sum(j in 1..m)(bool2int(i[j]);
|
|
|
|
- Value: where :math:`I` is represented by :math:`m+1` binary variables
|
|
:math:`i_0, \ldots, i_m` where
|
|
:math:`I = k \Leftrightarrow i_k`, and at most one of :math:`i_0, \ldots, i_m` is true.
|
|
This can be represented in MiniZinc as
|
|
|
|
.. code-block:: minizinc
|
|
|
|
array[0..m] of var bool: i;
|
|
constraint sum(j in 0..m)(bool2int(i[j]) == 1;
|
|
var 0..m: I;
|
|
constraint forall(j in 0..m)(I == j <-> i[j]);
|
|
|
|
There are advantages and disadvantages to each representation. It depends
|
|
on what operations on integers are to required in the model as to which is
|
|
preferable.
|
|
|
|
Modelling Disequality
|
|
---------------------
|
|
|
|
Let us consider modelling a latin squares problem. A latin square
|
|
is an :math:`n \times n` grid of numbers from :math:`1..n` such that
|
|
each number appears exactly once in every row and column.
|
|
An integer model for latin squares is shown in :numref:`ex-latin`.
|
|
|
|
.. literalinclude:: examples/latin.mzn
|
|
:language: minizinc
|
|
:name: ex-latin
|
|
:caption: Integer model for Latin Squares (:download:`latin.mzn <examples/latin.mzn>`).
|
|
|
|
The only constraint on the integers is in fact disequality, which is encoded
|
|
in the :mzn:`alldifferent` constraint.
|
|
The value representation is the best way of representing disequality.
|
|
A Boolean only model for latin squares is shown in
|
|
:numref:`ex-latinbool`.
|
|
Note each integer array element :mzn:`a[i,j]` is replaced by an array of
|
|
Booleans.
|
|
We use the :mzn:`exactlyone` predicate to encode that each value is used
|
|
exactly once in every row and every column, as well as to encode that exactly
|
|
one of the Booleans corresponding to integer array element :mzn:`a[i,j]` is true.
|
|
|
|
.. literalinclude:: examples/latinbool.mzn
|
|
:language: minizinc
|
|
:name: ex-latinbool
|
|
:caption: Boolean model for Latin Squares (:download:`latinbool.mzn <examples/latinbool.mzn>`).
|
|
|
|
Modelling Cardinality
|
|
---------------------
|
|
|
|
Let us consider modelling the Light Up puzzle. The puzzle consists of a
|
|
rectangular grid of squares which are blank, or filled. Every filled square
|
|
may contain a number from 1 to 4, or may have no number. The aim is to place
|
|
lights
|
|
in the blank squares so that
|
|
|
|
- Each blank square is "illuminated", that is can see a light through an
|
|
uninterrupted line of blank squares
|
|
- No two lights can see each other
|
|
- The number of lights adjacent to a numbered filled square
|
|
is exactly the number in the filled square.
|
|
|
|
An example of a Light Up puzzle is shown in :numref:`fig-lightup`
|
|
with its solution in :numref:`fig-lightup-sol`.
|
|
|
|
.. _fig-lightup:
|
|
|
|
.. figure:: figures/lightup.*
|
|
|
|
An example of a Light Up puzzle
|
|
|
|
.. _fig-lightup-sol:
|
|
|
|
.. figure:: figures/lightup2.*
|
|
|
|
The completed solution of the Light Up puzzle
|
|
|
|
It is natural to model this problem
|
|
using Boolean variables to determine which
|
|
squares contain a light and which do not, but there is some integer
|
|
arithmetic to consider for the filled squares.
|
|
|
|
.. literalinclude:: examples/lightup.mzn
|
|
:language: minizinc
|
|
:name: ex-lightup
|
|
:caption: SAT Model for the Light Up puzzle (:download:`lightup.mzn <examples/lightup.mzn>`).
|
|
|
|
A model for the problem is given in :numref:`ex-lightup`.
|
|
A data file for the problem shown in :numref:`fig-lightup`
|
|
is shown in :numref:`fig-lightupdzn`.
|
|
|
|
.. literalinclude:: examples/lightup.dzn
|
|
:language: minizinc
|
|
:name: fig-lightupdzn
|
|
:caption: Datafile for the Light Up puzzle instance shown in :numref:`fig-lightup`.
|
|
|
|
The model makes use of a Boolean sum predicate
|
|
|
|
.. code-block:: minizinc
|
|
|
|
predicate bool_sum_eq(array[int] of var bool:x, int:s);
|
|
|
|
which requires that the sum of an array of Boolean equals some fixed
|
|
integer. There are a number of ways of modelling such
|
|
*cardinality* constraints using Booleans.
|
|
|
|
- Adder networks: we can use a network of adders to
|
|
build a binary Boolean representation of the sum of the Booleans
|
|
- Sorting networks: we can use a sorting network to sort
|
|
the array of Booleans to create a unary representation of the sum
|
|
of the Booleans
|
|
- Binary decision diagrams: we can create a binary decision diagram
|
|
(BDD) that encodes the cardinality constraint.
|
|
|
|
|
|
.. literalinclude:: examples/bboolsum.mzn
|
|
:language: minizinc
|
|
:name: ex-bboolsum
|
|
:caption: Cardinality constraints by binary adder networks (:download:`bboolsum.mzn <examples/bboolsum.mzn>`).
|
|
|
|
.. literalinclude:: examples/binarysum.mzn
|
|
:language: minizinc
|
|
:name: ex-binarysum
|
|
:caption: Code for building binary addition networks (:download:`binarysum.mzn <examples/binarysum.mzn>`).
|
|
|
|
We can implement :mzn:`bool_sum_eq` using binary adder networks
|
|
using the code shown in :numref:`ex-bboolsum`.
|
|
The predicate :mzn:`binary_sum`
|
|
defined in :numref:`ex-binarysum`
|
|
creates a binary representation
|
|
of the sum of :mzn:`x` by splitting the list into two,
|
|
summing up each half to create a binary representation
|
|
and then summing these two binary numbers using :mzn:`binary_add`.
|
|
If the list :mzn:`x` is odd the last bit is saved to use as a carry in
|
|
to the binary addition.
|
|
|
|
.. \pjs{Add a picture of an adding network}
|
|
|
|
.. literalinclude:: examples/uboolsum.mzn
|
|
:language: minizinc
|
|
:name: ex-uboolsum
|
|
:caption: Cardinality constraints by sorting networks (:download:`uboolsum.mzn <examples/uboolsum.mzn>`).
|
|
|
|
.. literalinclude:: examples/oesort.mzn
|
|
:language: minizinc
|
|
:name: ex-oesort
|
|
:caption: Odd-even merge sorting networks (:download:`oesort.mzn <examples/oesort.mzn>`).
|
|
|
|
We can implement :mzn:`bool_sum_eq` using unary sorting networks
|
|
using the code shown in :numref:`ex-uboolsum`.
|
|
The cardinality constraint is defined by expanding the input
|
|
:mzn:`x` to have length a power of 2, and sorting the resulting bits
|
|
using an odd-even merge sorting network.
|
|
The odd-even merge sorter shown in :mzn:`ex-oesort` works
|
|
recursively by splitting
|
|
the input list in 2, sorting each list and merging the two
|
|
sorted lists.
|
|
|
|
.. \pjs{Add much more stuff on sorting networks}
|
|
|
|
|
|
|
|
.. \pjs{Add a picture of an adding network}
|
|
|
|
.. literalinclude:: examples/bddsum.mzn
|
|
:language: minizinc
|
|
:name: ex-bddsum
|
|
:caption: Cardinality constraints by binary decision diagrams (:download:`bddsum.mzn <examples/bddsum.mzn>`).
|
|
|
|
We can implement :mzn:`bool_sum_eq` using binary decision diagrams
|
|
using the code shown in :mzn:`ex:bddsum`.
|
|
The cardinality constraint is broken into two cases:
|
|
either the first element :mzn:`x[1]` is :mzn:`true`,
|
|
and the sum of the remaining bits
|
|
is :mzn:`s-1`, or :mzn:`x[1]` is :mzn:`false` and the sum of the remaining bits
|
|
is :mzn:`s`. For efficiency this relies on common subexpression elimination
|
|
to avoid creating many equivalent constraints.
|
|
|
|
|
|
.. \pjs{Add a picture of a bdd network network}
|
|
|
|
|