Convert Boolean FlatZinc to CNF DIMACS

2020-06-18 04:42发布

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?

1条回答
太酷不给撩
2楼-- · 2020-06-18 05:03

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:

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

查看更多
登录 后发表回答