如何在Prolog中创建算术和不等式约束

Bre*_*ent 5 prolog clpfd

我是Prolog的新手,我有兴趣将以下单词问题转换为(SWI)Prolog:

有4个孩子:安倍,丹,玛丽和苏.他们的年龄没有特别的顺序,分别为3,5,6和8岁.Abe比Dan年长.苏比玛丽年轻.苏的年龄是丹的年龄加上3年.玛丽比安倍年长.

到目前为止,我已经想到了

child(X) :-
    member(X, [3,5,6,8]).

solution(Abe, Dan, Mary, Sue) :-
    child(Abe),
    child(Dan),
    child(Mary),
    child(Sue),
    Abe > Dan,
    Sue < Mary,
    Sue == Dan+3,
    Mary > Abe,
    Abe \== Dan,
    Abe \== Mary,
    Abe \== Sue,
    Dan \== Mary,
    Dan \== Sue,
    Mary \== Sue.
Run Code Online (Sandbox Code Playgroud)

但是运行查询

?- solution(Abe, Dan, Mary, Sue)
Run Code Online (Sandbox Code Playgroud)

我得到了false.作为一个附带问题,Prolog会执行暴力搜索解决方案,还是有一些机器能够比O(n!)更好地解决这个(某种)问题?

我想要的结果是Abe = 5, Dan = 3, Mary = 9, Sue = 6.

mat*_*mat 8

整数的算术约束,例如这个难题中的约束,最好用Prolog系统的CLP(FD)约束表示.

例如,在SICStus Prolog,YAP或SWI中:

:- use_module(library(clpfd)).

ages(As) :-
        As = [Abe,Dan,Mary,Sue],    % There are 4 children: Abe, Dan, Mary, Sue
        As ins 3\/5\/6\/8,          % Their ages are 3, 5, 6 and 8
        all_different(As),
        Abe #> Dan,                 % Abe is older than Dan
        Sue #< Mary,                % Sue is younger than Mary
        Sue #= Dan + 3,             % Sue's age is Dan's age plus 3 years
        Mary #> Abe.                % Mary is older than Abe

示例查询及其结果:

?- ages([Abe,Dan,Mary,Sue]).
Abe = 5,
Dan = 3,
Mary = 8,
Sue = 6.

我们从这个答案看到这个谜题有一个独特的解决方案.

请注意,无需任何搜索即可获得此答案!约束求解器通过称为约束传播的强大隐式机制推导出唯一解,这是CLP系统相对于强力搜索的关键优势.在此示例中成功使用约束传播来修剪搜索树中除了一个剩余分支之外的所有分支.

  • @Brent.好问题!提供一些问题实例,我们可以尝试一下.我认为clpfd通常会(大幅度地)赢得这样的问题. (3认同)
  • 在查找clpfd并随后发现http://www.swi-prolog.org/man/clpqr.html后,我有几个小问题也许你可以回答.1)CLP(Q,R)是CLP(FD)的超集 - CLP(Q,R)能否有效地解决这个问题,或者严格地用整数作为一个有用的约束?2)我发现CLP(FD)用于处理整数,但字母FD实际上代表什么? (2认同)
  • 将CLP(Q,R)用于此(更准确,相似但更大)的问题会引入性能损失吗? (2认同)
  • @Brent.`fd` ="有限域".是和否,`clpqr`**可以用于整数和非整数(有理数和浮点数),但是它主要适用于线性方程组和线性不等式,可用高斯消元和单纯形"线性规划"解决" 方法.MIP(混合整数线性编程)也被提供,但是所有整数组合问题的首选武器是`clpfd`,而不是`clpqr`. (2认同)
  • @Brent:我同意重复所说的一切.此外,我认为*你的每个问题值得自己提出.你会得到几个很好的答案. (2认同)