我有一个玩具模块;
:- module(toys,toy/2).
%toy(TOY_NAME,PRICE).
我有一些玩具元素,
toy(train,5).
toy(doll,6).
toy(car,3).
..ext.
我写了一个函数来计算给定玩具清单的总价格,例如
calculatePrice([],0).
calculatePrice([H|T],Result):- toy(H,P),calculatePrice(T,X), Result is X+P.
当我调用calculatePrice([train,train,doll,train],X)时,它可以正常工作并返回21。但是当我调用calculatePrice(X,21)时,会发生无限循环。
我尝试用户削减,但后来我只得到1个答案,我想得到所有可能的答案,例如玩具的所有组合,总价为21。
答案 0 :(得分:0)
Prolog首先进行“深度研究”,因此这意味着它将继续寻找将玩具清单进一步添加到清单中,并且永远不会看是否已经达到总价,从而增加了更多元素没有道理。
我们可以通过反向计算价格来解决此问题:我们可以使用library(clpfd)
并定义带有玩具的列表的价格与没有玩具的价格之间的关系,并添加价格的约束如果我们递归,我们正在寻找的值应始终大于零,例如:
:- use_module(library(clpfd)).
calculatePrice([], 0).
calculatePrice([H|T], PHT) :-
PHT #> 0,
toy(H, PH),
PHT #= PT + PH,
calculatePrice(T, PT).
然后我们获取例如:
?- calculatePrice(L, 21).
L = [train, train, train, doll] ;
L = [train, train, train, car, car] ;
L = [train, train, doll, train] ;
L = [train, train, car, train, car] ;
L = [train, train, car, car, train] ;
L = [train, doll, train, train] ;
...
?- calculatePrice([train, train], P).
P = 10.
?- calculatePrice(L, P).
L = [],
P = 0 ;
L = [train],
P = 5 ;
L = [train, train],
P = 10 ;
L = [train, train, train],
P = 15 ;
L = [train, train, train, train],
P = 20 ;
L = [train, train, train, train, train],
P = 25
...
约束PHT #> 0
在这里是必需的。例如,当我们向PHT
查询时,您会看到calculatePrice(L, 21)
作为“我们有待支出的金额”。如果金额小于或等于零,我们将无法再花任何钱,因此该约束将失效。
答案 1 :(得分:0)
有一种方法iterative deepening,它可以解决您的问题,在Prolog中具有非常简单的基本实现,并且不需要任何复杂的库:
:- module(calculatePrice,
[calculatePrice/2
]).
toy(train,5).
toy(doll,6).
toy(car,3).
calculatePrice(L, P) :-
length(L, _N),
maplist(toy, L, Ps),
sumlist(Ps, P).
收益
?- calculatePrice(Ts,21).
Ts = [train, train, train, doll] ;
Ts = [train, train, doll, train] ;
Ts = [train, doll, train, train] ;
...
当心,它不会终止。你能找出原因吗?纠正吗?否则,寻求帮助:)