我正在编写以下代码,并给出了完美的结果。
edge(s,a,300).
edge(s,d,20).
edge(a,d,400).
edge(a,b,1500).
edge(b,c,9).
edge(b,e,200).
edge(c,d,2000).
edge(c,g,12).
edge(d,e,3).
edge(e,f,400).
edge(f,g,800).
connected(X,Y,D) :- edge(X,Y,D) ; edge(Y,X,D).
path(A,B,D,Path) :-
travel(A,B,D,[A],Q),
reverse(Q,Path).
travel(A,B,D,P,[B|P]) :-
connected(A,B,D).
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
D2 is D - D1,
travel(X,B,D2,[X|Visited],Path).
如果我查询
,请点击此处| ?- path(s,e,23,P).
P = [s,d,e] ? ;
no
| ?-
我得到了正确的回复。 但是,不,我希望得到D< 50的结果。 怎么办?
答案 0 :(得分:4)
算术表达式在Prolog中是一种特殊情况,并且预计不会与未绑定的参数一起使用,所以你不能简单地要求path(s,e,D,P), D < 50
,因为is
- 子句需要它的所有权利实例化的边参数。
您可以将finite domain (FD) constraint extensions用于Prolog(例如在GNU Prolog中):只需将is
更改为FD等效#=
,然后询问:
/Users/stolz/test.pl compiled, 27 lines read - 3180 bytes written, 8 ms
| ?- fd_domain(D,0,50), path(s,e,D,P).
D = 23
P = [s,d,e] ? ;
no
答案 1 :(得分:2)
你应该让Prolog计算距离D以及路径:
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
travel(X,B,D2,[X|Visited],Path),
D is D2 + D1.
然后你可以查询它
?- path(Start, Stop, D, P), D < 50.
将获得(在回溯时)D&lt; 50。
?- path(s,e,X,P),X<50.
X = 23,
P = [s, d, e] ;
false.
答案 2 :(得分:1)
虽然我认为有限域约束是最好的在这里使用,但您可以通过对代码的微小修改来实现您想要的。
在travel/5
的第一个子句中,而不是将输入参数D
与connected/3
的第三个参数统一,您可以使用一个新变量,然后检查您当前的距离( D
)大于或等于这个新变量。
travel(A,B,D,P,[B|P]) :-
connected(A,B,TD),
D >= TD.