在循环图prolog中反转搜索

时间:2015-01-13 18:35:52

标签: prolog

我在prolog程序中遇到了这个问题,因为我是一个完全的初学者,我以为我会来这里寻求答案或帮助。

这是我的数据库:

road(hoor,horby).
road(horby,lund).
road(horby,sjobo).
road(lund,sjobo).
road(sjobo,tomelilla).
road(sjobo,ystad).
road(tomelilla,ystad).
road(ronne,gudhjem).

然后这些是我的规则:

:- op(150, xfy, to).

X to Y :-
    findall(Waypoint, get_waypoints(X,Y,Waypoint), Waypoints),
    write(Waypoints).

get_waypoints(Start, End, []) :- 
    road(Start, End).
get_waypoints(Start, End, [Waypoint|Result]) :-
    road(Start, Waypoint),
    get_waypoints(Waypoint, End, Result).

例如,当我问

时,它工作正常
?- horby to ystad.

然后输出变为:

[[lund,sjobo],[lund,sjobo,tomelilla],[sjobo],[sjobo,tomelilla]]
true.

哪个是完美的。但是,让我说我想找到从? - ystad到horby的路径。 当我要求这个时它只给了我:

[]
true.

我可以通过哪些方法来解决此问题? 提前谢谢!

1 个答案:

答案 0 :(得分:0)

沿两个方向使用道路

问题是你的道路只是单向的。你需要两种方式使用它们。

您可以通过添加新规则来实现:

connected(X, Y):- road(X, Y) ; road(Y, X).

现在,如果您只是将road(Start, Waypoint)替换为connected(Start, Waypoint),那么现在可以向所有方向搜索,但是您的谓词get_waypoints将产生无数个解决方案,因为它可能在两者之间来回传递城市。

检查某个城市是否已被访问

您需要检查之前访问过的城市是否已被访问过。你可以使用你目前访问过的城市的列表(累加器)来做到这一点:

get_waypoints(Start, End, Waypoints):-
    get_waypoints(Start, End, [Start], Waypoints).

get_waypoints(Current, End, Acc, Waypoints):-
    connected(Current, End),
    reverse(Acc, [_|Waypoints]).

get_waypoints(Current, End, Acc, Waypoints):-
    connected(Current, Waypoint),
    Waypoint \== End,
    \+ member(Waypoint, Acc),
    get_waypoints(Waypoint, End, [Waypoint|Acc], Waypoints).

子目标Waypoint \== End确保一旦您到达目的地,您就不会在该路径上进一步构建。 \+ member(Waypoint, Acc)确保您不会两次访问同一个城市。

因为你需要检查你是否没有返回起始城市,所以累加器也会包含它。最后,当累加器被反转时,第一个元素(起始城市)被丢弃:reverse(Acc, [_|Waypoints])

示例查询

| ?- ystad to horby.
[[sjobo],[sjobo,lund],[tomelilla,sjobo],[tomelilla,sjobo,lund]]

yes

更新:在结果列表中包含开始和结束节点(在评论中请求)

要在结果中包含起点城市和结束城市以及航点,只需在End的第一个规则中将get_waypoints/2节点添加到累加器:

get_waypoints(Current, End, Acc, Waypoints):-
    connected(Current, End),
    reverse([End|Acc], Waypoints]).