如何确定两个命题公式在 Prolog 中是否等价?
How to determine if two propositional formulas are equivalent in Prolog?
我是 Prolog 的新手,有一些疑问。
我需要编写一个函数 form_equiv(A,B) 来告诉我们 B 是否等同于 A
其中 A 和 B 应该是命题。
我知道两个命题等价如果
重言式 (A iff B) = TRUE
但是我怎样才能创建一个函数来检查公式何时是同义反复。
顺便说一句,我不能只使用 AND、OR 和 NOT 的内置函数。
现在这是我目前拥有的:
and(P,Q) :- P, Q, !.
or(P,Q) :- (P; Q), !.
impl(P,Q) :- or(not(P),Q).
syss(P,Q) :- and(impl(P,Q),impl(Q,P)).
t.
f :- fail.
t(_).
f(_) :- fail.
:- op(400,xf,not).
:- op(500,xfx,and).
:- op(500,xfx,or).
:- op(600,xfx,impl).
:- op(700,xfx,syss).
我在 Haskell 中做过一个类似的程序,但我对 Prolog 真的很陌生。
谁能帮我写一个函数来检查公式是否是重言式?
提前致谢...
首先是逻辑部分:如果 A → B ∧ B → A
成立,则两个公式 A
和 B
是等价的。如果你能证明这个公式你就完成了。
现在进入序言部分:
- 您混淆了谓词和术语级别:
and(A, B)
将失败,并显示 A
未充分实例化的错误消息。创建谓词 eval
并定义 eval(and(A,B))
、eval(or(A,B))
等 就容易多了
- 您没有逻辑变量的表示。假设我的公式只是
A
。我如何确定 A
是否可以取真/假?我建议将变量显式包装到构造函数 var(Truthvalue)
中,以在模式匹配期间将其与逻辑运算符区分开来。否则,您的证明搜索将尝试将变量扩展为更复杂的公式,这显然没有帮助。
- 您在不必要的地方使用 cuts / fail:只有一个
and(P,Q)
定义,因此 cut 不会做任何事情。类似地,fail 使规则失败,就好像它不存在一样 - 因此您可以删除这些规则(除非您使用 cut 的额外功能,即)。请记住,cut 的行为不像逻辑结构,应尽可能避免。
- 你在制定否定时遇到了问题:你没有明确的否定规则,你的 ⊤ 和 ⊥ 谓词与你的其余规则没有联系(假设你想将 ¬A 定义为 A → ⊥)。这是由于 Prolog 规则的不对称性:派生谓词意味着它为真,但 non-derivability 不是定义逻辑错误语句的好方法。在这种情况下,我们可以明确说明公式为假的含义:例如如果
A
为假或 B
为假(或两者),则 A ∧ B
为假。让我们将 eval
分成两部分:如果 X
为真,则 eval_tt(X)
可推导;如果 X
为假,则 eval_ff(X)
可推导。
将所有这些笔记放在一起,这就是 ∧ 和 ¬ 的最小完整微积分:
eval_tt(var(true)).
eval_tt(and(A,B)) :-
eval_tt(A),
eval_tt(B).
eval_tt(not(A)) :-
eval_ff(A).
eval_ff(var(false)).
eval_ff(and(A,_B)) :-
eval_ff(A).
eval_ff(and(_A,B)) :-
eval_ff(B).
eval_ff(not(A)) :-
eval_tt(A).
我们可以使用以下查询查询 ¬(A ∧ ¬B)
的模型:
?- eval_tt(not(and(var(A), not(var(B))))).
A = false ;
B = true.
如果我们使用 cut 或 negation 作为失败,我们可能不会找到这两种解决方案。
同样 A ∧ ¬A
是不可满足的,正如预期的那样:
?- eval_tt(and(var(A), not(var(A)))).
false.
现在你只需要用你想要的其他运算符(析取、蕴涵、等价等)来扩展这个最小的微积分。顺便提一句。如果你看过相继演算,你可能会认出其中的一些想法:)
编辑:我还没有解释如何从可满足性到有效性。问题如下:从查询到 eval_tt(X)
的答案替换只告诉我们 X
是可满足的。在逻辑中,我们通常根据 ¬X 不可满足来将 X 定义为有效。这可以在 Prolog 中通过定义将否定表示为失败:
valid(X) :-
\+ eval_ff(X).
这里有什么问题?我们检查可满足性的公式,例如
?- valid2(not(and(var(X),not(var(X))))).
true.
但我们没有得到答案替换。特别是如果查询没有充分实例化,我们会得到错误的结果:
?- valid(X).
false.
但肯定有一个有效的公式 - 我们在上面尝试过一个。我还没有找到可以枚举所有有效公式的好的解决方案。
我是 Prolog 的新手,有一些疑问。
我需要编写一个函数 form_equiv(A,B) 来告诉我们 B 是否等同于 A 其中 A 和 B 应该是命题。
我知道两个命题等价如果
重言式 (A iff B) = TRUE
但是我怎样才能创建一个函数来检查公式何时是同义反复。
顺便说一句,我不能只使用 AND、OR 和 NOT 的内置函数。
现在这是我目前拥有的:
and(P,Q) :- P, Q, !.
or(P,Q) :- (P; Q), !.
impl(P,Q) :- or(not(P),Q).
syss(P,Q) :- and(impl(P,Q),impl(Q,P)).
t.
f :- fail.
t(_).
f(_) :- fail.
:- op(400,xf,not).
:- op(500,xfx,and).
:- op(500,xfx,or).
:- op(600,xfx,impl).
:- op(700,xfx,syss).
我在 Haskell 中做过一个类似的程序,但我对 Prolog 真的很陌生。
谁能帮我写一个函数来检查公式是否是重言式?
提前致谢...
首先是逻辑部分:如果 A → B ∧ B → A
成立,则两个公式 A
和 B
是等价的。如果你能证明这个公式你就完成了。
现在进入序言部分:
- 您混淆了谓词和术语级别:
and(A, B)
将失败,并显示A
未充分实例化的错误消息。创建谓词eval
并定义eval(and(A,B))
、eval(or(A,B))
等 就容易多了
- 您没有逻辑变量的表示。假设我的公式只是
A
。我如何确定A
是否可以取真/假?我建议将变量显式包装到构造函数var(Truthvalue)
中,以在模式匹配期间将其与逻辑运算符区分开来。否则,您的证明搜索将尝试将变量扩展为更复杂的公式,这显然没有帮助。 - 您在不必要的地方使用 cuts / fail:只有一个
and(P,Q)
定义,因此 cut 不会做任何事情。类似地,fail 使规则失败,就好像它不存在一样 - 因此您可以删除这些规则(除非您使用 cut 的额外功能,即)。请记住,cut 的行为不像逻辑结构,应尽可能避免。 - 你在制定否定时遇到了问题:你没有明确的否定规则,你的 ⊤ 和 ⊥ 谓词与你的其余规则没有联系(假设你想将 ¬A 定义为 A → ⊥)。这是由于 Prolog 规则的不对称性:派生谓词意味着它为真,但 non-derivability 不是定义逻辑错误语句的好方法。在这种情况下,我们可以明确说明公式为假的含义:例如如果
A
为假或B
为假(或两者),则A ∧ B
为假。让我们将eval
分成两部分:如果X
为真,则eval_tt(X)
可推导;如果X
为假,则eval_ff(X)
可推导。
将所有这些笔记放在一起,这就是 ∧ 和 ¬ 的最小完整微积分:
eval_tt(var(true)).
eval_tt(and(A,B)) :-
eval_tt(A),
eval_tt(B).
eval_tt(not(A)) :-
eval_ff(A).
eval_ff(var(false)).
eval_ff(and(A,_B)) :-
eval_ff(A).
eval_ff(and(_A,B)) :-
eval_ff(B).
eval_ff(not(A)) :-
eval_tt(A).
我们可以使用以下查询查询 ¬(A ∧ ¬B)
的模型:
?- eval_tt(not(and(var(A), not(var(B))))).
A = false ;
B = true.
如果我们使用 cut 或 negation 作为失败,我们可能不会找到这两种解决方案。
同样 A ∧ ¬A
是不可满足的,正如预期的那样:
?- eval_tt(and(var(A), not(var(A)))).
false.
现在你只需要用你想要的其他运算符(析取、蕴涵、等价等)来扩展这个最小的微积分。顺便提一句。如果你看过相继演算,你可能会认出其中的一些想法:)
编辑:我还没有解释如何从可满足性到有效性。问题如下:从查询到 eval_tt(X)
的答案替换只告诉我们 X
是可满足的。在逻辑中,我们通常根据 ¬X 不可满足来将 X 定义为有效。这可以在 Prolog 中通过定义将否定表示为失败:
valid(X) :-
\+ eval_ff(X).
这里有什么问题?我们检查可满足性的公式,例如
?- valid2(not(and(var(X),not(var(X))))).
true.
但我们没有得到答案替换。特别是如果查询没有充分实例化,我们会得到错误的结果:
?- valid(X).
false.
但肯定有一个有效的公式 - 我们在上面尝试过一个。我还没有找到可以枚举所有有效公式的好的解决方案。