【问题标题】:Convert Boolean FlatZinc to CNF DIMACS将 Boolean FlatZinc 转换为 CNF DIMACS
【发布时间】:2014-04-18 23:45:25
【问题描述】:

为了解决set of Boolean equations,我正在使用以下输入尝试Constraint-Programming Solver MiniZinc

%  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 确实为小参数 (rows=cols=2, products=7) 找到了解决方案,但并没有随着略微增加的参数而结束。 我想将生成的FlatZinc 模型输入到SAT solver 中,例如CryptominisatLingelingClasp。我希望这些工具的性能可能优于现有的 MiniZinc 后端。

我的问题:
是否有任何工具可用于将纯布尔 FlatZinc 模型转换为 CNF (DIMACS)
我可以做些什么来替换 xorall() 谓词,因为一些 MiniZinc 后端似乎不支持它?

【问题讨论】:

    标签: constraint-programming satisfiability minizinc


    【解决方案1】:

    我不知道有任何工具可以将 FlatZinc 文件转换为 CNF (DIMACS) 文件。 (MiniZinc 发行版有一个将 flatzinc 转换为 XCSP 格式的程序。也许有一个将 XCSP 转换为 CNF 的工具?)

    但是,有一些基于 SAT 的/受启发的求解器可能会更好,例如minicsp,fzn2smt。问题是它们——正如你提到的——不支持全新的 xorall() 函数。

    另外,使用带标签的搜索可能是个好主意,即类似这样的东西(注意 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;
    

    另外,我建议您进行测试以转换为基于 0..1 的模型,这样可以测试这些求解器以及其他求解器。

    这是我的转换模型,我刚刚将 var bool 更改为 var 0..1 并将 xorall() 替换为 sum() 和 bool2int() [我希望我转换正确。] 更新:我已经改变到 Axel 建议的版本。

     %  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];
    

    这是型号:http://www.hakank.org/minizinc/akemper1_2.mzn

    [更新:这些时间是针对较早的错误模型。] 模型中的问题实例在 3 秒内由 minicsp(包括展平)解决(第一个解决方案),由 Opturion CPX 求解器在 5 秒内解决,由 fzn2smt 在6秒。并且模型可能可以通过标签等进一步调整。

    提到的求解器的链接:

    另请参阅我的 MiniZinc 页面以获取更长的 FlatZinc 求解器列表:http://www.hakank.org/minizinc/

    【讨论】:

    • 非常感谢这些真正深刻的提示。恐怕您的解决时间短是由于建模错误造成的。 ((rowA == rowC) /\ (colB == colC) /\ (colA == rowB)) 应该翻译成bool2int((rowA == rowC)/\(colB == colC)/\(colA == rowB))
    • 感谢您的更正,阿克塞尔。它在答案中改变了。我会看看是否有更快的 FlatZinc 求解器。
    • 测试了新版本,MiniCSP还是挺快的:3s。
    • 有一种方法可以将 FlatZinc 转换为 CNF,方法是使用 Picat 的 FlatZinc 求解器的修改版本(求解器可在此处获得 picat-lang.org/projects.html)。它包括一个可以转储到 CNF 文件的 SAT 求解器。 sat_connector.pi 的修改版本在这里:hakank.org/picat/flatzinc_sat_connect_dump.pi.
    • 可悲的是,MiniCSP 中似乎存在一个错误(至少在我移植到 Windows 的版本中......)。如果我尝试使用 (aRows=1;aCols=2;bCols=1;noOfProducts=2) 的最小示例,则结果不满足约束条件。使用 FlatZinc 或 Gecode,我得到了简化示例的正确结果。顺便说一句:sum 表达式不等于 xor/parity,因为任何奇数和都可以,而不仅仅是 sum=1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多