【问题标题】:Prolog backtracks and loses all valuesProlog 回溯并丢失所有值
【发布时间】:2014-01-24 01:16:50
【问题描述】:

我有一些序言谓词来计算给定城市的成本。该过程以如下命令开始:best_route([std, lhr, bud, dse], 2013-5-5, X).

best_route(Cities, StartDate, Cost):-
    begin_routing(Cities, StartDate, Cost, []).

begin_routing(Cities, StartDate, Cost, CostList):-
    route(Cities, StartDate, CostList),
    min_list(CostList, Cost).

route(Cities, StartDate, Costing):-
    % stop if all cities have been covered once.
    length(Cities, Stop),
    length(Costing, Stop);

    [Origin, Dest|_] = Cities,
    flights(Origin, Dest, StartDate, Costing, Cities, [Cities, Origin, StartDate]).

使用SWI-Prolog中的trace函数,我发现一旦路由谓词-length(Costing, Stop)得到满足,即Costing List的长度等于Stop。 Prolog 并没有停在那里,而是继续使用min_list(CostList, Cost),而是回溯,直到 CostLost 再次丢失其所有值。完成后,当列表为 [] 时,它会转到 min_list

我不确定为什么会发生这种情况。任何帮助表示赞赏。

编辑:

flights(..):-
    % Code omitted.
    get_next_date(OriginalDate, NextDate),
    route(Cities, NextDate, [DayCost|Costing]).
    % where DayCost is a simple integer calculated before this is added to the current Costing list

最后,最后一个正确的电话是route([std, lhr, bud, dse], 2013-5-6, [329, 499, 323, 311]).

【问题讨论】:

  • 通读best_routebegin_routing,似乎在第一次调用route时,Cities被实例化为[std, lhr, bud, dse]Costing被实例化为[]。对length(Costing, Stop) 的调用变为length([], 4) 并失败。它以析取(;)终止,因此route 不会在此时失败,而是继续[Origin, Dest|_] = Cities 实例化OriginDest,然后调用flights。由于您没有显示 flights 的作用,因此不清楚它从那里做了什么。
  • @mbratch:请查看已编辑的问题,我省略了部分代码,因为它们相当不必要且冗长。希望这能让它更清楚。
  • @Namit: min_list(CostList, Cost) 失败或需要更多评估?要强制终止,请添加一个愚蠢的替代方案:( min_list(CostList, Cost) ; true )
  • @mbratch:它失败了,因为CostList 没有在递归期间进行。添加true 也没有太大区别。
  • @Namit,我在说明为什么它没有立即回到min_list

标签: prolog


【解决方案1】:

CostList 的用意似乎是记录不同路线的费用,然后选择费用最小的路线。但是,您将CostList 初始化为[],并且当递归正在构建CostList 时,您没有提供在递归返回时将其返回的方法。一个可能的解决方案是添加一个新参数FinalCostList,它只是简单地通过递归传递,直到终止子句。或者,您可以使用差异列表。

为了说明这一点,请考虑以下示例:

p :- q([]).
q(X) :- go(X), !, q([a|X]).
q(X) :- stop(X).

有一些相互排斥的gostop。计算期望的结果(q 和所有 as,只要 go)被计算但不返回。更好的解决方案是

p(Y) :- q([],Y).
q(X,Y) :- go(X), !, q([a|X],Y).
q(X,X) :- stop(X).

如上所述,也可以使用差异列表。

【讨论】:

  • 感谢您的回答,但为了清楚起见,您是说我应该将 CostList 的内容复制到通过递归进行的另一个参数吗?
  • 基本上是的。您还可以考虑将传递信息组合成递归和退出的差异列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多