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.