【问题标题】:Prolog: Optimizing a puzzle solverProlog:优化解谜程序
【发布时间】:2013-11-24 21:09:48
【问题描述】:

我目前正在解决一个特定的 kenken 问题,我注意到大约需要 5 秒才能解决。这是一个较小的谜题。但是,我还需要解决一个更大的问题,我担心找到解决方案需要很长时间。这是我的代码中最相关的部分(我已经删除了多余的部分,它们是预期的形式):

getlarger(First, Second, First) :- First >= Second.
getlarger(First, Second, Second) :- First < Second.

getsmaller(First, Second, Second) :- First >= Second.
getsmaller(First, Second, First) :- First < Second.

subtractsmallerfromlarger(First, Second, Result) :- getlarger(First, Second, Larger), 
    getsmaller(First, Second, Smaller), Result is Larger - Smaller.

intdividelargerbysmaller(First, Second, Result) :- getlarger(First, Second, Larger),
getsmaller(First, Second, Smaller), Result is Larger // Smaller.

groupof4(List) :- nodups(List).

allrowsof4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]) :-
    groupof4([X1, X5, X9, X13]), groupof4([X2, X6, X10, X14]), %snip....

allcolumnsof4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]) :-
    groupof4([X1, X2, X3, X4]), groupof4([X5, X6, X7, X8]), %snip....

validnumbers4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]) :-
    validnumber4(X1), validnumber4(X2), %.....

kenken([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]) :-
    %snip...
    validnumbers4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]),
    X5 * X1 * X2 =:= 2,
    %Additional Arithmetic contraints removed
    intdividelargerbysmaller(X11, X15, 2), %Dividend =:= 2,
    subtractsmallerfromlarger(X12, X16, 3), %Difference =:= 3,
    X13 * X14 =:= 6,
    allcolumnsof4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]),
    allrowsof4([X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16]).

对于已经定义的值,我使用语法:X1 is 5,我把它放在我的代码顶部,认为这样可以加快查找速度。

在不必让我的代码变得非常复杂的情况下,有什么地方可以让它更高效一些吗?

此外,我注意到将 intdividelargerbysmaller 和 subsmallerfromlarger “Result is”更改为“Result =”会使查询花费很长时间/无法解决,而如果我在第三个插槽中使用变量,它会同时解决这两个问题。

此外,我注意到如果我将行和列检查移动到接近开头的位置,查询会花费很长时间。

【问题讨论】:

    标签: optimization prolog clpfd


    【解决方案1】:

    您似乎正在使用 generate-then-test 方法,该方法首先生成候选者,然后检查它们是否是有效的解决方案。

    在此任务中使用约束 效率更高。考虑使用由library(clpfd) 在 SWI-Prolog 中提供的有限域约束

    约束允许您在搜索具体解决方案之前以声明方式声明所有要求。它们可以在搜索之前和期间过滤不一致的元素,这通常会产生巨大的性能提升。

    【讨论】:

    • 谢谢,我在让库工作时遇到了一些麻烦,但我想出了如何安装它。你愿意给我一些关于如何使用约束的指示吗?
    • 只需使用有限域约束(如#=/2#&gt;=/2 等)作为相应低级算术谓词(is/2&gt;/2 等)的替代。约束所有变量的域,然后使用labeling/2label/1搜索具体解。
    • 要从较大值中减去较小值,您可以使用有限域约束S #= max(X,Y) - min(X,Y)。此外,label/1 易于使用:label(Vars),其中Vars 是您要标记的有限域变量。
    • 我似乎不需要标签,但它现在工作得很好。真的很快。谢谢!
    • @ChrisChambers:阅读the manual with small examples,然后阅读search for uses
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多