Coq 函数值的嵌套归纳不动点证明

Coq 函数值的嵌套归纳不动点证明,coq,theorem-proving,Coq,Theorem Proving,我试图用Coq证明一个归纳原理。由于数据结构的定义,必须通过两个嵌套归纳来说明这一原则。外部感应通过固定点构造完成,内部感应通过原则列表_uind完成。 现在出现的问题是,内部归纳的归纳参数是一个函数的结果,即dfs t Inductive SearchTree (A : Type) : Type := | empty : SearchTree A | leaf : A -> SearchTree A | choice : SearchTree A -> SearchTr

我试图用Coq证明一个归纳原理。由于数据结构的定义,必须通过两个嵌套归纳来说明这一原则。外部感应通过
固定点
构造完成,内部感应通过原则
列表_uind
完成。 现在出现的问题是,内部归纳的归纳参数是一个函数的结果,即
dfs t

Inductive SearchTree (A : Type) : Type :=
  | empty : SearchTree A
  | leaf : A -> SearchTree A
  | choice : SearchTree A -> SearchTree A -> SearchTree A.

Fixpoint dfs (A : Type) (t: SearchTree A) : list A :=
  match t with
  | empty => nil
  | leaf x => cons x nil
  | choice t1 t2 => app (dfs t1) (dfs t2)
  end.
在内部归纳步骤中,我需要能够将外部归纳假设应用于
dfs t
的第一个元素。但是:当对dfs t进行归纳时,这是不可能的,因为它会导致格式错误的递归

在我看来,“正常”方法是对
t
进行归纳和简化,但在
t=choice t1 t2
的情况下,这总是会导致最初的问题,因为
dfs(choice t1 t2)
只会减少到
dfs t1++dfs t2

有人对如何继续进行这个证明有什么建议吗

编辑:虽然显示代码可能有点多,但这里是:


Require Import Setoid.
Require Import Coq.Lists.List.

Set Implicit Arguments.
Set Contextual Implicit.

Section list.
  Section listEquality.

    Variable A : Type.
    Variable eqA : A -> A -> Prop.

    Inductive EqL : list A -> list A -> Prop :=
    | EqL_nil : EqL nil nil
    | EqL_cons : forall (x y : A) (xs ys : list A),
        eqA x y ->
        EqL xs ys ->
        EqL (cons x xs) (cons y ys).

  End listEquality.
End list.

Section SearchTree.

  Inductive SearchTree (A : Type) : Type :=
  | empty : SearchTree A
  | leaf : A -> SearchTree A
  | choice : SearchTree A -> SearchTree A -> SearchTree A.

  Fixpoint dfs (A : Type) (t: SearchTree A) : list A :=
    match t with
    | empty => nil
    | leaf x => cons x nil
    | choice t1 t2 => app (dfs t1) (dfs t2)
    end.

  Section DFSEquality.

    Variable A : Type.
    Variable eqA : relation A.

    Definition EqDFS (t1 t2: SearchTree A) : Prop :=
      EqL eqA (dfs t1) (dfs t2).

  End DFSEquality.
End SearchTree.

Section List.
  Inductive List A :=
  | Nil : List A
  | Cons : SearchTree A -> SearchTree (List A) -> List A.
End List.

Section EqND.
    Variable A : Type.
    Variable eqA : relation A.
    Inductive EqND : List A -> List A -> Prop :=
    | Eq_Nil : EqND Nil Nil
    | Eq_Cons : forall tx ty txs tys,
        EqDFS eqA tx ty ->
        EqDFS EqND txs tys ->
        EqND (Cons tx txs) (Cons ty tys).
End EqND.

Section EqNDInd.
    Variable A : Type.
    Variable eqA : relation A.
    Variable P : List A -> List A -> Prop.
    Hypothesis BC : P Nil Nil.
    Hypothesis ST: forall mx my mxs mys,
        EqDFS eqA mx my
        -> EqDFS (fun xs ys => EqND eqA xs ys /\ P xs ys) mxs mys
        -> P (Cons mx mxs) (Cons my mys).

    Fixpoint IND (xs ys : List A) { struct xs } : EqND eqA xs ys -> P xs ys.
    Proof.
      intro eq.
      destruct xs,ys.
      + exact BC. 
      + inversion eq.
      + inversion eq.
      + inversion eq. subst. apply ST.
        ++ exact H2.
        ++ unfold EqDFS in *.
           generalize dependent (dfs s2).
           induction (dfs s0).
           +++ intros. inversion H4. constructor.
           +++ intros. inversion H4. subst. constructor.
               ++++ split.
                    * exact H1.
                    * apply IND. exact H1. (* Guarded. *)
               ++++ clear IND. firstorder.
     Admitted.
End EqNDInd.


出现问题证明
IND
保护。
注释掉失败。

要使用嵌套递归,您必须使用原始修复构造,例如使用“修复1”策略。归纳原则不会给你正确的递归调用。请注意,反转可能会导致重写,从而使守卫检查器感到困惑


实际上,如果您希望“嵌套”固定点不在原始列表的子项上,而是在[dfs t]上,那么它就不再是结构递归,您需要使用有充分依据的递归来证明递归的合理性。我在玫瑰树上有一个类似的例子,其中使用了有根据的嵌套递归。

您的尝试中有两个问题:

  • 您编写
    IND
    的方式防止递归参数是
    eq:EqND-eqA-xs-ys
    ,而这是自然的

  • 正如@Matthieu Sozeau所说,多重反转引入了噪声

令人惊讶的是,证据很短

以下是我的解决方案:

Fixpoint IND (xs ys : List A) (eq: EqND eqA xs ys) : P xs ys.
Proof.
  destruct eq.
  - assumption.
  - apply ST.
    + assumption.
    + unfold EqDFS in H0 |- *. induction H0.
      * constructor.
      * constructor.
        -- split.
           ++ assumption.
           ++ apply IND. assumption.
        -- assumption.
Qed.

您可能需要使用更一般的归纳原则,例如
forall l,length l