简体   繁体   中英

How to strengthen induction hypothesis in Coq proof?

I'm trying to formalize applicaion of context-free grammars in practice task. I have problems in proving one lemma. I tried to simplify my context to outline the problem, but it is still a bit cumbersome.

So I defined CFG in Chomsky normal form and derivability of list of terminals as follows:

Require Import List.
Import ListNotations.

Inductive ter : Type := T : nat -> ter.
Inductive var : Type := V : nat -> var.
Inductive eps : Type := E : eps.

Inductive rule : Type :=
  | Rt : var -> ter -> rule
  | Rv : var -> var -> var -> rule
  | Re : var -> eps -> rule.

Definition grammar := list rule.

Inductive der_ter_list : grammar -> var -> list ter -> Prop :=
  | Der_eps : forall (g : grammar) (v : var) (e : eps),
      In (Re v e) g -> der_ter_list g v []
  | Der_ter : forall (g : grammar) (v : var) (t : ter),
      In (Rt v t) g -> der_ter_list g v [t]
  | Der_var : forall (g : grammar) (v v1 v2 : var) (tl1 tl2 : list ter),
      In (Rv v v1 v2) g -> der_ter_list g v1 tl1 -> der_ter_list g v2 tl2 ->
        der_ter_list g v (tl1 ++ tl2).

I have objects that store terminal and some additional info, for example:

Inductive obj : Set := Get_obj : nat -> ter -> obj.

And I try to define all possible lists of objects, which are derivable from given nonterminal (with helper functions):

Fixpoint get_all_pairs (l1 l2 : list (list obj)) : list (list obj) := match l1 with
    | [] => []
    | l::t => (map (fun x => l ++ x) l2) ++ get_all_pairs t l2
  end.

Fixpoint getLabels (objs : list obj) : list ter := match objs with
    | [] => []
    | (Get_obj yy ter)::t => ter::(getLabels t)
  end.

Inductive paths : grammar -> var -> list (list obj) -> Prop :=
  | Empty_paths : forall (g : grammar) (v : var) (e : eps),
      In (Re v e) g -> paths g v [[]]
  | One_obj_path : forall (g : grammar) (v : var) (n : nat) (t : ter) (objs : list obj),
      In (Rt v t) g -> In (Get_obj n t) objs -> paths g v [[Get_obj n t]]
  | Combine_paths : forall (g : grammar) (v v1 v2 : var) (l1 l2 : list (list obj)),
      In (Rv v v1 v2) g -> paths g v1 l1 -> paths g v2 l2 -> paths g v (get_all_pairs l1 l2).

(Each constructor of paths actually corresponds to constructor of rule )

And now I'm trying to proof fact about paths by induction, that every element in paths can be derived from nonterminal:

Theorem derives_all_path : forall (g: grammar) (v : var)
  (ll : list (list obj)) (pths : paths g v ll), forall (l : list obj),
        In l ll -> der_ter_list g v (getLabels l).
Proof.
  intros g v ll pt l contains.
  induction pt.

This construction generates 3 subgoals, 1st and 2nd I've proved by applying Der_eps and Der_ter constructors respectively. But context in 3rd subgoal is not relevant to prove my goal, it has:

contains : In l (get_all_pairs l1 l2)
IHpt1 : In l l1 -> der_ter_list g v1 (getLabels l)
IHpt2 : In l l2 -> der_ter_list g v2 (getLabels l)

So contains means that l is concatenation of some elements from l1 and l2 , but premises in IHpt1 and IHpt2 are true iff l2 and l1 has empty lists, which is not true in general, so it is impossible to prove goal with this context.

The problem can be resolved if l in contains , IHpt1 , IHpt2 will be different lists, but unfortunately I don't know how to explain it to Coq. Is it any way somehow change IHpt1 and IHpt2 to prove the goal, or any other way to prove the whole fact?

I tried to look on paths_ind , but it didn't make me happy.

It looks like your induction hypothesis is not strong enough. If you perform induction pt on a more polymorphic goal, you'll get more useful hypotheses not tied to the specific l you started with.

You should try:

intros g v ll pt; induction pt; intros l contains.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM