Éliminer le cofix en preuve Coq

15

Tout en essayant de prouver certaines propriétés de base à l'aide de types coinductifs dans Coq, je continue à rencontrer le problème suivant et je ne peux pas le contourner. J'ai distillé le problème dans un simple script Coq comme suit.

Le type d' arbre définit des arbres peut - être infini avec des branches marquées avec des éléments de type A . Une branche ne doit pas être défini pour tous les éléments de A . La valeur Univ est l'arbre infini avec toutes les branches A toujours définies. isUniv teste si un arbre donné est égal à l' Univ . Le lemme affirme que Univ ne fait satisfaire isUniv .

Parameter A : Set.

CoInductive Tree: Set := Node : (A -> option Tree) -> Tree.

Definition derv (a : A) (t: Tree): option Tree :=
  match t with Node f => f a end.

CoFixpoint Univ : Tree := Node (fun _ => Some Univ).

CoInductive isUniv : Tree -> Prop :=
  isuniv : forall (nf : A -> option Tree) (a : A) (t : Tree), 
    nf a = Some t -> 
    isUniv t -> 
    isUniv (Node nf).

Lemma UnivIsUniv : isUniv Univ.
Proof.
  cofix CH.    (* this application of cofix is fine *)
  unfold Univ. 

Admitted.

À ce stade, j'abandonne la preuve. L'objectif actuel est:

CH : isUniv Univ
============================
isUniv (cofix Univ  : Tree := Node (fun _ : A => Some Univ))

Je ne sais pas quelle tactique appliquer pour éliminer le cofix dans le but de produire (Node something) afin que je puisse appliquer isuniv .

Quelqu'un peut-il aider à prouver ce lemme?
Quels sont les moyens standard d'éliminer le cofix dans une telle situation?

Dave Clarke
la source
1
L'étiquette "preuves-interactives" n'est pas adéquate, car elle se réfère généralement aux systèmes de preuves interactives dans leur sens théoriquement complexe. Le terme correct, je suppose, est "preuve de théorème interactif" ou "preuve de théorème".
Iddo Tzameret
Corrigé, en utilisant des "assistants de vérification"
Dave Clarke

Réponses:

6

Vous pouvez éliminer le cofix en utilisant une fonction auxiliaire dont le modèle correspond à Tree.

Definition TT (t:Tree) :=
  match t with
    | Node o => Node o
  end.

Lemma TTid : forall t: Tree, t = TT t.
  intro t.
  destruct t.
  reflexivity.
  Qed.

Lemma UnivIsUniv : isUniv Univ.
Proof.
  cofix.
  rewrite TTid.
  unfold TT.
  unfold Univ.

Vous obtiendrez cet objectif, qui est une étape non déroulée.

  UnivIsUniv : isUniv Univ
  ============================
   isUniv
     (Node
        (fun _ : A =>
         Some (cofix Univ  : Tree := Node (fun _ : A => Some Univ))))

J'ai adapté cette technique de http://adam.chlipala.net/cpdt/html/Coinductive.html

yhirai
la source
Merci pour cela. Je regardais cette page à peu près au même moment où votre réponse est arrivée. C'est fou, mais cela semble fonctionner ... et puis je suis coincé un peu plus loin, mais je vais m'opposer à cela un peu plus longtemps.
Dave Clarke
9
(* I post my answer as a Coq file. In it I show that supercoooldave's
   definition of a universal tree is not what he intended. His isUniv
   means "the tree has an infinite branch". I provide the correct
   definition, show that the universal tree is universal according to
   the new definition, and I provide counter-examples to
   supercooldave's definition. I also point out that the universal
   tree of branching type A has an infinite path iff A is inhabited.
   *)

Set Implicit Arguments.

CoInductive Tree (A : Set): Set := Node : (A -> option (Tree A)) -> Tree A.

Definition child (A : Set) (t : Tree A) (a : A) :=
  match t with
    Node f => f a
  end.

