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_

我有以下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_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