我有以下Isabelle目标:
lemma "⟦ if foo then a ≠ a else b ≠ b ⟧ ⟹ False"
没有任何策略simp
,fast
,clarsimp
,blast
,fastforce
等在目标上取得任何进展,尽管它相当简单。
为什么Isabelle不简化if
构造的主体,以便“a≠a”和“b≠b”成为False
,从而解决目标?
答案 0 :(得分:6)
if_weak_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)
这两个都将解决上述问题。
if_weak_cong
在默认的通配集另一个合理的问题可能是:“为什么if_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_weak_cong
成为默认情况。
答案 1 :(得分:5)
除了案例分析和同余规则之外,还有第三种方法可以使用简化器来解决这个目标:分离器。分离器允许简化器自己执行有限形式的案例分析。只有当该术语不能进一步简化时才会运行(分裂案例很容易导致目标爆炸)。
引理split_if_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
的规则是默认设置的一部分。
BTW,对于每种数据类型t
,数据类型包提供拆分规则t.split
和t.split_asm
,它们为涉及类型{{1}的case
表达式提供案例分析}。
答案 2 :(得分:4)
在包含if _ then _ else _
的证明中取得进展的另一种自然方式是对条件的案例分析,例如,
lemma "(if foo then a ~= a else b ~= b) ==> False"
by (cases foo) simp_all
或者如果foo
不是自由变量,而是由最外层的元级通用量词限定(在apply-scripts中通常就是这种情况):
lemma "!!foo. (if foo then a ~= a else b ~= b) ==> False"
apply (case_tac foo)
apply simp_all
done
不幸的是,如果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"
cases
和case_tac
都不适用。
注意:另请参阅here了解cases
与case_tac
之间的(轻微)差异。
答案 3 :(得分:4)
正如其他答案中已经提到的,if_weak_cong
同余规则阻止简化器简化if语句的分支。在这个答案中,我想详细说明简化器对同余规则的使用。
有关详细信息,另请参阅Isabelle/Isar Reference Manual中有关简化器的章节(特别是第9.3.2节)。
同余规则控制简化器如何降级为术语。它们可用于限制重写并提供其他假设。默认情况下,如果简化器遇到函数应用程序s t
,它将同时下降到s
和t
以将它们重写为s'
和t'
,然后再尝试重写生成的术语s' t'
。
对于每个常量(或变量)c,可以注册单个同余规则。规则if_weak_cong
默认注册为常量If
(基于if ... then ... else ...
语法):
?b = ?c ⟹ (if ?b then ?x else ?y) = (if ?c then ?x else ?y)
如下所示:"如果您遇到术语if ?b then ?x else ?y
且?b
可以简化为?c
,则将if ?b then ?x else ?y
重写为if ?c then ?x else ?y
&#34 ;.由于同余规则替换默认策略,因此禁止重写?x
和?y
。
if_weak_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的左(或右)分支时条件成立(或不成立)。 / p>
例如,考虑简化器在目标上的行为
if foo ∨ False then ¬foo ∨ False else foo ⟹ False
并假设我们对foo
一无所知。然后,
apply simp
:使用规则if_weak_cong
,这将简化为
if foo then ¬ foo ∨ False else foo ⟹ False
,只重写条件apply (simp cong del: if_weak_cong)
:没有任何一致性规则,这将是
简化为
if foo then ¬ foo else foo ⟹ False
,因为条件和分支被重写 apply (simp cong: if_cong del: if_cancel)
:使用规则if_cong
,此目标即可
简化为
if foo then False else False ⟹ False
:条件foo ∨ False
将是
改写为foo
。对于这两个分支,简化器现在重写
foo ⟹ ¬foo ∨ False
和¬foo ⟹ foo ∨ False
,两者都明显改写为
假
(我删除了if_cancel
,这通常会完全解决剩下的目标)