Load loadpath.
Require MSets.
Require Coq.Structures.Orders.
Require Coq.Structures.OrdersFacts.
Require Recdef.
Require Omega.
Definition list_bound {A: Type} (f: A -> Prop) (l: list A):=
Forall f l /\  NoDup l.
Definition vset := Ensemble var.
Definition expr_bound (n: vset) (e: expr) :=
match e with Nil => True | Var v => n v end.
Definition pure_bound (n: vset) (a : pure_atom) :=
match a with
| Eqv e e' => expr_bound n e /\ expr_bound n e'
end.
Definition space_bound (n: vset) (a: space_atom) :=
match a with
| Next e e' =>  expr_bound n e /\ expr_bound n e'
| Lseg e e' =>  expr_bound n e /\ expr_bound n e'
end.
Definition pures_bound n := list_bound (pure_bound n).
Definition spaces_bound n := list_bound (space_bound n).
Definition pures_bound' n := Forall (pure_bound n).
Definition spaces_bound' n := Forall (space_bound n).
Definition clause_bound' (n: vset)  (cl: clause) :=
match cl with
| PureClause pi pi' _ _ =>  pures_bound' n pi /\ pures_bound' n pi'
| PosSpaceClause pi pi' sigma =>
pures_bound' n pi /\ pures_bound' n pi'/\ spaces_bound' n sigma
| NegSpaceClause pi sigma pi' =>
pures_bound' n pi /\ pures_bound' n pi'/\ spaces_bound' n sigma
end.
Definition clause_bound (n: vset)  (cl: clause) :=
match cl with
| PureClause pi pi' _ _ =>  pures_bound n pi /\ pures_bound n pi'
| PosSpaceClause pi pi' sigma =>
pures_bound n pi /\ pures_bound n pi'/\ spaces_bound n sigma
| NegSpaceClause pi sigma pi' =>
pures_bound n pi /\ pures_bound n pi'/\ spaces_bound n sigma
end.
Definition var_upto (v: var): Ensemble var := fun x => Ile x v.

Lemma S_nat_of_P_id2pos_le:
forall x y, Ile x y -> S (nat_of_P (id2pos x)) <= S (nat_of_P (id2pos y)).