在prolog中绑定无序列表

在prolog中绑定无序列表,prolog,swi-prolog,Prolog,Swi Prolog,我对prolog有点陌生,我正试图弄清楚如何在顺序无关紧要的情况下实现对列表元素的绑定。我在最后两行代码中演示了这一点。这样做似乎微不足道,但它无法约束 fh(Hand) :- is_card(R, _, C1), is_card(R, _, C2), is_card(R, _, C3), C1 \== C2, C2 \== C3, C1 \== C3, is_card(RR, _, D1), is_card(RR, _, D2), R \

我对prolog有点陌生,我正试图弄清楚如何在顺序无关紧要的情况下实现对列表元素的绑定。我在最后两行代码中演示了这一点。这样做似乎微不足道,但它无法约束

fh(Hand) :-
   is_card(R, _, C1),
   is_card(R, _, C2),
   is_card(R, _, C3),
   C1 \== C2,
   C2 \== C3,
   C1 \== C3,

   is_card(RR, _, D1),
   is_card(RR, _, D2),
   R \= RR,
   D1 \== D2,
   is_set(Hand),
   list_to_set([C1,C2,C3,D1,D2], Hand).

我希望得到一些提示。(隐藏谓词名称和功能以防止剽窃)

阅读库中提供的文档(列表),对于您的用例来说,最好将集合表示为排序列表,没有重复项,使用
sort/2

以下是我得到的:

?- A = [2,3,1],
   B = [1,1,2,3,2,3],
   sort(A, S),
   sort(B, S).
A = [2, 3, 1],
B = [1, 1, 2, 3, 2, 3],
S = [1, 2, 3].
sort(A,S)
将确保S是一个有序列表,其元素与A相同,
sort(B,S)
将确保如果从B创建一个集合,则它与A相同

我看到
is_set/1的实现可能与
长度(set,lengh)、排序(set,Sorted)、长度(Sorted,Len)相同。
但我找不到
“$skip_list”的定义。
。但我明白了:

?- '$skip_list'(Len, [2,3,1], Tail).
Len = 3,
Tail = [].

与其他评论者一样,我假设您使用的是SWI Prolog库中的
is_set/1
。在你的代码中你有一个调用

is_set(Hand)
其中
Hand
是一个自由变量。您的目标似乎是将其用作某种生成器或“类型声明”,但这不起作用:

?- is_set(X).
false.
报告部分内容如下:

是否已设置(@set)[det]

如果集合是正确的列表,且没有重复项,则为True

这里发生了一些事情。根据,
det
表示“在没有选择点的情况下仅成功一次,
@
表示“参数不会比调用时进一步实例化。”。把这两个问题放在一起,
is_set/1
不能作为生成器,因为它不枚举解决方案:它甚至不实例化单个解决方案(
@
),即使实例化,也不会多次成功(
det
)。(事实上,
det
谓词应该永远不会失败,但是
is_set/1
会失败;这似乎是一个文档错误,正确的注释应该是
semidet


因此:您不能将
is_set/1
用作生成器,只能用作类型检查。但是,即使作为一个类型检查,它在这里也没有帮助,因为自由变量肯定不是“一个合适的列表”。但是,在这里您不需要生成器或类型检查。删除
is_set/1
调用,
list_to_set/2
单独应该做你想做的事。

你可以用更严格的条件来构建你的手,通过对它们下订单来建立独特的元素,而不仅仅是检查它们是否不同:

fh(Hand) :-
   is_card(R, _, C1),
   is_card(R, _, C2),
   is_card(R, _, C3),
   C1 @< C2,
   C2 @< C3,

   is_card(RR, _, D1),
   is_card(RR, _, D2),
   dif(R, RR),
   D1 @< D2.
fh(手动):-
is_卡(R,u,C1),
is_卡(R,u,C2),
is_卡(R,u,C3),
C1@

这样,您就可以使用排序来构造您的牌手,这样您就不会有任何重复。由于您不关心顺序是什么,因此拥有特定的顺序不会干扰需求,并提供了一种建立唯一性的方法。

您是否使用“信息系统”集合和“列表”到“从库(列表)”集合?可能list_to_set需要某种顺序,它说“当set与list的元素顺序相同时为True”。我不知道如何运行代码,所以我不知道。这是真的,所以显然它只是一个集合,元素不重复。
是_set(X):-sort(X,X).
suffices@CapelliC如果X已经是一个排序集,我认为这就足够了,问题是[2,3,1]也应该是“set”。is_set/1没有错误条件,没有实例化它的参数,如果元素的顺序不符合标准,那么它确实成功了。修复了
det
semidet
的问题,我没有处理数字。有没有办法定义
@@lamino
@@lamino您需要澄清您原来的问题。你缺少了很多关于你的需求的细节。如果事实数据库中存在
is_card/3
,则结果中不应存在任何变量。所以举个例子会非常有帮助。展示事实的样子。或者如果
是\u card/3
是谓词,则显示谓词。对不起,您完全正确。为了得到所有的解,我不得不添加排列