我是prolog的初学者。我在swipl解释器中试过这个:
?- length(Lists, 3), ord_subset(Lists, [1, 2, 3, 4]).
false.
期望得到[1,2,3,4]子集的所有长度为3的列表,如[1,2,3]或[1,2,4]。为什么我会弄错?
注意:长度和ord_subset都是SWI-Prolog中的内置函数(或者它们被调用的任何函数)。
答案 0 :(得分:1)
您没有得到解决方案,因为ord_subset/2
谓词只有检查,如果列表是另一个列表的子集;它不会生成子集。
这是一种简单的方法来定义一个谓词,它可以完成你的目标:
subset_set([], _). subset_set([X|Xs], S) :- append(_, [X|S1], S), subset_set(Xs, S1).
这假定这些是“ordsets”,即没有重复的排序列表。
您会注意到该子集恰好也是一个子序列。我们本来可以写:
subset_set(Sub, Set) :- % precondition( ground(Set) ), % precondition( is_list(Set) ), % precondition( sort(Set, Set) ), subseq_list(Sub, Set). subseq_list([], []). subseq_list([H|T], L) :- append(_, [H|L1], L), subseq_list(T, L1).
无论使用哪种定义,您都会得到:
?- length(Sub, 3), subset_set(Sub, [1,2,3,4]). Sub = [1, 2, 3] ; Sub = [1, 2, 4] ; Sub = [1, 3, 4] ; Sub = [2, 3, 4] ; false.
您甚至可以在示例查询中切换两个子目标的顺序,但这可能是编写它的更好方法。
然而,第二个参数必须基础;如果不是:
?- subset_set([A,B], [a,B]), B = a. A = B, B = a ; Not a real set, is it? false.