检测是否证明谓词统一了某些东西

Detecting whether proving a predicate unified something

我有一个谓词可以统一其参数,例如:

foo(X) :- X = 42.

如何判断在证明 foo(X) 时是否统一改变了 X?例如,我想知道 writeln(X), foo(X), writeln(X) 是否会在不实际打印的情况下为 X 打印相同的值两次。

我的实际实现foo/1其实要复杂得多,所以请不要针对上面的简化版本提出具体建议。在我的程序中,foo(X) 使用合一化简了 X,但是 foo(X) 可能需要多次证明,直到所有的化简都完成。我希望能够编写一个 foohelper(X) 调用 foo(X) 的谓词,直到 X 停止统一。

也许你可以使用标准的 term_variables/2 谓词?您可以在调用目标之前和之后用您的目标调用它,并检查返回的变量列表是否不同。类似于:

...,
term_variables(foo(X), Vars0),
foo(X),
term_variables(foo(X), Vars),
(  Vars0 == Vars ->
   write(simplified)
;  write(not_simplified)
),
...

假设我们只有句法统一——即没有约束:

:- meta_predicate(call_instantiated(0,?)).

call_instantiated(Goal_0, Instantiated) :-
    copy_term(Goal_0, Copy_0),
    Goal_0,
    (  subsumes_term(Goal_0, Copy_0) ->  % succeeds iff equal u.t.r.
       Instantiated = false
    ;  Instantiated = true
    ).

请注意 Goal_0 会或不会进一步实例化。上面的 subsumes_term/2 测试 Goal_0 现在是否 "more general" 而不是 Copy_0。当然,它不能更通用,如此有效以至于 test 测试术语是否相同直到重命名变量。

与使用 term_variables/2 相比,正如@PauloMoura 所指出的,这可能效率更高。主要看subsumes_term/2.

的效率