如何生成一条规则来告诉这个简单的事实是双向的?

时间:2013-10-28 14:13:01

标签: prolog

所以我有几个事实:

%bridge(Name,From,To).
bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).

编辑:更改为原子

所以这就像“桥A从区域1到区域2的十字架”。这很简单。然而,反过来也是如此。桥A从第2区到第1区的交叉。这就是为什么我想:

bridge(B,S,E):- bridge(B,E,S).

事实上,这会扰乱我的程序,因为每当swi-prolog找不到桥的匹配时,它将继续使用桥规则一遍又一遍地反转它的参数。有没有办法阻止这个?或者有没有其他方法来创建一个简单的规则?如果我添加其他所有事实(桥(A,2,1),桥(C,3,2)等),我的程序将完美运行。

2 个答案:

答案 0 :(得分:3)

首先请注意,您似乎在使用变量来表示使用原子来识别桥梁。

关于你的问题:你可以通过添加额外的必要事实来轻松解决这个问题,例如:

bridge(a, 1, 2).
bridge(a, 2, 1).

bridge(b, 1, 2).
bridge(b, 2, 1).

etc.

然而,正如您已经直观地注意到的那样,这显然是多余的,您可以使用辅助谓词重构它,例如bridge_/2,其中包含两个子句:

bridge(B, X, Y) :- bridge_(B, X, Y).
brigde(B, X, Y) :- bridge_(B, Y, X).

bridge_(a, 1, 2).
bridge_(b, 2, 1).
bridge_(c, 2, 3).
etc.

答案 1 :(得分:1)

Prolog提供了一种处理每个子句读取的方法,断言之前,通过term_expansion / 2。应该这样工作:

term_expansion(bridge(K,A,B), bridge(K,A,B)) :- assertz(bridge(K,B,A)).

也就是说,它'返回'未更改的术语读取,并添加一个带有交换'连接'的术语。 请注意,使用图形跟踪器调试转换后的源代码可能很困难......

编辑我的回答有点肤浅,我正在尝试调试它......

编辑感谢Paulo提示,这里有点工作......

:- module(bridge, [bridge/3]).

term_expansion(bridge(K,A,B), [bridge(K,A,B),bridge(K,B,A)]).

bridge(a,1,2).
bridge(b,1,2).
bridge(c,2,3).
bridge(d,3,4).