我为什么要用“我的”呢;数字“自然”;或;数字符号“simps”;当在Isabelle中证明一个简单的可计算的自然等式时
采用阶乘函数的标准定义:我为什么要用“我的”呢;数字“自然”;或;数字符号“simps”;当在Isabelle中证明一个简单的可计算的自然等式时,isabelle,Isabelle,采用阶乘函数的标准定义: primrec factorial :: "nat ⇒ nat" where "factorial 0 = 1" | "factorial (Suc n) = (Suc n) * (factorial n)" 如果我们要求值“factorial 3”,伊莎贝尔可以预料地给我们6。然而,如果我们试图将其作为引理,它将失败: lemma "factorial (3::nat) = (6:
primrec factorial :: "nat ⇒ nat"
where
"factorial 0 = 1"
| "factorial (Suc n) = (Suc n) * (factorial n)"
如果我们要求值“factorial 3”
,伊莎贝尔可以预料地给我们6
。然而,如果我们试图将其作为引理,它将失败:
lemma "factorial (3::nat) = (6::nat)"
by simp
(* Failed to apply initial proof method *)
simp
,auto
,甚至arith
都找不到解决方案。但是,如果我们添加numeric\u nat
或numeric.simps
,simp
可以解决这个问题:
lemma "factorial (3::nat) = (6::nat)"
by (simp add: numeral_nat)
lemma "factorial (3::nat) = (6::nat)"
by (simp add: numeral.simps)
有趣的是,在这两个证明中,Isabelle都给出了警告“忽略重复重写规则”
,这意味着它应该已经知道这些。此外,Isabelle证明“3*2*1=6”
,这让我更加困惑于这些引理是如何被使用的
因此,如果这是一个如此简单且易于计算的等式-如此之多以至于Isabelle可以用
value
命令计算它-而且这些规则显然已经存在,为什么Isabelle不能在没有它们的情况下解出引理呢?numeric\u nat
包含7个引理:
thm numeral_nat
(*
Numeral1 = Suc 0
numeral (num.Bit0 ?n) = Suc (numeral (Num.BitM ?n))
numeral (num.Bit1 ?n) = Suc (numeral (num.Bit0 ?n))
Num.BitM num.One = num.One
Num.BitM (num.Bit0 ?n) = num.Bit1 (Num.BitM ?n)
Num.BitM (num.Bit1 ?n) = num.Bit1 (num.Bit0 ?n)
1 = Suc 0
*)
而simp
投诉了其中的4个:
Ignoring duplicate rewrite rule:
Num.BitM num.One ≡ num.One
Ignoring duplicate rewrite rule:
Num.BitM (num.Bit0 ?n1) ≡ num.Bit1 (Num.BitM ?n1)
Ignoring duplicate rewrite rule:
Num.BitM (num.Bit1 ?n1) ≡ num.Bit1 (num.Bit0 ?n1)
Ignoring duplicate rewrite rule:
1 ≡ Suc 0
因此,有了7-4=3
新的定理。跟踪(参见simp\u trace
)表明numeric\u nat(2,3)
是有用的引理
惯用的方法是(numeric\u eq\u Suc
通常是一个糟糕的simp规则):
您可能想知道为什么从3
扩展到Suc(Suc(Suc 0))
实际上是必要的,因为定义是factorial(Suc n)=……
。伊莎贝尔的答案是:只适用于1
。这对于大多数递归函数来说已经足够了,并且避免了目标的膨胀。试一试
lemma "factorial (6::nat) = A"
apply (simp add: numeral_nat(2,3))
看到一个被放大的进球
现在,value
的工作原理非常不同。它有三种模式:
value
或value[code]
(eval
策略)生成标准ML代码并执行。您信任代码方程式和编译器value[nbe]
(normalization
策略)是通过评估实现的规范化(也使用代码生成)。“需要信任的代码堆栈相当多”()value[simp]
(code\u simp
策略)使用简化器。完全可信即使在最后一种情况下,也会使用特定的参数和定理调用简化器,而不是像您那样使用默认的参数和定理。这就是区别。回答得很好!但是仍然有一个问题:为什么首先需要这些引理呢?。如果
factorial3
最终减少到3*2*1
(对吗?),为什么simp
可以证明3*2*1=6
没有它们,而不是factorial3=6
?定义是factorial(Suc n)=……
。所以问题就变成了:你想什么时候把一个数字转换成Suc(Suc…(0)…)?伊莎贝尔的答案是:只为1。这对于大多数递归函数来说已经足够了,并且避免了目标的膨胀。尝试lemma“factorial(6::nat)=A”apply(simp add:numeric_nat(2,3))
来查看一个放大的目标。这很有意义。。。而且值得回答!把它加进去,我会欣然接受(我会自己添加一个建议的编辑,但不幸的是编辑队列已满)
lemma "factorial (6::nat) = A"
apply (simp add: numeral_nat(2,3))