我有一个问题,关于证明函数nat-> QArith.Q(Coq标准库中的有理数)是单调的(始终不变),这是在Coq中使用理性的练习的一部分。问题是我被困在证明过程的归纳步骤中。假设我定义了一个函数,如下所示。
Definition silly (n:nat) : QArith_base.Q :=
match n with
| 0 => 1#1
| 1 => 2#1
| 2 => 3#1
| 3 => 4#1
| 4 => 5#1
| 5 => 6#1
| S n => Z.of_N (N.of_nat(S n)) + 7#1
end.
N.of_nat是一个定义,它通过正归纳类型(https://coq.inria.fr/library/Coq.NArith.BinNatDef.html)以二进制方式(https://coq.inria.fr/library/Coq.Numbers.BinNums.html#N)将自然数形式化。 Z.of_N从Z库开始构建一个整数,Q的构造函数Qmake将使用该整数来构建有理数。我已经定义了这种方式,因此可以更轻松地定义函数(至少这是我所想的)。
假设我要证明以下内容:
Lemma sillyIsNondecrescent : forall n, Qle (silly n) (silly(S n))
,Q等于或小于布尔值Q。
证明进行得很好,直到我打到(S n)分支为止,这给了我以下子目标:
(silly (S n) <= silly (S (S n)))%Q
没关系,因为我通过归纳证明了,那么证明上下文就是
n : nat
IHn : (silly n <= silly (S n))%Q
______________________________________(1/1)
(silly (S n) <= silly (S (S n)))%Q
然后我继续展开傻的定义。目标展现给:
(match n with
| 0 => 5 # 1
| 1 => 8 # 1
| 2 => 11 # 1
| 3 => 14 # 1
| 4 => 17 # 1
| S (S (S (S (S _)))) => Z.of_N (N.of_nat (S n)) + 16 # 1
end <=
match n with
| 0 => 8 # 1
| 1 => 11 # 1
| 2 => 14 # 1
| 3 => 17 # 1
| S (S (S (S _))) => Z.of_N (N.of_nat (S (S n))) + 16 # 1
end)%Q
然后我对N进行案例分析,直到到达后继分支。现在的证明阶段是
n : nat
IHn : (silly n <= silly (S n))%Q
n0, n1, n2, n3, n4 : nat
______________________________________(1/1)
(Z.of_N (N.of_nat (S (S (S (S (S (S n4))))))) + 16 # 1 <=
Z.of_N (N.of_nat (S (S (S (S (S (S (S n4)))))))) + 16 # 1)%Q
通过展开N.of_nat,目标是
(match N.of_nat (S (S (S (S (S (S n4)))))) with
| 0%N => 0
| N.pos p => Z.pos p
end + 16 # 1 <=
match N.of_nat (S (S (S (S (S (S (S n4))))))) with
| 0%N => 0
| N.pos p => Z.pos p
end + 16 # 1)%Q
这就是我遇到的问题。在这里对n4进行案例分析或破坏n4都不会做,因为它将生成两个目标,每个目标针对nat的每个构造函数(这是那些策略所期望的)。
从这一点上我该如何进行?是否有更漂亮的方法来进行与此类似的证明?我是否以错误的方式定义了功能?
我觉得我缺少一些很简单的东西。任何提示将不胜感激。
预先感谢, 埃里克。
编辑:按照亚瑟的回答,傻被重新定义为
silly (n:nat) : QArith_base.Q :=
if Nat.leb n 5 then Z.of_nat (S n)#1 else Z.of_nat (S n) + 7#1
考虑以下证明方法:
Lemma sillyIsNondecrescent : forall n, Qle (silly n) (silly (S n)).
Proof.
intros. case_eq (Nat.leb n 5).
- intros. unfold silly. rewrite H0. case_eq (Nat.leb (S n) 5).
+ intros.
为我提供了以下上下文:
1 subgoal
n : nat
H0 : (n <=? 5) = true
H1 : (S n <=? 5) = true
______________________________________(1/1)
(Z.of_nat (S n) # 1 <= Z.of_nat (S (S n)) # 1)%Q
可以回溯到与此处介绍的初始情况类似的情况。如果我明确知道“ n”,Coq(显然)将知道如何解决该目标。否则我会被卡住。我正确格式化了引理吗?我正在考虑根据与
相同的库(Q)中定义的“ Qeq_bool”来重写它Definition Qeq_bool x y :=
(Zeq_bool (Qnum x * QDen y) (Qnum y * QDen x))%Z.
有任何想法吗?
答案 0 :(得分:3)
根据经验,当要推理的对象是根据数字的前辈递归定义时,归纳证明是合适的。这里没有递归模式,因此归纳几乎没有帮助。我认为按以下步骤进行会更容易:
将silly
重新定义为
silly n := if n <= 5 then S n
else n + 7
(插入强制以使此有效Coq适当。)
通过分别考虑案例silly
,n < 5
和n = 5
来证明n > 5
是单调的。