处理复杂的序言循环

Dealing with complicated prolog loops

我正在使用 Prolog 对我的一个项目中的一些相当复杂的规则进行编码。有很多递归,包括互递归。部分规则如下所示:

pred1(X) :- ...
pred1(X) :- someguard(X), pred2(X).

pred2(X) :- ...
pred2(X) :- othercondition(X), pred1(X).

pred1pred2之间有一个相当明显的无限循环。不幸的是,这些谓词之间的交互非常复杂且难以隔离。我能够通过传递已传递给 pred1 的对象列表来消除此实例中的无限循环,但这非常笨拙!事实上,它在很大程度上违背了在此应用程序中使用 Prolog 的目的。

如何让 Prolog 避免无限循环?例如,如果在证明 pred1(foo) 的过程中它试图证明 pred1(foo) 作为一个子目标,失败并回溯。

是否可以用 meta-interpreters 做到这一点?

某些 Prolog 系统中提供的一项功能可以帮助您解决此类问题,称为 制表。例如参见 [​​=11=].

如果制表不可用,那么是的,元解释器肯定可以提供很多帮助。例如,你可以用元解释器改变执行策略等。

在 SWI-Prolog 中,还检查 call_with_inference_limit/3 以稳健地限制执行,独立于 CPU 类型和系统负载。

相关且有用的是 终止分析器,例如 cTI:它们允许您静态导出 终止条件

是的,正如 mat 所建议的那样,您可以为此目的使用元解释器。但对于正常用例,这远远超出了常规工作。

您可能会考虑使用高阶谓词将循环功能与您的实际逻辑分开。这是一种非常安全的方式——SWI 甚至会检查所有的使用是否都有相应的定义。输入 make.check.

时会调用此检查

例如,考虑 closure0/3 and path/4,它都处理循环检查 "once and forever"。