在Prolog中基于条件从列表中过滤元素

3

我有一份路由列表

path(chicago,milwaukee).
path(milwaukee,detroit).
path(chicago,detroit).
path(detroit, newyork).
path(newyork, boston).
path(atlanta,boston).

我有一个名为 routefrom 的谓词,它可以给出从起点到终点之间所有的城市。

例如:

?- routefrom(chicago,newyork,X).
X=[chicago,milwaukee,detroit,newyork]

获取所有的路由:
要获取所有的路由,可以使用以下命令:
allroutes(Start,End,P) :- findall(X,pathfrom(Start,End,X),P).

例子:

?- allroutes(chicago,neywork,P).
X=[[chicago,milwaukee,detroit,newyork],[chicago,detroit,newyork]].

我有一个谓词规则goodroute(M),如果路线不包含密尔沃基且包含芝加哥或纽约,则返回true。

例如:

?- goodroute([chicago, milwaukee,detroit]).
false

?-goodroute([chicago,detroit,newyork,boston]).
true

现在,我需要过滤出包含密尔沃基的路线,并从所有路线的结果中得到一个包含芝加哥或纽约的列表。我尝试过。

filerroute :- exclude(maplist(goodroute(findall(X,pathfrom(Start,End,X),P).

我的目标是将goodroute映射到findall的结果上,使其中一部分为true,一部分为false,并使用exclude来排除false。我不确定exclude的工作原理。如何过滤掉与goodroute谓词不符的元素,并获得仅匹配true条件的元素列表?

1个回答

3

excludeinclude(你真正想要的)将谓词名称作为它们的第一个参数:

goodroutes(From, To, Routes) :-
    allroutes(From, To, All),
    include(goodroute, All, Routes).

虽然在调用 findall 时过滤掉错误路线会更有效率,因为这样你就不需要先建立所有路线的集合:

goodroutes(From, To, Routes) :-
    findall(Route, (pathfrom(From, To, Route), goodroute(Route)), Routes).

请注意( , );我们将两个目标连接作为 findall 的第二个参数。

谢谢。使用findall的那个看起来比使用include的那个更有效率。在findall(Route, (pathfrom(From, To, Route), goodroute(Route)), Routes).中,我们可以使用尽可能多的目标来匹配对吧?如果我有更多的条件需要满足,我只需要这样做:findall(Route, (pathfrom(From, To, Route), goodroute(Route),another_condition), Routes).是吗? - Bharat
@RBK:没错,而且它也更具可移植性。如果您获得一个完全构建好的列表作为输入,则“include”很好,但是尽早过滤可以在最终节省大量时间。 - Fred Foo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接