在Coq中n m : nat
与偶数相邻的一种可能方式是从0和2开始以归纳方式定义该关系。
Inductive adj_ev : nat -> nat -> Prop :=
| ae_0 : adj_ev 0 2
| ae_1 : forall ( n m : nat ), adj_ev n m -> adj_ev m ( S ( S m ) )
| ae_2 : forall ( n m : nat ), adj_ev n m -> adj_ev m n.
ae_0
表示0和2是偶数偶数。 ae_1
指出,如果某些n m : nat
与偶数相邻,则m
和m + 2
也是如此。使用这两个构造函数,我们可以覆盖所有相邻的偶数,直到无穷大。可是等等!当且仅当n
时,这适用于m
和n < m
。所以我们需要最后一个构造函数ae_2
来翻转关系中的任何给定数字对。
现在我已经定义了关系,我想对它进行一些健全性检查以确保它有效。例如,我知道1和3不是偶数偶数,我也知道adj_ev 1 3
永远不能从我定义adj_ev
的方式获得。所以我肯定证明 ~ ( adj_ev 1 3 )
,对吧?
Theorem test' : ~ ( adj_ev 1 3 ).
unfold not. intros H.
inversion H. inversion H0.
经过几次反转后,我很快陷入了无限循环。这就像我问Coq,“n
和m
如何相邻甚至?” Coq回答“好吧,也许m
和n
相邻甚至......”然后我问,“m
和n
如何相邻甚至?” Coq说“好吧,也许n
和m
相邻甚至......”无限。
一般问题是,当你有一个归纳定义的对称关系R
时,很容易证明R
保持它确实占有的位置,但很难证明它不存在它没有。在这种情况下,或许有一个比inversion
更好的策略来解除矛盾,但我不确定它可能是什么。
有什么想法吗?
答案 0 :(得分:1)
首先,我尝试了induction
一些额外的方程式,但这还不够。
Goal forall n1 n2, adj_ev n1 n2 -> n1 = 1 -> n2 = 3 -> False.
Proof. induction 1. Abort.
我设法通过首先证明两个相邻的偶数是偶数来证明你的定理。
启用等价关系重写。
Require Import Coq.Setoids.Setoid.
使用firstorder
时关闭校对搜索。只允许简化。
Set Firstorder Depth 0.
创建提示数据库Hints
,以便与auto
,autorewrite
或autounfold
一起使用。
Create HintDb Hints.
常用战术的简写。
Ltac simplify := repeat (firstorder || subst || autorewrite with Hints in *).
Inductive even : nat -> Prop :=
| even_0 : even 0
| even_S : forall n1, even n1 -> even (S (S n1)).
足够简单。
Conjecture C1 : even 0 <-> True.
Conjecture C2 : even 1 <-> False.
Conjecture C3 : forall n1, even (S (S n1)) <-> even n1.
Hint Rewrite C1 C2 C3 : Hints.
Theorem T1 : forall n1 n2, adj_ev n1 n2 -> even n1 /\ even n2.
Proof. induction 1; simplify. Qed.
Goal ~ adj_ev 1 3. Proof. intro H1. apply T1 in H1. simplify. Qed.
你也可以定义
Definition least : (nat -> Prop) -> nat -> Prop := fun p1 n1 => p1 n1 /\ (forall n2, p1 n2 -> n2 >= n1).
Definition greatest : (nat -> Prop) -> nat -> Prop := fun p1 n1 => p1 n1 /\ (forall n2, p1 n2 -> n2 <= n1).
Definition even : nat -> Prop := fun n1 => exists n2, n1 = 2 * n2.
Definition least_greater_even : nat -> nat -> Prop := fun n1 => least (fun n2 => n2 > n1 /\ even n2).
Definition greatest_less_even : nat -> nat -> Prop := fun n1 => greatest (fun n2 => n2 < n1 /\ even n2).
Definition adjacent_even : nat -> nat -> Prop := fun n1 n2 => least_greater_even n1 n2 /\ greatest_less_even n2 n1 \/ greatest_less_even n1 n2 /\ least_greater_even n2 n1.
并从那里开始工作。还有其他方法可以定义谓词。
Inductive adj_ev : nat -> nat -> Prop :=
| adj_ev_0_2 : adj_ev 0 2
| adj_ev_2_0 : adj_ev 2 0
| adj_ev_S_S : forall n1 n2, adj_ev n1 n2 -> adj_ev (S (S n1)) (S (S n2)).
Goal ~ adj_ev 1 3. Proof. inversion 1. Qed.