我有一个(SWI-)Prolog程序,它以极大的方式使用CLP(FD)变量(²)。我正在将CLP(FD)项列表移入和移出几个谓词(¹),并且它们的约束呈指数增长。我的代码适用于小型列表,但是当我尝试将它用于长元素列表(每个元素的约束量变得很大)时,我最终会遇到 Out of global stack 错误。< / p>
我的观点是我是否可以使用不同的方法来传递这些巨大的参数而不使用堆栈。我的第一个想法是使用asserta
将中间结果存储在动态数据库中,但我不确定我是否能够以这种方式存储未实例化的变量或CLP(FD)约束。而且我不知道这是否是最佳解决方案......
¹更多详细信息:我需要的是N个长度为L的列表的重叠,其中第一个元素是非关系的。但是,偏移量不受约束,而是CLP(FD)变量。
²更多细节:基本上,我有许多列表,其中每个元素都有数千个约束。每个元素约束基本上都包含有关其值的信息,该值与“主变量”值相关联。根据主变量的值,每个列表项都有一个或另一个值。
由于我已经遇到了这种列表生成器的实现问题,我在这里询问了一些建议,你可以看到实际的列表制作者谓词overlap_at/5
,here。
overlap_lists/4
是发出错误的谓词(确实适用于Rs
长度少于140个元素且小于10 Cs
} elements):
% Cs -> lists that have to be overlapped. Their items are integers.
% Ss -> Offsets per each list. They are CLP(FD) variables.
% Rs -> (not important here)
% Os -> List of overlapped elements.
overlap_lists(Cs,Ss,Rs,Os) :-
length(Rs,L),
zeros(Zs,L), % The initial list to overlap with is a list filled with zeros.
overlap(Cs,Ss,Zs,Os),
list_limit(Os,Rs). % Constrains the consumptions
overlap([],[],Fs,Fs) :- !.
overlap([C|Cs],[S|Ss],Os,Fs) :-
fd_inf(S,Inf),
overlap_at(Os,C,S,Inf,Os2),!,
overlap(Cs,Ss,Os2,Fs).
overlap_at([], _, _, _, []).
overlap_at([A|As], Bs, S, N0, [AB|ABs]) :-
overlap_here(Bs, [A|As], [AB|ABs], Conj),
S #= N0 #==> Conj,
S #> N0 #==> AB #= A,
N1 #= N0 + 1,
overlap_at(As, Bs, S, N1, ABs).
overlap_here(_, [], _, 1) :- !.
overlap_here([], [A|As], [AB|ABs], (AB #= A #/\ Rest)) :-
overlap_here([], As, ABs, Rest).
overlap_here([B|Bs], [A|As], [AB|ABs], (AB #= A + B #/\ Rest)) :-
overlap_here(Bs, As, ABs, Rest).
答案 0 :(得分:3)
首先想到的是:增加SWI-Prolog通过
分配的全局堆栈 swipl -G128M ...
可能有助于您阅读有关Prolog堆栈的更多信息:例如,全局堆栈不应与本地堆栈混淆。以不同方式传递参数通常无助于减少全局堆栈使用量。 Richard O'Keefes Prolog的工艺包含了关于空间去向的很好的讨论。
在64位处理器上,使用SWI-Prolog时全局堆栈可能大于128MB,因此对于严格的计算,您可能需要一台具有大量RAM的64位计算机。
话虽这么说,我发布的代码只使用多项式,而不是指数量的内存。如果您以一种需要指数空间的方式来制定问题,您可能首先尝试找到更多(记忆)效率的公式。这个问题似乎并不需要指数空间。
如果您需要保留assertz/1
上的约束,请使用copy_term/3
将约束作为剩余目标获取,并将这些剩余目标与变量一起断言,以便稍后通过{{恢复目标1}}。