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))
正确成功。在这种情况下(裸元变量),良好的编程风格也是防御性编程。