Prolog(Sicstus) - 非成员和setof问题

时间:2017-01-08 04:56:13

标签: prolog prolog-setof

鉴于以下事实:

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)] ? ;
...

我认为我的会员资格逻辑不正确,但我无法弄清楚是什么问题。谁能看到我失败的地方?

我还阅读了关于按照建议here收集结果的第11章“学习Prolog”,但似乎我仍然无法正确使用^运算符。任何帮助将不胜感激!

更新:

根据用户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)的重复,但下一步将是删除单独规则中的那些。谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

我认为你应该将set / 2调用放在setof'目标,并更清楚地表达不相交,所以你可以单独测试它。关于type运算符,它在目标范围内请求变量通用量化。也许在bagof/3手册页上找到的简洁解释会有所帮助......

^

答案 1 :(得分: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结果中不需要的变量会自动隐藏在辅助谓词定义中。