End NORM_SUBST_REC.
Fixpoint interp_PElist (l:list R) (lpe:list (PExpr*PExpr)) {struct lpe} : Prop :=
match lpe with
| nil => True
| (me,pe)::lpe =>
match lpe with
| nil => PEeval l me == PEeval l pe
| _ => PEeval l me == PEeval l pe /\ interp_PElist l lpe
end
end.
Fixpoint mon_of_pol (P:Pol) : option (C * Mon) :=
match P with
| Pc c => if (c ?=! cO) then None else Some (c, mon0)
| Pinj j P =>
match mon_of_pol P with
| None => None
| Some (c,m) =>  Some (c, mkZmon j m)
end
| PX P i Q =>
if Peq Q P0 then
match mon_of_pol P with
| None => None
| Some (c,m) => Some (c, mkVmon i m)
end
else None
end.
Fixpoint mk_monpol_list (lpe:list (PExpr * PExpr)) : list (C*Mon*Pol) :=
match lpe with
| nil => nil
| (me,pe)::lpe =>
match mon_of_pol (norm_subst 0 nil me) with
| None => mk_monpol_list lpe
| Some m => (m,norm_subst 0 nil pe):: mk_monpol_list lpe
end
end.

(* Specifications: *)
Lemma mon_of_pol_ok : forall P m, mon_of_pol P = Some m ->
forall l, [fst m] * Mphi l (snd m) == P@l.
Lemma interp_PElist_ok : forall l lpe,
interp_PElist l lpe -> MPcond (mk_monpol_list lpe) l.
Lemma norm_subst_ok : forall n l lpe pe,
interp_PElist l lpe ->
PEeval l pe == (norm_subst n (mk_monpol_list lpe) pe)@l.
Lemma ring_correct : forall n l lpe pe1 pe2,
interp_PElist l lpe ->
(let lmp := mk_monpol_list lpe in
norm_subst n lmp pe1 ?== norm_subst n lmp pe2) = true ->
PEeval l pe1 == PEeval l pe2.