通过prolog中的枚举从给定列表生成一个大列表

时间:2014-12-16 13:23:15

标签: prolog combinations permutation enumeration

我正在尝试从一个小的给定列表(N个元素)生成一个大列表(2 ^ N个元素)。例如, 有一个列表[X,Y,Z],其中X,Y或Z只能是0.1或0.9。我将从X中选取0.1或0.9,从Y中选取0.1或0.9并从Z顺序选择0.1或0.9,然后将X Y Z视为新列表的元素。因此,新列表[0.001,0.009,0.009,...,0.729][0.1*0.1*0.1, 0.1*0.1*0.9, 0.1*0.9*0.1, ..., 0.9*0.9*0.9])中应该有2 ^ N个元素。如何从给定列表中获取此新列表? N是从给定列表中获取的参数,

trn(List_given,Outlist):-
    length(List_given,N),
    ...

我只想这样实现,

?- trn([X,Y],Out).
Out=[0.01,0.09,0.09,0.81].

提前致谢!

1 个答案:

答案 0 :(得分:1)

生成值的可能组合:

mem(L, E) :- member(E, L).

gen_values(N, Choices, Values) :-
    length(Values, N),
    maplist(mem(Choices), Values).

所以:

| ?- gen_values(3, [0.1, 0.9], L).

L = [0.10000000000000001,0.10000000000000001,0.10000000000000001] ? a

L = [0.10000000000000001,0.10000000000000001,0.90000000000000002]

L = [0.10000000000000001,0.90000000000000002,0.10000000000000001]

L = [0.10000000000000001,0.90000000000000002,0.90000000000000002]

L = [0.90000000000000002,0.10000000000000001,0.10000000000000001]

L = [0.90000000000000002,0.10000000000000001,0.90000000000000002]

L = [0.90000000000000002,0.90000000000000002,0.10000000000000001]

L = [0.90000000000000002,0.90000000000000002,0.90000000000000002]

(1 ms) yes

然后你需要一个列表乘数:

prodlist(L, P) :-
    prodlist(L, 1, P).

prodlist([X], A, P) :- P is X * A.
prodlist([X,Y|T], A, P) :-
    A1 is X * A,
    prodlist([Y|T], A1, P).

然后,您可以使用findall/3获得所有结果:

trn(List_given, Outlist):-
    length(List_given, N),
    findall(X, (gen_values(N, [0.1, 0.9], Values), prodlist(Values, X)), Outlist).

导致:

| ?- trn([_,_,_], Out).

Out = [0.0010000000000000002,0.0090000000000000028,0.0090000000000000011,0.081000000000000016,0.0090000000000000011,0.081000000000000016,0.081000000000000016,0.72900000000000009]

yes
| ?-

你可以在这里使用trn([X,Y,Z], Out),但这没有意义。您也可以使用长度定义谓词:trn(3, Out)

注意,发生了一些轻微的浮点精度误差,产生长小数。此外,这种方法没有利用计算中的冗余,因此它可能不是最有效的方法。最后,如果N(输入列表的长度)很大,这将会爆炸。