Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Boolean FlatZinc to CNF DIMACS

To solve a set of Boolean equations, I am experimenting with the Constraint-Programming Solver MiniZinc using the following input:

%  Solve system of Brent's equations modulo 2

%  Matrix dimensions
int: aRows = 3;
int: aCols = 3;
int: bCols = 3;
int: noOfProducts = 23;

%  Dependent parameters
int: bRows = aCols;
int: cRows = aRows;
int: cCols = bCols;
set of int: products = 1..noOfProducts;

%  Corefficients are stored in arrays
array[1..aRows, 1..aCols, products] of var bool: A;
array[1..bRows, 1..bCols, products] of var bool: B;
array[1..cRows, 1..cCols, products] of var bool: C;

constraint
    forall(rowA in 1..aRows, colA in 1..aCols) (
        forall(rowB in 1..bRows, colB in 1..bCols) (
            forall (rowC in 1..cRows, colC in 1..cCols) (
                xorall (k in products) (
                    A[rowA, colA, k] /\ B[rowB, colB, k] /\ C[rowC, colC, k]
                ) == ((rowA == rowC) /\ (colB == colC) /\ (colA == rowB))
            )
        )
    );

solve satisfy;

%  Output solution as table of variable value assignments
output 
["\nSolution for <" ++ show(aRows) ++ ", " ++ show(aCols) ++ 
                 ", " ++ show(bCols) ++ "> " ++ show(noOfProducts) ++ " products:"] ++
["\nF" ++ show(100*rowA+10*colA+k) ++ " = " ++ 
show(bool2int(A[rowA, colA, k])) |
rowA in 1..aRows, colA in 1..aCols, k in products] ++

["\nG" ++ show(100*rowB+10*colB+k) ++ " = " ++ 
show(bool2int(B[rowB, colB, k])) |
rowB in 1..bRows, colB in 1..bCols, k in products] ++

["\nD" ++ show(100*rowC+10*colC+k) ++ " = " ++ 
show(bool2int(C[rowC, colC, k])) |
rowC in 1..cRows, colC in 1..cCols, k in products];

MiniZinc does find a solution for small parameters (rows=cols=2, products=7) , but does not come to an end with the slightly increased ones. I'd like to feed the generated FlatZinc model into a SAT solver like Cryptominisat, Lingeling or Clasp. My hope is these tools might outperform the existing MiniZinc back-ends.

My Question:
Is there any tool available to convert a purely Boolean FlatZinc model into CNF (DIMACS)?
What could I do to replace the xorall() predicate as some of the MiniZinc back-ends don't seem to support it?

like image 648
Axel Kemper Avatar asked Mar 13 '14 22:03

Axel Kemper


1 Answers

I don't know of any tools that converts a FlatZinc file to and CNF (DIMACS) file. (The MiniZinc distribution has a program to convert flatzinc to XCSP format. Perhaps there's a tool for XCSP to CNF?)

However, there are some SAT based/inspired solvers that might be better, e.g. minicsp, fzn2smt. There problem is that they - as you mention - don't support the quite new xorall() function.

Also, it might be a good idea to use a labeled search, i.e. something like this (note the bool_search)

  solve :: bool_search(
       [A[i,j,k] | i in 1..aRows, j in 1..aCols, k in products],
       first_fail,
       indomain_min,
       complete)
     satisfy;

Also, I suggest you to test to convert to a 0..1 based model instead, where these solvers can be tested as well as others.

Here's my converted model where I've just changed var bool to var 0..1 and replaced the xorall() with sum() and bool2int() [I hope I converted that correct.] Update: I've changed to the version Axel suggested.

 %  Solve system of Brent's equations modulo 2

 %  Matrix dimensions
 int: aRows = 3;
 int: aCols = 3;
 int: bCols = 3;
 int: noOfProducts = 23;

 %  Dependent parameters
 int: bRows = aCols;
 int: cRows = aRows;
 int: cCols = bCols;
 set of int: products = 1..noOfProducts;

 %  Corefficients are stored in arrays
 array[1..aRows, 1..aCols, products] of var 0..1: A; % hakank: change to 0..1
 array[1..bRows, 1..bCols, products] of var 0..1: B;
 array[1..cRows, 1..cCols, products] of var 0..1: C;

constraint
     forall(rowA in 1..aRows, colA in 1..aCols) (
         forall(rowB in 1..bRows, colB in 1..bCols) (
             forall (rowC in 1..cRows, colC in 1..cCols) (
                 % hakank: changed
                 sum (k in products) (
                     bool2int(A[rowA, colA, k]=1/\ B[rowB, colB, k]=1 /\ C[rowC, colC, k]=1)
                ) == 
                     %% bool2int(rowA == rowC)+ bool2int(colB == colC) + bool2int(colA == rowB)
                     bool2int((rowA == rowC)/\(colB == colC)/\(colA == rowB))
             )
         )
     );


     solve :: int_search(
         [A[i,j,k] | i in 1..aRows, j in 1..aCols, k in products] ++ 
         [B[i,j,k] | i in 1..aRows, j in 1..aCols, k in products] ++ 
         [C[i,j,k] | i in 1..aRows, j in 1..aCols, k in products] 
         ,
         first_fail,
         indomain_min,
         complete)
     satisfy;

    %  Output solution as table of variable value assignments
    output 
    ["\nSolution for <" ++ show(aRows) ++ ", " ++ show(aCols) ++ 
             ", " ++ show(bCols) ++ "> " ++ show(noOfProducts) ++ " products:"] ++
    ["\nF" ++ show(100*rowA+10*colA+k) ++ " = " ++ 
        show(A[rowA, colA, k]) |
        rowA in 1..aRows, colA in 1..aCols, k in products] ++

    ["\nG" ++ show(100*rowB+10*colB+k) ++ " = " ++ 
       show(B[rowB, colB, k]) |
       rowB in 1..bRows, colB in 1..bCols, k in products] ++

    ["\nD" ++ show(100*rowC+10*colC+k) ++ " = " ++ 
       show(C[rowC, colC, k]) |
       rowC in 1..cRows, colC in 1..cCols, k in products];

Here's the model: http://www.hakank.org/minizinc/akemper1_2.mzn .

[Update: These times are for the earlier, wrong, model.] The problem instance in the model is solved (first solution) by minicsp in 3s (including flattening), by the Opturion CPX solver in 5s, by fzn2smt in 6s. And the model can perhaps be tweaked further with labelings etc.

Links to the solvers mentioned:

  • Opturion CPX: http://www.opturion.com/cpx.html

  • MiniCSP: http://www.inra.fr/mia/T/katsirelos/minicsp.html

  • fzn2smt: http://ima.udg.edu/Recerca/ESLIP/fzn2smt/index.html

Also see my MiniZinc page for a longer list of FlatZinc solvers: http://www.hakank.org/minizinc/ .

like image 143
hakank Avatar answered Oct 19 '22 14:10

hakank