Coq中可逆列表是回文的证明

Coq中可逆列表是回文的证明,coq,palindrome,theorem-proving,logical-foundations,Coq,Palindrome,Theorem Proving,Logical Foundations,以下是我对回文的归纳定义: Inductive pal { X : Type } : list X -> Prop := | pal0 : pal [] | pal1 : forall ( x : X ), pal [x] | pal2 : forall ( x : X ) ( l : list X ), pal l -> pal ( x :: l ++ [x] ). 我想从软件基础上证明的定理是: 我对证据的非正式概述如下: 假设l0是一个任意列表,使得l0=rev

以下是我对回文的归纳定义:

Inductive pal { X : Type } : list X -> Prop :=
  | pal0 : pal []
  | pal1 : forall ( x : X ), pal [x]
  | pal2 : forall ( x : X ) ( l : list X ), pal l -> pal ( x :: l ++ [x] ).
我想从软件基础上证明的定理是:

我对证据的非正式概述如下:

假设
l0
是一个任意列表,使得
l0=rev l0
。那么,以下三种情况之一必须成立<代码>l0具有:

(a) 零元素,在这种情况下,根据定义它是回文

(b) 一个元素,在这种情况下,根据定义它也是回文

(c) 两个或两个以上的元素,在这种情况下,对于某些元素
x
和一些列表
l1
,l1=rev l1

现在,由于
l1=rev l1
,以下三种情况之一必须适用于

递归案例分析将终止于任何有限列表
l0
,因为分析的列表长度在每次迭代中减少2。如果它终止于任何列表
ln
,则它的所有外部列表(直到
l0
)也都是回文,因为通过在回文的任一端附加两个相同元素构建的列表也是回文


我认为理由是合理的,但我不确定如何将其形式化。它能成为Coq的证据吗?对所使用的策略如何工作的一些解释将特别有用。

这是一个很好的例子,其中“直接”归纳法根本不起作用,因为您不直接在尾部进行递归调用,而是在尾部的部分进行递归调用。在这种情况下,我通常建议用列表的长度来表示引理,而不是列表本身。然后你可以专门化它。这大概是:

Lemma rev_eq_pal_length: forall (X: Type) (n: nat) (l: list X), length l <= n -> l = rev l -> pal l.
Proof.
(* by induction on [n], not [l] *)
Qed.

Theorem rev_eq_pal: forall (X: Type) (l: list X), l = rev l -> pal l.
Proof.
(* apply the previous lemma with n = length l *)
Qed.

你也可以从一种有充分根据的归纳法中推导出你的归纳法原理

Notation " [ ] " := nil : list_scope.
Notation " [ x1 ; .. ; x2 ] " := (cons x1 .. (cons x2 nil) ..) : list_scope.
Open Scope list_scope.

Conjecture C1 : forall t1 f1 p1, (forall x1, (forall x2, f1 x2 < f1 x1 -> p1 x2) -> p1 x1) -> forall x1 : t1, p1 x1.
Conjecture C2 : forall t1 p1, p1 [] -> (forall x1 l1, p1 ([x1] ++ l1)) -> forall l1 : list t1, p1 l1.
Conjecture C3 : forall t1 p1, p1 [] -> (forall x1 l1, p1 (l1 ++ [x1])) -> forall l1 : list t1, p1 l1.
Conjecture C4 : forall t1 (x1 x2 : t1) l1, length l1 < length ([x1] ++ l1 ++ [x2]).

Theorem T1 : forall t1 p1,
  p1 [] ->
  (forall x1, p1 [x1]) ->
  (forall x1 x2 l1, p1 l1 -> p1 ([x1] ++ l1 ++ [x2])) ->
  forall l1 : list t1, p1 l1.
Proof.
intros t1 p1 h1 h2 h3.
induction l1 as [l1 h4] using (C1 (list t1) (@length t1)).
induction l1 as [| x1 l1] using C2.
eapply h1.
induction l1 as [| x2 l1] using C3.
simpl.
eapply h2.
eapply h3.
eapply h4.
eapply C4.
Qed.
符号“[]”:=nil:list\u范围。
符号“[x1;;x2]:=(cons-x1..(cons-x2-nil)…):列出范围。
打开范围列表\u范围。
猜想C1:对于所有t1 f1 p1,(对于所有x1,(对于所有x2,f1 x2p1 x2)->p1 x1)->对于所有x1:t1,p1 x1。
猜想C2:对于所有t1 p1,p1[]->(对于所有x1 l1,p1([x1]++l1))->对于所有l1:列表t1,p1 l1。
猜想C3:对于所有t1 p1,p1[]->(对于所有x1 l1,p1(l1++[x1]))->对于所有l1:列表t1,p1 l1。
猜想C4:对于所有t1(x1x2:t1)l1,长度l1
(对于所有x1,p1[x1])->
(对于所有x1-x2-l1,p1-l1->p1([x1]++l1++[x2]))->
对于所有l1:列表t1、p1和l1。
证明。
简介t1 p1 h1 h2 h3。
使用(C1(列表t1)(@长度t1))将感应l1作为[l1 h4]。
使用C2的感应l1为[| x1 l1]。
EAPPLYH1。
使用C3诱导l1为[| x2 l1]。
简单。
EAPPLYH2。
EAPPLYH3。
EAPPLYH4。
eapply C4。
Qed。
你可以证明猜想
C1
,首先将假设应用于结论,然后对
f1 x1
使用结构归纳法,然后使用有关
l1=[]
为空l1=false->l1=delete\u last l1++[get\u last l1]
(get\u last需要一个默认值)

Lemma tool : forall (X:Type) (l l': list X) (a b: X),                                                                                                         
            a :: l = l' ++ b :: nil -> (a = b /\ l = nil) \/ exists k, l = k ++ b :: nil.

Lemma tool2 : forall (X:Type) (l1 l2 : list X) (a b: X),                                                                                                         
     l1 ++ a :: nil = l2 ++ b :: nil -> a = b /\ l1 = l2.
Notation " [ ] " := nil : list_scope.
Notation " [ x1 ; .. ; x2 ] " := (cons x1 .. (cons x2 nil) ..) : list_scope.
Open Scope list_scope.

Conjecture C1 : forall t1 f1 p1, (forall x1, (forall x2, f1 x2 < f1 x1 -> p1 x2) -> p1 x1) -> forall x1 : t1, p1 x1.
Conjecture C2 : forall t1 p1, p1 [] -> (forall x1 l1, p1 ([x1] ++ l1)) -> forall l1 : list t1, p1 l1.
Conjecture C3 : forall t1 p1, p1 [] -> (forall x1 l1, p1 (l1 ++ [x1])) -> forall l1 : list t1, p1 l1.
Conjecture C4 : forall t1 (x1 x2 : t1) l1, length l1 < length ([x1] ++ l1 ++ [x2]).

Theorem T1 : forall t1 p1,
  p1 [] ->
  (forall x1, p1 [x1]) ->
  (forall x1 x2 l1, p1 l1 -> p1 ([x1] ++ l1 ++ [x2])) ->
  forall l1 : list t1, p1 l1.
Proof.
intros t1 p1 h1 h2 h3.
induction l1 as [l1 h4] using (C1 (list t1) (@length t1)).
induction l1 as [| x1 l1] using C2.
eapply h1.
induction l1 as [| x2 l1] using C3.
simpl.
eapply h2.
eapply h3.
eapply h4.
eapply C4.
Qed.