(* We consider two trees, one is the universal tree on A (always
   branches out fully), and the other is a binary tree which always
   branches to one side and not to the other, so it is like an
   infinite path with branches of length 1 shooting off at each node.  *)

CoFixpoint Univ (A : Set) : Tree A := Node (fun _ => Some (Univ A)).

CoFixpoint Thread : Tree (bool) :=
  Node (fun (b : bool) => if b then Some Thread else None).

(* The original definition of supercooldave should be called "has an
   infinite path", so we rename it to "hasInfinitePath". *)
CoInductive hasInfinitePath (A : Set) : Tree A -> Prop :=
  haspath : forall (f : A -> option (Tree A)) (a : A) (t : Tree A),
    f a = Some t ->
    hasInfinitePath t -> 
    hasInfinitePath (Node f).

(* The correct definition of universal tree. *)
CoInductive isUniv (A : Set) : Tree A -> Prop :=
  isuniv : forall (f : A -> option (Tree A)),
    (forall  a, exists t, f a = Some t /\ isUniv t) -> 
    isUniv (Node f).

(* Technicalities that allow us to get coinductive proofs done. *)
Definition TT (A : Set) (t : Tree A) :=
  match t with
    | Node o => Node o
  end.

Lemma TTid (A : Set) : forall t: Tree A, t = TT t.
  intros A t.
  destruct t.
  reflexivity.
  Qed.

(* Thread has an infinite path. *)
Lemma ThreadHasInfinitePath : hasInfinitePath Thread.
Proof.
  cofix H.
  rewrite TTid.
  unfold TT.
  unfold Thread.
  (* there is a path down the "true" branch leading to Thread. *)
  apply haspath with (a := true) (t := Thread).
  auto.
  auto.
Qed.

(* Auxiliary lemma *)
Lemma univChildNotNone (A : Set) (t : Tree A) (a : A):
  isUniv t -> (child t a <> None).
Proof.
  intros A t a [f H].
  destruct (H a) as [u [G _]].
  unfold child.
  rewrite G.
  discriminate.
Qed.

(* Thread is not universal. *)
Lemma ThreadNotUniversal: ~ (isUniv Thread).
Proof.
  unfold not.
  intro H.
  eapply univChildNotNone with (t := Thread) (a := false).
  auto.
  unfold Thread, child.
  auto.
Qed.

(* Now let us show that Univ is universal. *)
Lemma univIsuniv (A : Set): isUniv (Univ A).
Proof.
  intro A.
  cofix H.
  rewrite TTid.
  unfold TT.
  unfold Univ.
  apply isuniv.
  intro a.
  exists (Univ A).
  auto.
Qed.

(* By the way, it need not be the case that a universal tree has
   an infinite path! In fact, the universal tree of branching type
   A has an infinite path iff A is inhabited. *)

Lemma whenUnivHasInfiniteBranch (A : Set):
  hasInfinitePath (Univ A) <-> exists a : A, True.
Proof.
  intro A.
  split.
  intro H.
  destruct H as [f a t _].
  exists a.
  trivial.
  intros [a _].
  cofix H.
  rewrite TTid.
  unfold TT.
  unfold Univ.
  apply haspath with (t := Univ A); auto.
Qed.
Andrej Bauer
la source
Merci pour cette réponse quelque peu embarrassante. J'ai rencontré le problème avec A étant habité, mais j'ai réussi à contourner cela. Étonnamment, l'univers ne s'est pas déroulé.
Dave Clarke
Eh bien, je ne suis pas gêné par ma réponse :-) J'ai pensé que je pourrais aussi bien donner une réponse complète si je donne une réponse.
Andrej Bauer
Votre réponse a été gênante pour moi. Mais certainement très apprécié.
Dave Clarke
Je plaisantais ... De toute façon, il n'y a pas de quoi être gêné. J'ai fait de pires erreurs. De plus, le Web invite les gens à publier avant de réfléchir. J'ai moi-même posté ici une correction erronée de votre définition, mais heureusement, je l'ai remarqué avant vous.
Andrej Bauer