Prolog 检测是否证明谓词统一了某些内容

Prolog 检测是否证明谓词统一了某些内容,prolog,unification,Prolog,Unification,我有一个可以统一其参数的谓词,例如: foo(X):-X=42。 在证明foo(X)时,我如何判断统一是否改变了X?例如,我想知道writeln(X)、foo(X)、writeln(X)是否会将相同的值打印两次,而不进行实际打印 我对foo/1的实际实现实际上要复杂得多,所以请不要建议特定于上面的简化版本。在我的程序中,foo(X)使用统一简化了X,但是foo(X)可能需要多次验证,直到所有简化都完成。我希望能够编写一个调用foo(X)谓词的foo(X),直到X停止统一 也许你可以使用标准的术语

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

foo(X):-X=42。

在证明
foo(X)
时,我如何判断统一是否改变了X?例如,我想知道
writeln(X)、foo(X)、writeln(X)
是否会将相同的值打印两次,而不进行实际打印


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

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

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

也许您可以使用标准的
术语\u 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
将或不会进一步实例化。上面的
包含了\u term/2
测试
目标\u 0
现在是否比
复制\u 0
更“一般”。当然,它不能更一般,因此有效地测试术语是否相同,直到重命名变量为止


正如@PauloMoura所指出的,与使用术语变量/2相比,这可能更有效。这主要取决于
包含项/2

的效率,假设我们只有语法统一,即没有约束:

:- 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
将或不会进一步实例化。上面的
包含了\u term/2
测试
目标\u 0
现在是否比
复制\u 0
更“一般”。当然,它不能更一般,因此有效地测试术语是否相同,直到重命名变量为止


正如@PauloMoura所指出的,与使用术语变量/2相比,这可能更有效。它主要取决于
subsumes\u term/2

的效率,您希望何时告知是否已实例化
X
?(我们不改变
X
,我们实例化了它)我想知道
X
是否在我的例子中第二个
writeln(X)
的位置被实例化,同时证明
foo(X)
。你想知道
X
是否被实例化了?(我们不改变
X
,我们实例化了它)我想知道
X
在我的例子中,在证明
foo(X)
的第二个
writeln(X)
位置时是否实例化了
X
。“简化”应该是“相同的”@false阅读问题。在那里你会发现我为什么用“简化”这个词。我想这应该行得通——谢谢!我很好奇是否有更好的方法来拍摄一个术语的“快照”。@EdMcMan您也可以使用标准的
copy\u term/2
谓词来拍摄一个术语的快照,然后将此快照与标准的
subsumes\u term/2
谓词一起使用,但这将是一个更详细、更昂贵的解决方案。“simplified”应该是“等同的”@false阅读这个问题。你会发现我为什么用“simplified”这个词。我想这应该行得通——谢谢!我想知道有没有更好的方法来拍摄“快照”“@EdMcMan您可以使用标准的
copy\u term/2
谓词来获取一个术语的快照,然后将此快照与标准的
subsumes\u term/2
谓词一起使用,但这将是一个更详细、成本更高的解决方案。
Goal\u 0
应该是
call(Goal\u 0)
。使用裸(元)变量的编程风格不好。此外,它们的语义可能等同于也可能不等同于
call/1
,这取决于Prolog系统(w.r.t.对cuts不透明或透明)。@PauloMoura??这是定义明确的行为。哪个Prolog系统不能正确处理这个问题?不是正确性的问题,而是为裸元变量选择语义的问题。ECLiPSe是一个系统的例子,在这个系统中,裸露的元变量对切割是透明的。@PauloMoura:也许有时候会有一些不同。但这种情况没有区别。说:
mynot(X):-X!,失败mynot(41;
。在Eclipse(默认模式)下使用
mynot((!,fail))
正确成功。在这种情况下(裸元变量),良好的编程风格也是防御性编程。
Goal\u 0
应该是
call(Goal\u 0)
。使用裸(元)变量的编程风格不好。此外,它们的语义可能等同于也可能不等同于
call/1
,这取决于Prolog系统(w.r.t.对cuts不透明或透明)。@PauloMoura??这是定义明确的行为。哪个Prolog系统不能正确处理这个问题?不是正确性的问题,而是为裸元变量选择语义的问题。ECLiPSe是一个系统的例子,在这个系统中,裸露的元变量对切割是透明的。@PauloMoura:也许有时候会有一些不同。但这种情况没有区别。说:
mynot(X):-X!,失败mynot(41;
。在Eclipse(默认模式)下使用
mynot((!,fail))
正确成功。在这种情况下(裸元变量),良好的编程风格也是防御性编程。