我正在尝试从一个小的给定列表(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].
提前致谢!
答案 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
(输入列表的长度)很大,这将会爆炸。