1

鉴于以下事实:

route(TubeLine, ListOfStations).

route(green, [a,b,c,d,e,f]).
route(blue, [g,b,c,h,i,j]).
...

我需要找到所有没有任何公共站点的地铁线路对,生成以下内容:

| ?- disjointed_lines(Ls).
Ls = [(yellow,blue),(yellow,green),(yellow,red),(yellow,silver)] ? ;
no

我想出了下面的答案,但是它不仅给了我不正确的答案,而且也没有应用我的 X^ 条件 - 即它仍然单独打印每个站列表成员的结果:

disjointed_lines(Ls) :- 
                        route(W, Stations1),
                        route(Z, Stations2),
                        setof(
                        (W,Z),X^
                        (member(X, Stations1),nonmember(X, Stations2)),
                         Ls).

这是定义产生的输出:

| ?- disjointed_lines(L).
L = [(green,green)] ? ;
L = [(green,blue)] ? ;
L = [(green,silver)] ? ;
...

我相信我与会员资格有关的逻辑是不正确的,但是我无法弄清楚哪里出了问题。谁能看到我在哪里失败?

我还按照此处的建议阅读了有关结果收集的 Learn Prolog Now 第 11 章,但是似乎我仍然无法正确使用 ^ 运算符。任何帮助,将不胜感激!


更新:

根据用户 CapelliC 的建议,我将代码更改为以下内容:

disjointed_lines(Ls) :- 
                        setof(
                        (W,Z),(Stations1, Stations2)^
                        ((route(W, Stations1),
                        route(Z, Stations2),notMembers(Stations1,Stations2))),
                         Ls).

notMembers([],_).
notMembers([H|T],L):- notMembers(T,L), nonmember(H,L).

然而,下面给出了 (X,Y) 和 (Y,X) 的重复项,但下一步将在单独的规则中删除它们。感谢您的帮助!

4

2 回答 2

2

我认为您应该将 route/2 调用放在 setof' 目标中,并更清楚地表达不相交性,以便您可以单独对其进行测试。关于^算子,它要求一个变量在目标范围内被普遍量化。也许像bagof/3手册页上的简明解释会有所帮助......

disjointed_lines(Ls) :- 
  setof((W,Z), Stations1^Stations2^(
    route(W, Stations1),
    route(Z, Stations2),
    disjoint(Stations1, Stations2)
  ), Ls).

disjoint(Stations1, Stations2) :-
  ... % could be easy as intersection(Stations1, Stations2, [])
      % or something more efficient: early fail at first shared 'station'
于 2017-01-08T08:52:19.517 回答
1

setof/3如果您创建一个表达您感兴趣的关系的辅助谓词,则更易于使用:

disjoint_routes(W, Z) :-
    route(W, Stations1),
    route(Z, Stations2),
    disjoint(Stations1, Stations2).

有了这个, 的定义disjointed_lines/1变得更短更简单,不再需要任何^操作符

disjointed_lines(Ls) :-
    setof((W, Z), disjoint_routes(W, Z), Ls).

结果中不需要的变量setof/3会自动隐藏在辅助谓词定义中。

于 2017-01-08T14:05:29.283 回答