Isabelle 为什么赢了';伊莎贝尔简化了我的身体;如果“然后”则“其他”;构造?
我有以下Isabelle目标:Isabelle 为什么赢了';伊莎贝尔简化了我的身体;如果“然后”则“其他”;构造?,isabelle,Isabelle,我有以下Isabelle目标: lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False" 尽管目标很简单,但是没有一种战术能在目标上取得任何进展。simp、fast、clarsimp、blast、fastforce 为什么Isabelle不简化if构造的主体,以便≠ a和b≠ b“变得False,从而解决目标?if\u-weak\u-cong一致性规则 默认情况下,Isabelle包含一组影响简化发生位置的“一致性规则”。特别是,默认的一致性规则是if_
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
尽管目标很简单,但是没有一种战术能在目标上取得任何进展。simp
、fast
、clarsimp
、blast
、fastforce
为什么Isabelle不简化if
构造的主体,以便≠ a和b≠ b“变得False
,从而解决目标?if\u-weak\u-cong一致性规则
默认情况下,Isabelle包含一组影响简化发生位置的“一致性规则”。特别是,默认的一致性规则是if_weak_cong
,如下所示:
b = c ⟹ (if b then x else y) = (if c then x else y)
此一致性规则告诉简化程序简化if
语句(即b=c
)的条件,但决不尝试简化if
语句的主体
您可以使用以下方法禁用一致性规则:
apply (simp cong del: if_weak_cong)
或者用另一个(更强大的)一致性规则覆盖它:
apply (simp cong: if_cong)
这两个问题都将解决上述引理
为什么如果“弱”cong
在默认cong集合中
另一个合理的问题可能是:“如果_weak _cong会导致上述问题,为什么会在默认同余集中?”
一个动机是防止简化器无限地展开递归函数,如以下情况:
fun fact where
"fact (n :: nat) = (if n = 0 then 1 else (n * fact (n - 1)))"
在这种情况下,
lemma "fact 3 = 6"
by simp
解决目标,同时
lemma "fact 3 = 6"
by (simp cong del: if_weak_cong)
将简化器发送到一个循环中,因为fact
定义的右侧不断展开
第二种情况往往比原始问题中的情况发生得更频繁,这促使if\u weak\u cong
成为默认情况。在包含if\then\else>的证明中取得进展的另一种自然方式是对条件进行案例分析,例如
lemma "(if foo then a ~= a else b ~= b) ==> False"
by (cases foo) simp_all
或者,如果foo
不是一个自由变量,而是由最外层的元级通用量词绑定(在apply脚本中经常出现这种情况):
不幸的是,如果foo
被另一种量词绑定,例如
lemma "ALL foo. (if foo then a ~= a else b ~= b) ==> False"
或者通过嵌套假设中的元级通用量词,例如
lemma "True ==> (!!foo. (if foo then a ~= a else b ~= b)) ==> False"
案例
和案例
均不适用
注意:另请参见案例
和案例
一致性规则之间的(轻微)差异
正如在其他答案中已经指出的那样,if\u weak\u cong
同余规则阻止简化程序简化if语句的分支。在这个答案中,我想详细介绍一下简化器对同余规则的使用
有关更多信息,请参见中关于简化器的章节(特别是第9.3.2节)
同余规则控制简化器如何降为术语。它们可以用来限制重写并提供额外的假设。默认情况下,如果简化程序遇到函数应用程序s t
,它将下降到s
和t
,将它们重写为s'
和t'
,然后再尝试重写生成的术语s't'
对于每个常量(或变量)c,可以注册一个同余规则。默认情况下,规则if\u-weak\u-cong
注册为常量if
(这是if…then…else…
语法的基础):
这是这样写的:“如果你遇到一个术语If?b那么?x else?y
,b
可以简化为?c
,然后将If?b那么?x else?y
重写为If?c那么?x else?y
”。由于一致性规则取代了默认策略,因此禁止对?x
和?y
进行任何重写
强同余规则if_cong
是if_cong
的另一种选择:
⟦ ?b = ?c; (?c ⟹ ?x = ?u); (¬ ?c ⟹ ?y = ?v) ⟧
⟹ (if ?b then ?x else ?y) = (if ?c then ?u else ?v)
注意两个假设(?c⟹ ?x=?u)
和(?-c⟹ ?y=?v)
:它们告诉简化程序,在简化if的左(或右)分支时,可能会假定条件成立(或不成立)
作为一个例子,考虑简化器在目标
上的行为。
if foo ∨ False then ¬foo ∨ False else foo ⟹ False
假设我们对foo
一无所知。那么
apply simp
:使用规则if_weak_cong
,这将简化为
如果是foo那么-foo∨ 假艾尔斯福⟹ False
,仅重写条件
apply(simp-cong-del:if\u-weak\u-cong)
:如果没有任何一致性规则,这将是
简化为
如果是foo,那么-foo,else foo⟹ False
,因为条件和分支被重写
apply(simp-cong:if-cong-del:if-cancel)
:使用规则if-cong
,此目标将
简化为
如果为foo,则为False,否则为False⟹ False
:条件foo∨ False
将被删除
重写为foo
。对于这两个分支,简化器现在重写
foo⟹ 埃福∨ 错误
和-foo⟹ 福∨ False
,这两个值显然都重写为
错
(如果取消,我会删除,这通常会完全解决剩余目标)
拆分规则
除了案例分析和一致性规则之外,还有第三种方法可以通过简化器来解决这个问题:拆分器。拆分器允许简化器自己执行有限形式的案例分析。只有当术语本身无法进一步简化时(拆分案例很容易导致目标爆炸),才可以运行它
引理split\u if\u asm
指示拆分器拆分假设中的if
:
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
by (simp split: split_if_asm)
可以使用split
方法执行单步拆分:
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
apply (split split_if_asm)
apply simp_all
done
请注意,在结论中拆分if
的规则(split_if
)是默认设置的一部分
顺便说一句,每个
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
by (simp split: split_if_asm)
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
apply (split split_if_asm)
apply simp_all
done