Path prolog列出路径并避免某些路由

Path prolog列出路径并避免某些路由,path,prolog,Path,Prolog,我有一份数据清单 city(portsmouth,london). city(london,bristol). city(portsmouth,plymouth). city(plymouth,london). city(london,plymouth). city(london,birmingham). city(birmingham,bristol). 我使用的方法是 ?-op(150,xfy,pathto). ?-op(150,xfy,avoid). X pathto Y:- ci

我有一份数据清单

city(portsmouth,london).
city(london,bristol).
city(portsmouth,plymouth).
city(plymouth,london).
city(london,plymouth).
city(london,birmingham).
city(birmingham,bristol).
我使用的方法是

 ?-op(150,xfy,pathto).
 ?-op(150,xfy,avoid).
 X pathto Y:- city(X,Y).
不太确定是否可以像这样使用

X pathto Y avoid Z:-
    findall(Path,avoid_country(X,Y,Z,Path),Paths),write(Paths),nl.  

avoid_path(Start, End, Avoid,[]) :- 
    country(Start, End).

avoid_path(Start,End,Avoid,[Path|Result]):-
    city(Start,Path),
    Path\== Avoid,
    avoid_path(Path, End,Avoid, Result).
实际上,它在没有避免对象以及路径\==Avoid的情况下可以完美地工作

错误结果是

   | ?- portsmouth to bristol avoid birmingham.
   Error 1, Backtrack Stack Full, Trying city/2

应该是[[伦敦],[普利茅斯,伦敦]]

事实包括以下两个方面:

city(plymouth,london).
city(london,plymouth).

您的代码(其中包含一些不一致之处)不会检查是否已经访问过某个城市。这将使
findall/3
收集所有可能的路线[伦敦],[普利茅斯,伦敦],[普利茅斯,伦敦,普利茅斯,伦敦],这迟早会导致记忆枯竭。

好吧,那么:首先,你在你的事实中有一个循环:(伦敦,普利茅斯)和(普利茅斯,伦敦)。这意味着任何回溯的尝试都不会结束。
那么我不确定你是否可以这样使用2个操作符,但因为我不确定,其他人会对这件事有更深刻的见解:)
我参加了这个会议:朴茨茅斯到布里斯托尔-[伦敦,伯明翰]意味着从朴茨茅斯到布里斯托尔避开伦敦和伯明翰(我参加这个会议不是为了处理运营商问题),下面是一个工作代码,它跟踪访问过的城市,以避免无限的可能性:

city(portsmouth,london).
city(london,bristol).
city(portsmouth,plymouth).
city(plymouth,london).
city(london,plymouth).
city(london,birmingham).
city(birmingham,bristol).

:- op(150, xfy, to).

Start to End-Avoid :-
    findall(Waypoint, get_waypoints(Start, End, [Start], Avoid, Waypoint), Waypoints),
    !,
    write(Waypoints).
Start to End :-
    findall(Waypoint, get_waypoints(Start, End, [Start], [], Waypoint), Waypoints),
    write(Waypoints).

get_waypoints(Start, End, _Visited, _Avoid, []) :- 
    city(Start, End).
get_waypoints(Start, End, Visited, Avoid, [Waypoint|Result]) :-
    city(Start, Waypoint),
不要穿越城市来逃避

    \+ member(Waypoint, Avoid),
这项检查使我们不会陷入循环。这样,回溯就结束了

    \+ member(Waypoint, Visited),
    get_waypoints(Waypoint, End, [Waypoint|Visited], Avoid, Result).

谢谢,但是我可以知道从开始到结束是如何工作的吗?是吗?-从朴茨茅斯到布里斯托尔伯明翰还是其他司令部?对不起,我从来没有见过像这样的。基本上,这只是一个惯例,我把两个参数打包在一个里面,因为to运算符只有两个参数。但正如我所说,我对运算符定义不太了解,所以可能有一种方法可以让它与to一起工作,并避免使用3个参数。因此,回到关于结束避免的解释,如果你使用“x到y”,它将不会与“开始到结束避免”统一,因此将使用第二个子句,如果你使用“x到y-z”,它将与“开始到结束避免”统一使用Start=x End=y和Avoid=Z,因此将Z作为参数Avoid传递给get_waypoints谓词。语法是?-Start-to-End-[Avoid1,Avoid2,…]您是否指定了[birmingham],是使用我的代码还是仅使用birmingham?因为如果你不想避开城市列表(我代码中的情况),你可以将行\+成员(Waypoint,avoid)更改为\+Waypoint=avoid,它会起作用是的,实际上我的页面没有刷新,所以我在看到你的评论后发布了它。此外,我还使用谓词to某处,并具有类似的函数和prolog。无论如何谢谢你!