Prolog差异常规

时间:2009-12-09 17:44:08

标签: prolog logic

我需要一些我正在尝试创建的例程的帮助。我需要制作一个看起来像这样的例程:

difference([(a,b),(a,c),(b,c),(d,e)],[(a,_)],X).

X = [(b,c),(d,e)].

我真的需要帮助...

到目前为止,我已经编写了一个方法,可以删除它找到的第一个匹配项。但是我需要它来删除所有出现的事件。这是我到目前为止所拥有的......

memberOf(A, [A|_]).
memberOf(A, [_|B]) :-
    memberOf(A, B).

mapdiff([], _, []) :- !.
mapdiff([A|C], B, D) :-
        memberOf(A, B), !,
        mapdiff(C, B, D).
mapdiff([A|B], C, [A|D]) :-
        mapdiff(B, C, D).

我已从列表(减去)中获取此代码。

我不完全明白它的作用,但我知道这几乎是我想要的。我没有使用减法因为我的最终代码必须与WIN-Prolog兼容......我正在SWI Prolog上测试它。

3 个答案:

答案 0 :(得分:4)

整蛊一个! 简陋的咖啡有正确的想法。这是一个使用双重否定的奇特解决方案:

difference([], _, []).
difference([E|Es], DL, Res) :-
    \+ \+ member(E, DL), !,
    difference(Es, DL, Res).
difference([E|Es], DL, [E|Res]) :-
    difference(Es, DL, Res).

适用于SWI-PROLOG。说明:

第1条:基本案例。什么都不反对!

第2条:如果E在差异列表DL中,member/2子目标评估为true,但我们不希望接受member/2在存在的变量之间的绑定例如,在任一列表中,就像我们所希望的那样,术语(a,_)中的变量可以在其他术语中重用,而不是绑定到第一个解决方案。因此,第一个\+会删除成功评估member/2所创建的变量绑定,第二个\+会根据需要将评估状态反转为true。检查后发生切割,排除第3个子句,并丢弃统一的元素。

第3条:在两个清单中保留任何不可统一的要素。

答案 1 :(得分:3)

我不确定,但这样的事情可行。您可以使用findall查找无法与模式统一的所有元素:

?- findall(X, (member(X, [(a,b),(b,c),(a,c)]), X \= (a,_)), Res).

获得回复

Res = [ (b, c) ]

所以

removeAll(Pattern, List, Result) :-
  findall(ZZ109, (member(ZZ109, List), ZZ109 \= Pattern), Result).

应该有效,假设ZZ109不是Pattern中的变量(遗憾的是,我不知道为此获取新变量的方法。可能有一个不可移植的变量WIN-序言)。然后可以递归地定义difference

difference(List, [], List).
difference(List, [Pattern|Patterns], Result) :- 
  removeAll(Pattern, List, Result1),
  difference(Result1, Patterns, Result).

答案 2 :(得分:2)

您可以轻松修改代码,使其成为memberOF谓词只是检查列表中是否有可以统一的元素而不实际统一它的代码。在SWI Prolog中,可以这样做:

memberOf(A, [B|_]) :- unifiable(A,B,_).

但我不熟悉WIN-PRolog所以不知道它是否有一个谓词或运算符只测试参数是否可以统一。