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.

(* Specifications: *)
Lemma norm_aux_PEadd pe1 pe2 : norm_aux (PEadd pe1 pe2) = match get_PEopp pe1, get_PEopp pe2 with | Some pe1', _ => (norm_aux pe2) -- (norm_aux pe1') | None, Some pe2' => (norm_aux pe1) -- (norm_aux pe2') | None, None => (norm_aux pe1) ++ (norm_aux pe2) end.
Lemma norm_aux_PEopp pe : match get_PEopp pe with | Some pe' => norm_aux pe = -- (norm_aux pe') | None => True end.
Lemma norm_aux_spec l pe : PEeval l pe == (norm_aux pe)@l.
Lemma norm_subst_spec : forall l pe, MPcond lmp l -> PEeval l pe == (norm_subst pe)@l.