如何在Isabelle中证明2公式在语义上是等价的
我想(错过-)用Isabelle来证明两个给定的公式在语法上是等价的。例如如何在Isabelle中证明2公式在语义上是等价的,isabelle,equivalence,Isabelle,Equivalence,我想(错过-)用Isabelle来证明两个给定的公式在语法上是等价的。例如A∧ B=B∧ A 关于公式背后的逻辑,我不想详细讨论。我不想关心那件事∧ 当A和B都为真时,B为真。我只想在结构层面上比较这两个公式,并说它们是等价的,因为它们具有交换性质 基本上,我希望能够写出比较两个公式和一些等式函数的引理,并使用给定的公理,不管它们是如何指定的 到目前为止,我认为这可以而且应该使用公理化来完成,但是这里的每个人都告诉我公理化是不好的 这就引出了我的问题:这项任务应该如何完成。在《伊莎贝尔》中,如何
A∧ B=B∧ A
关于公式背后的逻辑,我不想详细讨论。我不想关心那件事∧ 当A和B都为真时,B为真。我只想在结构层面上比较这两个公式,并说它们是等价的,因为它们具有交换性质
基本上,我希望能够写出比较两个公式和一些等式函数的引理,并使用给定的公理,不管它们是如何指定的
到目前为止,我认为这可以而且应该使用公理化
来完成,但是这里的每个人都告诉我公理化
是不好的
这就引出了我的问题:这项任务应该如何完成。在《伊莎贝尔》中,如何比较2(比如命题)公式的句法等价性。举一个具体的例子:
formula ∧ formula | formula ∨ formula
如果可能的话,以运算符的形式给出
和分配性和交换性
作为规则给出。
A∧ B=B∧ 一个
,如果在定理中陈述,则应该是可证明的
这就是我想要做的,我希望这个想法是明确的,有人能向我解释如何在伊莎贝尔身上正确地追求这个目标。提前谢谢。从你所写的内容来看,我很确定你指的是句法对等。如果两个公式对所有变量的赋值结果相同,则它们在语义上是等价的;如果给定一组特定的重写规则(或者更一般地说,使用一组特定的推理规则证明它们的等价性),那么两个公式在语法上是等价的。语义对等只关注表达的价值,而不关注表达的结构;句法等价只关注表达式的结构,而不是它们产生的值 现在,我们来回答如何在伊莎贝尔身上做到这一点的问题 定义关系 标准方法是为公式定义数据类型(我为其添加了一些更好的中缀语法): 然后,您可以定义“评估”的概念,如公式w.r.t.给定变量的评估:
primrec eval_formula :: "(vname ⇒ bool) ⇒ formula ⇒ bool" where
"eval_formula s (Atom x) ⟷ s x"
| "eval_formula _ FTrue ⟷ True"
| "eval_formula s (Neg a) ⟷ ¬eval_formula s a"
| "eval_formula s (a and b) ⟷ eval_formula s a ∧ eval_formula s b"
| "eval_formula s (a or b) ⟷ eval_formula s a ∨ eval_formula s b"
lemma eval_formula_False [simp]: "eval_formula s FFalse = False"
by (simp add: FFalse_def)
在此基础上,您可以定义语义等价的概念:如果两个公式在所有赋值中的求值结果相同,则它们在语义上是等价的:
definition formula_equiv_sem :: "formula ⇒ formula ⇒ bool" (infixl "≈" 40) where
"a ≈ b ⟷ (∀s. eval_formula s a = eval_formula s b)"
从你的问题中,我推断你想做的是根据重写规则定义某种等价关系:如果你可以通过应用一组给定的重写规则将一个公式转换成另一个公式,那么两个公式在语法上是等价的
这可以通过Isabelle的归纳谓词包来实现:
inductive formula_equiv :: "formula ⇒ formula ⇒ bool" (infixl "∼" 40) where
formula_refl [simp]: "a ∼ a"
| formula_sym: "a ∼ b ⟹ b ∼ a"
| formula_trans [trans]: "a ∼ b ⟹ b ∼ c ⟹ a ∼ c"
| neg_cong: "a ∼ b ⟹ Neg a ∼ Neg b"
| conj_cong: "a1 ∼ b1 ⟹ a2 ∼ b2 ⟹ a1 and a2 ∼ b1 and b2"
| disj_cong: "a1 ∼ b1 ⟹ a2 ∼ b2 ⟹ a1 or a2 ∼ b1 or b2"
| conj_commute: "a and b ∼ b and a"
| disj_commute: "a or b ∼ b or a"
| conj_assoc: "(a and b) and c ∼ a and (b and c)"
| disj_assoc: "(a or b) or c ∼ a or (b or c)"
| disj_conj: "a or (b and c) ∼ (a or b) and (a or c)"
| conj_disj: "a and (b or c) ∼ (a and b) or (a and c)"
| de_morgan1: "Neg (a and b) ∼ Neg a or Neg b"
| de_morgan2: "Neg (a or b) ∼ Neg a and Neg b"
| neg_neg: "Neg (Neg a) ∼ a"
| tnd: "a or Neg a ∼ FTrue"
| contr: "a and Neg a ∼ FFalse"
| disj_idem: "a or a ∼ a"
| conj_idem: "a and a ∼ a"
| conj_True: "a and FTrue ∼ a"
| disj_True: "a or FTrue ∼ FTrue"
前六条规则基本上设置了重写(您可以将任何内容重写到自身,您可以从左到右或从右到左重写,您可以链接重写步骤,如果您可以重写子项,您还可以重写整个术语)。剩下的规则是一些示例规则,您可能希望在其中包含这些规则(不要求完整性)
有关归纳谓词的更多信息,请参阅谓词工具手册
证明它的东西
那么你能用这个做什么呢?我想你们会想证明这是正确的,也就是说,两个在语法上等价的公式在语义上也是等价的:
lemma formula_equiv_syntactic_imp_semantic:
"a ∼ b ⟹ a ≈ b"
by (induction a b rule: formula_equiv.induct)
(auto simp: formula_equiv_sem_def)
value "Atom 0 and Atom 1 ≈ Atom 1 and Atom 0" (* True *)
value "Atom 0 and Atom 1 ≈ Atom 1 or Atom 0" (* False *)
您可能还想证明一些派生的语法规则。为此,使用一些方便的传递性规则并使用同余规则设置简化器是很有用的:
lemmas formula_congs [simp] = neg_cong conj_cong disj_cong
lemma formula_trans_cong1 [trans]:
"a ∼ f b ⟹ b ∼ c ⟹ (⋀x y. x ∼ y ⟹ f x ∼ f y) ⟹ a ∼ f c"
by (rule formula_trans) simp_all
lemma formula_trans_cong2 [trans]:
"a ∼ b ⟹ f b ∼ f c ⟹ (⋀x y. x ∼ y ⟹ f x ∼ f y) ⟹ f a ∼ f c"
by (rule formula_trans) simp_all
然后我们可以做这样的证明:
lemma conj_False: "a and FFalse ∼ FFalse"
proof -
have "a and FFalse ∼ Neg (Neg (a and FFalse))"
by (rule formula_sym, rule neg_neg)
also have "Neg (a and FFalse) ∼ Neg a or Neg FFalse"
by (rule de_morgan1)
also have "Neg FFalse ∼ FTrue" unfolding FFalse_def by (rule neg_neg)
also have "Neg a or FTrue ∼ FTrue" by (rule disj_True)
also have "Neg FTrue = FFalse" unfolding FFalse_def ..
finally show ?thesis by - simp
qed
lemma disj_False: "a or FFalse ∼ a"
proof -
have "a or FFalse ∼ Neg (Neg (a or FFalse))" by (rule formula_sym, rule neg_neg)
also have "Neg (a or FFalse) ∼ Neg a and Neg FFalse" by (rule de_morgan2)
also have "Neg FFalse ∼ FTrue" unfolding FFalse_def by (rule neg_neg)
also have "Neg a and FTrue ∼ Neg a" by (rule conj_True)
also have "Neg (Neg a) ∼ a" by (rule neg_neg)
finally show ?thesis by - simp
qed
当然,人们还想证明完备性,即语义等价的任何两个公式在语法上也是等价的。对于这一点,我认为你需要更多的规则,然后证明是相当复杂的
为什么不公理化?
您提到了公理化,您可能会问,为什么建议您不要将其用于此目的。一个原因是公理化允许你在系统中引入不一致性。你可以“定义”两个事物是等价的,也可以在另一个地方定义其他事物,这意味着它们是不等价的,然后你就得到了False,破坏了一切。对于归纳谓词包,这是不可能发生的,因为它会自动证明您的定义是一致的。(通过将它们限制为单调)
一个更实际的原因是,正如你在上面看到的,你可以对归纳谓词进行归纳,也就是说,如果你有两个语法等价的公式,你可以对它们的语法等价性的证明树进行归纳。特别是,您知道如果两个公式在语法上是等价的,那么必须根据您指定的规则来证明。如果你只是做了公理化,你就没有这样的保证——可能会有更多语法上等价的公式;有了公理化,你甚至不能反驳像原子0这样的东西≈ Atom 1,除非您也将类似的东西公理化,否则这将非常难看,并且非常容易出现意外的不一致
Isabelle用户很少使用公理化。多年来,我一直在与Isabelle合作,也从未使用过公理化。它是一个非常低级的功能,旨在设置基本的底层逻辑,并且在高级定义工具上投入了大量的工作,如typedef
,datatype
,fun
,inclusive
,codatatype
等,为用户提供了一个定义界面(希望如此)保证与用户的一致性
附录:确定语义对等
如果您对使用代码生成在公式上做一些有趣的事情感兴趣:我们甚至可以决定语义等价性:我们可以简单地测试这两个表达式是否求值
primrec vars :: "formula ⇒ vname list" where
"vars (Atom x) = [x]"
| "vars FTrue = []"
| "vars (Neg a) = vars a"
| "vars (Conj a b) = vars a @ vars b"
| "vars (Disj a b) = vars a @ vars b"
lemma eval_formula_cong:
"(⋀x. x ∈ set (vars a) ⟹ s x = s' x) ⟹ eval_formula s a = eval_formula s' a"
by (induction a) simp_all
primrec valuations :: "vname list ⇒ (vname ⇒ bool) list" where
"valuations [] = [λ_. False]"
| "valuations (x#xs) = [f' . f ← valuations xs, f' ← [f, fun_upd f x True]]"
lemma set_valuations: "set (valuations xs) = {f. ∀x. x∉set xs ⟶ f x = False}"
proof safe
case (goal2 f)
thus ?case
proof (induction xs arbitrary: f)
case (Cons x xs)
def f' ≡ "fun_upd f x False"
from Cons.prems have f': "f' ∈ set (valuations xs)"
by (intro Cons) (auto simp: f'_def)
show ?case
proof (cases "f x")
case False
hence "f' = f" by (intro ext) (simp add: f'_def)
with f' show ?thesis by auto
next
case True
hence "fun_upd f' x True = f" by (intro ext) (simp add: f'_def)
with f' show ?thesis by auto
qed
qed auto
qed (induction xs, auto)
lemma formula_equiv_sem_code [code]:
"a ≈ b ⟷ (∀s∈set (valuations (remdups (vars a @ vars b))).
eval_formula s a = eval_formula s b)"
unfolding formula_equiv_sem_def
proof (rule iffI; rule ballI allI)
case (goal2 s)
def s' ≡ "λx. if x ∈ set (vars a @ vars b) then s x else False"
have "s' ∈ set (valuations (remdups (vars a @ vars b)))"
by (subst set_valuations) (auto simp: s'_def)
with goal2 have "eval_formula s' a = eval_formula s' b" by blast
also have "eval_formula s' a = eval_formula s a"
by (intro eval_formula_cong) (auto simp: s'_def)
also have "eval_formula s' b = eval_formula s b"
by (intro eval_formula_cong) (auto simp: s'_def)
finally show ?case .
qed auto
value "Atom 0 and Atom 1 ≈ Atom 1 and Atom 0" (* True *)
value "Atom 0 and Atom 1 ≈ Atom 1 or Atom 0" (* False *)