SWI-Prolog回溯无限循环

时间:2019-05-17 20:55:11

标签: prolog

我有一个玩具模块;

:- 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。

2 个答案:

答案 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] ;
...

当心,它不会终止。你能找出原因吗?纠正吗?否则,寻求帮助:)

如果您想进一步了解迭代加深和Prolog,请参阅this pagethis doc ...