Section NORM_SUBST_REC.
Variable n : nat.
Variable lmp:list (C*Mon*Pol).
Let subst_l P := PNSubstL P lmp n n.
Let Pmul_subst P1 P2 := subst_l (P1 ** P2).
Let Ppow_subst := Ppow_N subst_l.
Fixpoint norm_aux (pe:PExpr) : Pol :=
match pe with
| PEO => Pc cO
| PEI => Pc cI
| PEc c => Pc c
| PEX j => mk_X j
| PEadd (PEopp pe1) pe2 => (norm_aux pe2) -- (norm_aux pe1)
| PEadd pe1 (PEopp pe2) => (norm_aux pe1) -- (norm_aux pe2)
| PEadd pe1 pe2 => (norm_aux pe1) ++ (norm_aux pe2)
| PEsub pe1 pe2 => (norm_aux pe1) -- (norm_aux pe2)
| PEmul pe1 pe2 => (norm_aux pe1) ** (norm_aux pe2)
| PEopp pe1 => -- (norm_aux pe1)
| PEpow pe1 n => Ppow_N (fun p => p) (norm_aux pe1) n
end.
Definition norm_subst pe := subst_l (norm_aux pe).
(** Internally, [norm_aux] is expanded in a large number of cases. To speed-up proofs, we use an alternative definition. *)
Definition get_PEopp pe :=
match pe with
| PEopp pe' => Some pe'
| _ => None
end.
Arguments norm_aux !pe : simpl nomatch.

Lemma norm_subst_spec :
forall l pe, MPcond lmp l ->
PEeval l pe == (norm_subst pe)@l.