Fixpoint样张,对函数的值进行嵌套归纳

时间:2017-10-09 02:07:48

标签: coq theorem-proving

我试图证明Coq中的归纳原理。由于数据结构的定义,必须通过两个嵌套导入来显示该原理。外部归纳是通过Fixpoint构造完成的,内部归纳是通过原则list_ind完成的。 现在出现的问题是内部归纳的归纳论证是函数的结果,即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.


问题发生在证明INDGuarded.注释失败。

2 个答案:

答案 0 :(得分:2)

要使用嵌套递归,您必须使用"修复1"来使用原始修复构造。例如战术。归纳原则不会给你正确的递归调用。请注意,反转可能会进行重写,使警卫检查员感到困惑。

实际上,如果你想要"嵌套" fixpoint不是在原始列表的子项上,而是在[dfs t]上,那么它不再是结构递归,你需要使用有根据的递归来证明递归。我在玫瑰树上有一个类似的example,其中使用了有根据的嵌套递归。

答案 1 :(得分:2)

您的尝试有两个问题:

  • 您编写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.