Prolog:如何获得所有组合

时间:2014-12-12 09:17:40

标签: prolog combinations

我有以下例子:

bag(b1)
bag(b2)

item(i1)
item(i2)
item(i3)
item(i4)

现在我真的不明白我是如何从中获得所有可能性的?我必须使用所有的包。 就像我应该得到这样的列表列表:

[ [together(b1, [i1,i2,i3,i4]), together(b2, [])] ,..., [together(b1, [i1]), together(b2, [i2,i3,i4])] [together(b1, [i1,i2]), together(b2, [i3,i4])] ]

等所有可能的组合但必须使用所有项。我知道我可以使用findall获取事实,但后来我被卡住了

这就是我所拥有的:

test(X) :-
findall(C, bag(C),Bags),
findall(K, item(K),Items),
something???

关于从哪里开始的任何想法,因为我是无能为力的,我不明白如何思考以达到这样的结果。

获得组合的可能想法:

item_combination(C) :-
    findall(I, item(I), Is),
    combination(Is, C).

combination(_, []).
combination(Set, [X|Xs]) :-
    select(X, Set, Set0),
    combination(Set0, Xs).

我需要类似的东西,得到第一个包的组合,然后,转到下一个包,采取组合,如果它是有效的(所有使用的项目)附加到列表,否则回到第一个包与另一种组合等等......还是有更好的解决方案?

提前致谢!

1 个答案:

答案 0 :(得分:2)

首先定义谓词powset/3,该谓词powset3([],[],[]). powset3([H|T],T2,[H|T3]) :- powset3(T,T2,T3). powset3([H|T],[H|T2],T3) :- powset3(T,T2,T3). 生成给定集合中的所有powersets,未选择元素作为第三个列表:

divide/3

接下来,我们定义一个N命令,该命令给出一个项目列表,将其划分为divide(_,N,[]) :- N < 1. divide(Items,1,[Items]). divide(Items,N,[Selected|Other]) :- N > 1, powset3(Items,Selected,Rest), N1 is N-1, divide(Rest,N1,Other). 个集合:

ziptogether/3

最后是一个ziptogether([],[],[]). ziptogether([HA|TA],[HB|TB],[together(HA,HB)|TC]) :- ziptogether(TA,TB,TC). 实用程序,它将两个列表压缩为谓词列表:

findall(I,item(I),Is),
findall(B,bag(B),Bs),
length(Bs,NB),
findall(Proposal,(divide(Is,NB,Ds),ziptogether(Bs,Ds,Proposal)),List).

你可以这样做:

?- findall(I,item(I),Is),
|        findall(B,bag(B),Bs),
|        length(Bs,NB),
|        findall(Proposal,(divide(Is,NB,Ds),ziptogether(Bs,Ds,Proposal)),List).
Is = [i1, i2, i3, i4],
Bs = [b1, b2],
NB = 2,
List = [[together(b1, []), together(b2, [i1, i2, i3, i4])], [together(b1, [i4]), together(b2, [i1, i2, i3])], [together(b1, [i3]), together(b2, [i1, i2, i4])], [together(b1, [i3, i4]), together(b2, [i1, i2])], [together(b1, [i2]), together(b2, [i1|...])], [together(b1, [i2|...]), together(b2, [...|...])], [together(b1, [...|...]), together(..., ...)], [together(..., ...)|...], [...|...]|...].

示例:

findall

懒人版

使用getBagConfig(Proposal) :- findall(I,item(I),Is), findall(B,bag(B),Bs), length(Bs,NB), divide(Is,NB,Ds), ziptogether(Bs,Ds,Proposal). 的先前版本活动:它会生成整个配置列表。在许多情况下,延迟评估更好:它使一个人能够生成有限数量的实例。懒惰的版本是:

{{1}}

时间复杂度: 算法在O(b ^ n + b + n)中运行,其中b为二进制数,n为二进制数,n为项数。< / em>的

注意: 很可能一些引入的谓词已经存在于很多Prolog实现中,但由于这些谓词不是标准化的,因此最好自己提供一个实现。