Inductive reduce (Q : list (poly A0 eqA ltM)) :
list (Term A n) -> list (Term A n) -> Prop :=
  | reducetop :
      forall (a b : Term A n) (nZb : ~ zeroP (A:=A) A0 eqA (n:=n) b)
        (p q r : list (Term A n)),
      inPolySet (pX b q) Q ->
      divP A A0 eqA multA divA n a b ->
      eqP A eqA n
        (spminusf A A0 A1 eqA invA minusA multA divA eqA_dec n ltM ltM_dec a
           b nZb p q) r -> reduce Q (pX a p) r
  | reduceskip :
      forall (a b : Term A n) (p q : list (Term A n)),
      reduce Q p q ->
      eqTerm (A:=A) eqA (n:=n) a b -> reduce Q (pX a p) (pX b q).Inductive reduce (Q : list (poly A0 eqA ltM)) :
list (Term A n) -> list (Term A n) -> Prop :=
  | reducetop :
      forall (a b : Term A n) (nZb : ~ zeroP (A:=A) A0 eqA (n:=n) b)
        (p q r : list (Term A n)),
      inPolySet (pX b q) Q ->
      divP A A0 eqA multA divA n a b ->
      eqP A eqA n
        (spminusf A A0 A1 eqA invA minusA multA divA eqA_dec n ltM ltM_dec a
           b nZb p q) r -> reduce Q (pX a p) r
  | reduceskip :
      forall (a b : Term A n) (p q : list (Term A n)),
      reduce Q p q ->
      eqTerm (A:=A) eqA (n:=n) a b -> reduce Q (pX a p) (pX b q).Inductive reduce (Q : list (poly A0 eqA ltM)) :
list (Term A n) -> list (Term A n) -> Prop :=
  | reducetop :
      forall (a b : Term A n) (nZb : ~ zeroP (A:=A) A0 eqA (n:=n) b)
        (p q r : list (Term A n)),
      inPolySet (pX b q) Q ->
      divP A A0 eqA multA divA n a b ->
      eqP A eqA n
        (spminusf A A0 A1 eqA invA minusA multA divA eqA_dec n ltM ltM_dec a
           b nZb p q) r -> reduce Q (pX a p) r
  | reduceskip :
      forall (a b : Term A n) (p q : list (Term A n)),
      reduce Q p q ->
      eqTerm (A:=A) eqA (n:=n) a b -> reduce Q (pX a p) (pX b q).

(* Specifications: *)
Lemma pO_reduce : forall (Q : list (poly A0 eqA ltM)) (p : list (Term A n)), ~ reduce Q (pO A n) p.
Theorem reduce_in_pO : forall (Q : list (poly A0 eqA ltM)) (p : list (Term A n)), inPolySet p Q -> reduce Q p (pO A n).
Theorem ltP_reduce : forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), reduce Q p q -> canonical A0 eqA ltM p -> ltP (A:=A) (n:=n) ltM q p.
Theorem canonical_reduce : forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), reduce Q p q -> canonical A0 eqA ltM p -> canonical A0 eqA ltM q.
Theorem reduce_eqp_com : forall (Q : list (poly A0 eqA ltM)) (p q r s : list (Term A n)), reduce Q p q -> canonical A0 eqA ltM p -> eqP A eqA n p r -> eqP A eqA n q s -> reduce Q r s.
Theorem reduce_inv : forall (Q : list (poly A0 eqA ltM)) (a b : Term A n) (p q : list (Term A n)), reduce Q (pX a p) (pX b q) -> eqTerm (A:=A) eqA (n:=n) a b -> canonical A0 eqA ltM (pX a p) -> reduce Q p q.
Theorem reducetop_sp : forall (Q : list (poly A0 eqA ltM)) (a b : Term A n) (nZb : ~ zeroP (A:=A) A0 eqA (n:=n) b) (p q : list (Term A n)), inPolySet (pX b q) Q -> divP A A0 eqA multA divA n a b -> reduce Q (pX a p) (spminusf A A0 A1 eqA invA minusA multA divA eqA_dec n ltM ltM_dec a b nZb p q).
Theorem reduce_inv2 : forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), reduce Q p q -> canonical A0 eqA ltM p -> exists x : list (Term A n), (exists a : Term A n, ~ zeroP (A:=A) A0 eqA (n:=n) a /\ inPolySet x Q /\ canonical A0 eqA ltM x /\ eqP A eqA n q (minuspf A A0 A1 eqA invA minusA multA eqA_dec n ltM ltM_dec p (mults (A:=A) multA (n:=n) a x))).
Theorem mults_eqp_inv : forall (a : Term A n) (p q : list (Term A n)), eqP A eqA n (mults (A:=A) multA (n:=n) a p) (mults (A:=A) multA (n:=n) a q) -> ~ zeroP (A:=A) A0 eqA (n:=n) a -> eqP A eqA n p q.
Theorem reduce_mults_invf : forall (a : Term A n) (nZa : ~ zeroP (A:=A) A0 eqA (n:=n) a), eqT a (T1 A1 n) -> forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), canonical A0 eqA ltM p -> reduce Q (mults (A:=A) multA (n:=n) a p) q -> reduce Q p (mults (A:=A) multA (n:=n) (divTerm (A:=A) (A0:=A0) (eqA:=eqA) divA (n:=n) (T1 A1 n) (b:=a) nZa) q).
Theorem reduce_mults : forall (Q : list (poly A0 eqA ltM)) (a : Term A n) (p q : list (Term A n)), reduce Q p q -> canonical A0 eqA ltM p -> ~ zeroP (A:=A) A0 eqA (n:=n) a -> reduce Q (mults (A:=A) multA (n:=n) a p) (mults (A:=A) multA (n:=n) a q).
Theorem reduce_mults_inv_lem : forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), reduce Q p q -> forall r : list (Term A n), canonical A0 eqA ltM r -> p = mults (A:=A) multA (n:=n) (invTerm (A:=A) invA (n:=n) (T1 A1 n)) r -> reduce Q r (mults (A:=A) multA (n:=n) (invTerm (A:=A) invA (n:=n) (T1 A1 n)) q).
Theorem reduce_mults_invr : forall (Q : list (poly A0 eqA ltM)) (p q : list (Term A n)), reduce Q (mults (A:=A) multA (n:=n) (invTerm (A:=A) invA (n:=n) (T1 A1 n)) p) q -> canonical A0 eqA ltM p -> reduce Q p (mults (A:=A) multA (n:=n) (invTerm (A:=A) invA (n:=n) (T1 A1 n)) q).