证明有理函数在Coq中单调递减

时间:2019-04-10 01:58:54

标签: coq

我有一个问题,关于证明函数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.

有任何想法吗?

1 个答案:

答案 0 :(得分:3)

根据经验,当要推理的对象是根据数字的前辈递归定义时,归纳证明是合适的。这里没有递归模式,因此归纳几乎没有帮助。我认为按以下步骤进行会更容易:

  1. silly重新定义为

    silly n := if n <= 5 then S n
               else n + 7
    

    (插入强制以使此有效Coq适当。)

  2. 通过分别考虑案例sillyn < 5n = 5来证明n > 5是单调的。