let rec pred sigma = function
  | Papp(f,ts) -> p_app f (List.map (term sigma) ts)
  | Ptrue -> Ptrue
  | Pfalse -> Pfalse
  | Pif(e,p,q) -> p_if (term sigma e) (pred sigma p) (pred sigma q)
  | Pand(p,q) -> p_and (pred sigma p) (pred sigma q)
  | Por(p,q) -> p_or (pred sigma p) (pred sigma q)
  | Piff(p,q) -> p_iff (pred sigma p) (pred sigma q)
  | Pnot p -> p_not (pred sigma p)
  | Pnamed(a,p) -> p_named a (pred sigma p)
  | Pforall(x,p) -> let x,sigma = fresh sigma x in p_forall x (pred sigma p)
  | Pexists(x,p) -> let x,sigma = fresh sigma x in p_exists x (pred sigma p)
  | Plet(x,v,p) ->
      let v = term sigma v in
      if is_simple v && Wp_parameters.Simpl.get()
      then
        pred (bind x v sigma) p
      else
        let x,sigma = fresh sigma x in
        p_let x v (pred sigma p)
  | Pimplies(p,q) ->
      match def p with
        | Papp(("eq"|"eq_int"|"eq_real"),([Tvar x;e] | [e;Tvar x])) when Wp_parameters.Simpl.get() ->
            let ve = term sigma e in
            if is_simple ve then
              let vx = alpha sigma x in
              let q = pred (bind x ve sigma) q in
              let p = redef p (Papp("eq",[vx;ve])) in
              p_implies p q
            else
              let vx = alpha sigma x in
              let q = pred sigma q in
              let p = redef p (Papp("eq",[vx;ve])) in
              p_implies p q
        | _ ->
            let p = pred sigma p in
            let q = pred sigma q in
            match def p with
              | Papp("eq",([Tvar x;v] | [v;Tvar x]))
                  when is_simple v && Wp_parameters.Simpl.get() ->
                  let q = Fol.pred_replace (fun _ -> None) x v q in
                  p_implies p q
              | _ -> p_implies p q