没有断言/撤回的分支和边界

vas*_*ily 1 prolog branch-and-bound

这个练习要求我找到三种产品的最佳组合,考虑到价格和要避免的特定组合。教科书使用assertzretractall模拟一个状态变量。


price(a1, 1900).
price(a2,  750).
price(a3,  900).
price(b1,  300).
price(b2,  500).
price(b3,  450).
price(b4,  600).
price(c1,  700).
price(c2,  850).

incompatible(a2, c1).
incompatible(b2, c2).
incompatible(b3, c2).
incompatible(a2, b4).
incompatible(a1, b3).
incompatible(a3, b3).

:- dynamic bound/1.
bound(5000).

solution(A, B, C, P) :-
  member(A, [a1, a2, a3]), 
  price(A, PA),
  member(B, [b1, b2, b3, b4]),
  \+ incompatible(A, B),
  price(B, PB),
  P0 is PA + PB,
  bound(Bound),
  write('Current bound: '), writeln(Bound),
  P0 =< Bound,
  member(C, [c1, c2]),
  \+ incompatible(A, C),
  \+ incompatible(B, C),
  price(C, PC),
  P is PA + PB + PC,
  P =< Bound,
  retractall(bound(_)),
  assertz(bound(P)).
Run Code Online (Sandbox Code Playgroud)
  1. 是否可以在 Prolog 中使用分支定界而不诉诸动态谓词?
  2. Prolog 中的状态变量是否有共识?
  3. 有没有办法将状态变量(或任何代理)的范围限制为单个规则?

fal*_*lse 5

这段代码最大的问题是它不可重入。它隐含地假设在任何时间点都只有一个搜索实例。但是如果内部的某些部分想要自己使用类似的搜索,则没有警告没有错误可以防止这种情况发生。

对于精确的机制应该是什么样子,目前还没有太多共识,现有的系统各不相同。要理解这一点,请查看SICStus、SWI 和 Eclipse的实现findall/3call_nth/2哪里有特定的解决方案。正是这里也需要这种机制。

但也要考虑使这个搜索更通用。据推测,您所指的教科书是在call/N.