【问题标题】:SWI-Prolog Backtrace Infinite LoopSWI-Prolog 回溯无限循环
【发布时间】:2019-05-18 17:59:05
【问题描述】:

我有一个玩具模块;

:- 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 的所有玩具组合。

【问题讨论】:

    标签: prolog


    【解决方案1】:

    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。当我们查询 calculatePrice(L, 21) 时,您可以看到 PHT 作为“我们还剩下要花费的金额”。如果金额小于或等于零,我们就不能再花任何钱了,因此这个约束应该失败。

    【讨论】:

    • 谢谢你的回答,我知道了
    【解决方案2】:

    有一种方法,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...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      相关资源
      最近更新 更多