aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--plugins/nsatz/NsatzR.v4
-rw-r--r--plugins/nsatz/Nsatz_domain.v559
-rw-r--r--test-suite/success/Nsatz_domain.v274
3 files changed, 835 insertions, 2 deletions
diff --git a/plugins/nsatz/NsatzR.v b/plugins/nsatz/NsatzR.v
index 5db25599c..004840ab3 100644
--- a/plugins/nsatz/NsatzR.v
+++ b/plugins/nsatz/NsatzR.v
@@ -352,8 +352,8 @@ Ltac nsatzR_gen radicalmax info lparam lvar n RNG lH _rl :=
(*idtac "variables:";idtac fv;*)
let nparam := eval compute in (Z_of_nat (List.length lparam)) in
let fv := parametres_en_tete fv lparam in
- (* idtac "variables:"; idtac fv;
- idtac "nparam:"; idtac nparam;*)
+ idtac "variables:"; idtac fv;
+ (* idtac "nparam:"; idtac nparam;*)
let lpol := list_fold_right
ltac:(fun p l => let p' := mkPol p fv in constr:(p'::l))
(@nil (PExpr Z))
diff --git a/plugins/nsatz/Nsatz_domain.v b/plugins/nsatz/Nsatz_domain.v
new file mode 100644
index 000000000..29479b31a
--- /dev/null
+++ b/plugins/nsatz/Nsatz_domain.v
@@ -0,0 +1,559 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(*
+ Tactic nsatz: proofs of polynomials equalities with variables in R.
+ Uses Hilbert Nullstellensatz and Buchberger algorithm.
+ Thanks to B.Gregoire for the verification of the certicate
+ and L.Thery for help on ring tactic,
+ and to B.Barras for modularization of the ocaml code.
+ Example: see test-suite/success/Nsatz.v
+ L.Pottier, june 2010
+*)
+
+Require Import List.
+Require Import Setoid.
+Require Import BinPos.
+Require Import BinList.
+Require Import Znumtheory.
+Require Import Ring_polynom Ring_tac InitialRing.
+
+Declare ML Module "nsatz_plugin".
+
+
+Class Zero (A : Type) := {zero : A}.
+Notation "0" := zero.
+Class One (A : Type) := {one : A}.
+Notation "1" := one.
+Class Addition (A : Type) := {addition : A -> A -> A}.
+Notation "x + y" := (addition x y).
+Class Multiplication (A : Type) := {multiplication : A -> A -> A}.
+Notation "x * y" := (multiplication x y).
+Class Subtraction (A : Type) := {subtraction : A -> A -> A}.
+Notation "x - y" := (subtraction x y).
+Class Opposite (A : Type) := {opposite : A -> A}.
+Notation "- x" := (opposite x).
+
+Class Ring (R:Type) := {
+ ring0: R; ring1: R;
+ ring_plus: R->R->R; ring_mult: R->R->R;
+ ring_sub: R->R->R; ring_opp: R->R;
+ ring_ring:
+ ring_theory ring0 ring1 ring_plus ring_mult ring_sub
+ ring_opp (@eq R)}.
+
+Class Domain (R : Type) := {
+ domain_ring:> Ring R;
+ domain_axiom_product:
+ forall x y, ring_mult x y = ring0 -> x = ring0 \/ y = ring0;
+ domain_axiom_one_zero: ring1 <> ring0}.
+
+Ltac ring2 := simpl; ring.
+
+Section domain.
+
+Variable R: Type.
+Variable Rd: Domain R.
+Add Ring Rr: (@ring_ring R (@domain_ring R Rd)).
+
+Instance zero_ring : Zero R := {zero := ring0}.
+Instance one_ring : One R := {one := ring1}.
+Instance addition_ring : Addition R := {addition x y := ring_plus x y}.
+Instance multiplication_ring : Multiplication R := {multiplication x y := ring_mult x y}.
+Instance subtraction_ring : Subtraction R := {subtraction x y := ring_sub x y}.
+Instance opposite_ring : Opposite R := {opposite x := ring_opp x}.
+
+Lemma psos_r1b: forall x y:R, x - y = 0 -> x = y.
+intros x y H; replace x with ((x - y) + y);
+ [rewrite H | idtac]; ring2.
+Qed.
+
+Lemma psos_r1: forall x y, x = y -> x - y = 0.
+intros x y H; rewrite H; ring2.
+Qed.
+
+
+Lemma nsatzR_diff: forall x y:R, x<>y -> x - y<>0.
+intros.
+intro; apply H.
+replace x with ((x - y) + y) by ring2.
+rewrite H0; ring2.
+Qed.
+
+(* code de Benjamin *)
+Require Import ZArith.
+
+Definition PolZ := Pol Z.
+Definition PEZ := PExpr Z.
+
+Definition P0Z : PolZ := @P0 Z 0%Z.
+
+Definition PolZadd : PolZ -> PolZ -> PolZ :=
+ @Padd Z 0%Z Zplus Zeq_bool.
+
+Definition PolZmul : PolZ -> PolZ -> PolZ :=
+ @Pmul Z 0%Z 1%Z Zplus Zmult Zeq_bool.
+
+Definition PolZeq := @Peq Z Zeq_bool.
+
+Definition norm :=
+ @norm_aux Z 0%Z 1%Z Zplus Zmult Zminus Zopp Zeq_bool.
+
+Fixpoint mult_l (la : list PEZ) (lp: list PolZ) : PolZ :=
+ match la, lp with
+ | a::la, p::lp => PolZadd (PolZmul (norm a) p) (mult_l la lp)
+ | _, _ => P0Z
+ end.
+
+Fixpoint compute_list (lla: list (list PEZ)) (lp:list PolZ) :=
+ match lla with
+ | List.nil => lp
+ | la::lla => compute_list lla ((mult_l la lp)::lp)
+ end.
+
+Definition check (lpe:list PEZ) (qe:PEZ) (certif: list (list PEZ) * list PEZ) :=
+ let (lla, lq) := certif in
+ let lp := List.map norm lpe in
+ PolZeq (norm qe) (mult_l lq (compute_list lla lp)).
+
+
+(* Correction *)
+Definition PhiR : list R -> PolZ -> R :=
+ (Pphi 0 ring_plus ring_mult (gen_phiZ 0 1 ring_plus ring_mult ring_opp)).
+
+Definition pow (r : R) (n : nat) := pow_N 1 ring_mult r (Nnat.N_of_nat n).
+
+Definition PEevalR : list R -> PEZ -> R :=
+ PEeval 0 ring_plus ring_mult ring_sub ring_opp
+ (gen_phiZ 0 1 ring_plus ring_mult ring_opp)
+ Nnat.nat_of_N pow.
+
+Lemma P0Z_correct : forall l, PhiR l P0Z = 0.
+Proof. trivial. Qed.
+
+Lemma Rext: ring_eq_ext ring_plus ring_mult ring_opp eq.
+apply mk_reqe. intros. rewrite H; rewrite H0; trivial.
+ intros. rewrite H; rewrite H0; trivial.
+intros. rewrite H; trivial. Qed.
+
+Lemma Rset : Setoid_Theory R eq.
+apply Eqsth.
+Qed.
+
+Lemma PolZadd_correct : forall P' P l,
+ PhiR l (PolZadd P P') = ((PhiR l P) + (PhiR l P')).
+Proof.
+ refine (Padd_ok Rset Rext (Rth_ARth Rset Rext (@ring_ring _ (@domain_ring _ Rd)))
+ (gen_phiZ_morph Rset Rext (@ring_ring _ (@domain_ring _ Rd)))).
+Qed.
+
+Lemma PolZmul_correct : forall P P' l,
+ PhiR l (PolZmul P P') = ((PhiR l P) * (PhiR l P')).
+Proof.
+ refine (Pmul_ok Rset Rext (Rth_ARth Rset Rext (@ring_ring _ (@domain_ring _ Rd)))
+ (gen_phiZ_morph Rset Rext (@ring_ring _ (@domain_ring _ Rd)))).
+Qed.
+
+Lemma R_power_theory
+ : power_theory 1 ring_mult eq Nnat.nat_of_N pow.
+apply mkpow_th. unfold pow. intros. rewrite Nnat.N_of_nat_of_N. trivial. Qed.
+
+Lemma norm_correct :
+ forall (l : list R) (pe : PEZ), PEevalR l pe = PhiR l (norm pe).
+Proof.
+ intros;apply (norm_aux_spec Rset Rext (Rth_ARth Rset Rext (@ring_ring _ (@domain_ring _ Rd)))
+ (gen_phiZ_morph Rset Rext (@ring_ring _ (@domain_ring _ Rd))) R_power_theory)
+ with (lmp:= List.nil).
+ compute;trivial.
+Qed.
+
+Lemma PolZeq_correct : forall P P' l,
+ PolZeq P P' = true ->
+ PhiR l P = PhiR l P'.
+Proof.
+ intros;apply
+ (Peq_ok Rset Rext (gen_phiZ_morph Rset Rext (@ring_ring _ (@domain_ring _ Rd))));trivial.
+Qed.
+
+Fixpoint Cond0 (A:Type) (Interp:A->R) (l:list A) : Prop :=
+ match l with
+ | List.nil => True
+ | a::l => Interp a = 0 /\ Cond0 A Interp l
+ end.
+
+Lemma mult_l_correct : forall l la lp,
+ Cond0 PolZ (PhiR l) lp ->
+ PhiR l (mult_l la lp) = 0.
+Proof.
+ induction la;simpl;intros;trivial.
+ destruct lp;trivial.
+ simpl in H;destruct H.
+ rewrite PolZadd_correct, PolZmul_correct, H, IHla;[ring2 | trivial].
+Qed.
+
+Lemma compute_list_correct : forall l lla lp,
+ Cond0 PolZ (PhiR l) lp ->
+ Cond0 PolZ (PhiR l) (compute_list lla lp).
+Proof.
+ induction lla;simpl;intros;trivial.
+ apply IHlla;simpl;split;trivial.
+ apply mult_l_correct;trivial.
+Qed.
+
+Lemma check_correct :
+ forall l lpe qe certif,
+ check lpe qe certif = true ->
+ Cond0 PEZ (PEevalR l) lpe ->
+ PEevalR l qe = 0.
+Proof.
+ unfold check;intros l lpe qe (lla, lq) H2 H1.
+ apply PolZeq_correct with (l:=l) in H2.
+ rewrite norm_correct, H2.
+ apply mult_l_correct.
+ apply compute_list_correct.
+ clear H2 lq lla qe;induction lpe;simpl;trivial.
+ simpl in H1;destruct H1.
+ rewrite <- norm_correct;auto.
+Qed.
+
+(* fin du code de Benjamin *)
+
+Lemma pow_not_zero: forall p n, pow p n = 0 -> p = 0.
+induction n. unfold pow; simpl. intros. absurd (1 = 0).
+simpl. apply domain_axiom_one_zero.
+ trivial. replace (pow p (S n)) with (p * (pow p n)). intros.
+case (@domain_axiom_product _ _ _ _ H). trivial. trivial.
+unfold pow; simpl.
+clear IHn. induction n; try ring2. simpl.
+ rewrite pow_pos_Psucc. trivial. exact Rset.
+ intros. rewrite H; rewrite H0; trivial.
+ intros. ring2. intros. ring2. Qed.
+
+Lemma Rdomain_pow: forall c p r, ~c= 0 -> c * (pow p r)= 0 -> p = ring0.
+intros. case (@domain_axiom_product _ _ _ _ H0). intros; absurd (c = 0); auto.
+intros. apply pow_not_zero with r. trivial. Qed.
+
+Definition R2:= 1 + 1.
+
+Fixpoint IPR p {struct p}: R :=
+ match p with
+ xH => 1
+ | xO xH => 1 + 1
+ | xO p1 => R2 + (IPR p1)
+ | xI xH => 1 + (1 + 1)
+ | xI p1 => 1 + (R2 * (IPR p1))
+ end.
+
+Definition IZR1 z :=
+ match z with Z0 => 0
+ | Zpos p => IPR p
+ | Zneg p => -(IPR p)
+ end.
+
+Fixpoint interpret3 t fv {struct t}: R :=
+ match t with
+ | (PEadd t1 t2) =>
+ let v1 := interpret3 t1 fv in
+ let v2 := interpret3 t2 fv in (v1 + v2)
+ | (PEmul t1 t2) =>
+ let v1 := interpret3 t1 fv in
+ let v2 := interpret3 t2 fv in (v1 * v2)
+ | (PEsub t1 t2) =>
+ let v1 := interpret3 t1 fv in
+ let v2 := interpret3 t2 fv in (v1 - v2)
+ | (PEopp t1) =>
+ let v1 := interpret3 t1 fv in (- v1)
+ | (PEpow t1 t2) =>
+ let v1 := interpret3 t1 fv in pow v1 (Nnat.nat_of_N t2)
+ | (PEc t1) => (IZR1 t1)
+ | (PEX n) => List.nth (pred (nat_of_P n)) fv 0
+ end.
+
+
+End domain.
+
+Ltac equalities_to_goal :=
+ lazymatch goal with
+ | H: (@eq _ ?x 0) |- _ => try revert H
+ | H: (@eq _ 0 ?x) |- _ =>
+ try generalize (sym_equal H); clear H
+ | H: (@eq _ ?x ?y) |- _ =>
+ try generalize (@psos_r1 _ _ _ _ H); clear H
+ end.
+
+Ltac nsatz_domain_begin tacsimpl:=
+ intros;
+ try apply (@psos_r1b _ _);
+ repeat equalities_to_goal;
+ tacsimpl.
+
+Ltac generalise_eq_hyps:=
+ repeat
+ (match goal with
+ |h : (?p = ?q)|- _ => revert h
+ end).
+
+Ltac lpol_goal t :=
+ match t with
+ | ?a = ring0 -> ?b =>
+ let r:= lpol_goal b in
+ constr:(a::r)
+ | ?a = ring0 => constr:(a::nil)
+ end.
+
+(* lp est incluse dans fv. La met en tete. *)
+
+Ltac parametres_en_tete fv lp :=
+ match fv with
+ | (@nil _) => lp
+ | (@cons _ ?x ?fv1) =>
+ let res := AddFvTail x lp in
+ parametres_en_tete fv1 res
+ end.
+
+Ltac append1 a l :=
+ match l with
+ | (@nil _) => constr:(cons a l)
+ | (cons ?x ?l) => let l' := append1 a l in constr:(cons x l')
+ end.
+
+Ltac rev l :=
+ match l with
+ |(@nil _) => l
+ | (cons ?x ?l) => let l' := rev l in append1 x l'
+ end.
+
+Ltac nsatz_call_n info nparam p rr lp kont :=
+ let ll := constr:(PEc info :: PEc nparam :: PEpow p rr :: lp) in
+ nsatz_compute ll;
+ match goal with
+ | |- (?c::PEpow _ ?r::?lq0)::?lci0 = _ -> _ =>
+ intros _;
+ set (lci:=lci0);
+ set (lq:=lq0);
+ kont c rr lq lci
+ end.
+
+Ltac nsatz_call radicalmax info nparam p lp kont :=
+ let rec try_n n :=
+ lazymatch n with
+ | 0%N => fail
+ | _ =>
+(* idtac "Trying power: " n;*)
+ (let r := eval compute in (Nminus radicalmax (Npred n)) in
+ nsatz_call_n info nparam p r lp kont) ||
+ let n' := eval compute in (Npred n) in try_n n'
+ end in
+ try_n radicalmax.
+
+
+Set Implicit Arguments.
+Class Cclosed_seq T (l:list T) := {}.
+Instance Iclosed_nil T : Cclosed_seq (T:=T) nil.
+Instance Iclosed_cons T t l `{Cclosed_seq (T:=T) l} : Cclosed_seq (T:=T) (t::l).
+
+Class Cfind_at (R:Type) (b:R) (l:list R) (i:nat) := {}.
+Instance Ifind0 (R:Type) (b:R) l: Cfind_at b (b::l) 0.
+Instance IfindS (R:Type) (b2 b1:R) l i `{Cfind_at R b1 l i} : Cfind_at b1 (b2::l) (S i) | 1.
+Definition Ifind0' := Ifind0.
+Definition IfindS' := IfindS.
+
+Definition li_find_at (R:Type) (b:R) l i `{Cfind_at R b l i} {H:Cclosed_seq (T:=R) l} := (l,i).
+
+Class Creify (R:Type) (e:PExpr Z) (l:list R) (b:R) := {}.
+Instance Ireify_zero (R:Type) (Rd:Domain R) l : Creify (PEc 0%Z) l ring0.
+Instance Ireify_one (R:Type) (Rd:Domain R) l : Creify (PEc 1%Z) l ring1.
+Instance Ireify_plus (R:Type) (Rd:Domain R) e1 l b1 e2 b2 `{Creify R e1 l b1} `{Creify R e2 l b2}
+ : Creify (PEadd e1 e2) l (ring_plus b1 b2).
+Instance Ireify_mult (R:Type) (Rd:Domain R) e1 l b1 e2 b2 `{Creify R e1 l b1} `{Creify R e2 l b2}
+ : Creify (PEmul e1 e2) l (ring_mult b1 b2).
+Instance Ireify_sub (R:Type) (Rd:Domain R) e1 l b1 e2 b2 `{Creify R e1 l b1} `{Creify R e2 l b2}
+ : Creify (PEsub e1 e2) l (ring_sub b1 b2).
+Instance Ireify_opp (R:Type) (Rd:Domain R) e1 l b1 `{Creify R e1 l b1}
+ : Creify (PEopp e1) l (ring_opp b1).
+Instance Ireify_var (R:Type) b l i `{Cfind_at R b l i}
+ : Creify (PEX _ (P_of_succ_nat i)) l b | 100.
+
+
+Class Creifylist (R:Type) (le:list (PExpr Z)) (l:list R) (lb:list R) := {}.
+Instance Creify_nil (R:Type) l : Creifylist nil l (@nil R).
+Instance Creify_cons (R:Type) e1 l b1 le2 lb2 `{Creify R e1 l b1} `{Creifylist R le2 l lb2}
+ : Creifylist (e1::le2) l (b1::lb2).
+
+Definition li_reifyl (R:Type) le l lb `{Creifylist R le l lb}
+ {H:Cclosed_seq (T:=R) l} := (l,le).
+
+Unset Implicit Arguments.
+
+Ltac lterm_goal g :=
+ match g with
+ ?b1 = ?b2 => constr:(b1::b2::nil)
+ | ?b1 = ?b2 -> ?g => let l := lterm_goal g in constr:(b1::b2::l)
+ end.
+
+Ltac reify_goal l le lb:=
+ match le with
+ nil => idtac
+ | ?e::?le1 =>
+ match lb with
+ ?b::?lb1 =>
+ let x := fresh "B" in
+ set (x:= b) at 1;
+ change x with (@interpret3 _ _ e l);
+ clear x;
+ reify_goal l le1 lb1
+ end
+ end.
+
+Ltac get_lpol g :=
+ match g with
+ (interpret3 _ _ ?p _) = _ => constr:(p::nil)
+ | (interpret3 _ _ ?p _) = _ -> ?g =>
+ let l := get_lpol g in constr:(p::l)
+ end.
+
+Ltac nsatz_domain_generic radicalmax info lparam lvar tacsimpl Rd :=
+ match goal with
+ |- ?g => let lb := lterm_goal g in
+ (*idtac "lb"; idtac lb;*)
+ match eval red in (li_reifyl (lb:=lb)) with
+ | (?fv, ?le) =>
+ let fv := match lvar with
+ (@nil _) => fv
+ | _ => lvar
+ end in
+ (* idtac "variables:";idtac fv;*)
+ let nparam := eval compute in (Z_of_nat (List.length lparam)) in
+ let fv := parametres_en_tete fv lparam in
+ (*idtac "variables:"; idtac fv;
+ idtac "nparam:"; idtac nparam;*)
+ match eval red in (li_reifyl (l:=fv) (lb:=lb)) with
+ | (?fv, ?le) =>
+ idtac "variables:";idtac fv;
+ reify_goal fv le lb;
+ match goal with
+ |- ?g =>
+ let lp := get_lpol g in
+ let lpol := eval compute in (List.rev lp) in
+ (*idtac "polynomes:"; idtac lpol;*)
+ tacsimpl; intros;
+
+ let SplitPolyList kont :=
+ match lpol with
+ | ?p2::?lp2 => kont p2 lp2
+ | _ => idtac "polynomial not in the ideal"
+ end in
+ tacsimpl;
+ SplitPolyList ltac:(fun p lp =>
+ set (p21:=p) ;
+ set (lp21:=lp);
+ (*idtac "lp:"; idtac lp; *)
+ nsatz_call radicalmax info nparam p lp ltac:(fun c r lq lci =>
+ set (q := PEmul c (PEpow p21 r));
+ let Hg := fresh "Hg" in
+ assert (Hg:check lp21 q (lci,lq) = true);
+ [ (vm_compute;reflexivity) || idtac "invalid nsatz certificate"
+ | let Hg2 := fresh "Hg" in
+ assert (Hg2: interpret3 _ _ q fv = ring0);
+ [ tacsimpl;
+ apply (@check_correct _ Rd fv lp21 q (lci,lq) Hg);
+ tacsimpl;
+ repeat (split;[assumption|idtac]); exact I
+ | simpl in Hg2; tacsimpl;
+ apply Rdomain_pow with (interpret3 _ _ c fv) (Nnat.nat_of_N r); tacsimpl;
+ [ apply domain_axiom_one_zero || idtac "could not prove discrimination result"
+ | exact Hg2]
+ ]
+ ]
+)
+)
+end end end end .
+
+Ltac nsatz_domainpv radicalmax info lparam lvar tacsimpl rd:=
+ nsatz_domain_begin tacsimpl;
+ nsatz_domain_generic radicalmax info lparam lvar tacsimpl rd.
+
+Ltac nsatz_domain:=
+ intros;
+ match goal with
+ |- (@eq ?r _ _ ) =>
+ let a := constr:(@Ireify_zero _ _ (@nil r)) in
+ match a with
+ (@Ireify_zero _ ?rd _) =>
+ nsatz_domainpv 6%N 1%Z (@nil r) (@nil r) ltac:(simpl) rd
+ end
+ end.
+
+
+
+(* Dans Z *)
+Instance Zri : Ring Z := {
+ ring0 := 0%Z;
+ ring1 := 1%Z;
+ ring_plus := Zplus;
+ ring_mult := Zmult;
+ ring_sub := Zminus;
+ ring_opp := Zopp;
+ ring_ring := Zth}.
+
+Lemma Zaxiom_one_zero: 1%Z <> 0%Z.
+discriminate.
+Qed.
+
+Instance Zdi : Domain Z := {
+ domain_ring := Zri;
+ domain_axiom_product := Zmult_integral;
+ domain_axiom_one_zero := Zaxiom_one_zero}.
+
+
+Ltac simplZ:=
+ simpl;
+replace 0%Z with (@ring0 _ (@domain_ring _ Zdi));[idtac|reflexivity];
+replace 1%Z with (@ring1 _ (@domain_ring _ Zdi));[idtac|reflexivity];
+replace Zplus with (@ring_plus _ (@domain_ring _ Zdi));[idtac|reflexivity];
+replace Zmult with (@ring_mult _ (@domain_ring _ Zdi));[idtac|reflexivity];
+replace Zminus with (@ring_sub _ (@domain_ring _ Zdi));[idtac|reflexivity];
+replace Zopp with (@ring_opp _ (@domain_ring _ Zdi));[idtac|reflexivity].
+
+Ltac nsatz_domainZ:= nsatz_domainpv 6%N 1%Z (@nil Z) (@nil Z) ltac:simplZ Zdi.
+
+
+(* Dans R *)
+Require Import Reals.
+Require Import RealField.
+
+Instance Rri : Ring R := {
+ ring0 := 0%R;
+ ring1 := 1%R;
+ ring_plus := Rplus;
+ ring_mult := Rmult;
+ ring_sub := Rminus;
+ ring_opp := Ropp;
+ ring_ring := RTheory}.
+
+Lemma Raxiom_one_zero: 1%R <> 0%R.
+discrR.
+Qed.
+
+Instance Rdi : Domain R := {
+ domain_ring := Rri;
+ domain_axiom_product := Rmult_integral;
+ domain_axiom_one_zero := Raxiom_one_zero}.
+
+
+Ltac simplR:=
+ simpl;
+replace 0%R with (@ring0 _ (@domain_ring _ Rdi));[idtac|reflexivity];
+replace 1%R with (@ring1 _ (@domain_ring _ Rdi));[idtac|reflexivity];
+replace Rplus with (@ring_plus _ (@domain_ring _ Rdi));[idtac|reflexivity];
+replace Rmult with (@ring_mult _ (@domain_ring _ Rdi));[idtac|reflexivity];
+replace Rminus with (@ring_sub _ (@domain_ring _ Rdi));[idtac|reflexivity];
+replace Ropp with (@ring_opp _ (@domain_ring _ Rdi));[idtac|reflexivity].
+
+Ltac nsatz_domainR:= nsatz_domainpv 6%N 1%Z (@List.nil R) (@List.nil R) ltac:simplR Rdi.
+
diff --git a/test-suite/success/Nsatz_domain.v b/test-suite/success/Nsatz_domain.v
new file mode 100644
index 000000000..2fd4091fe
--- /dev/null
+++ b/test-suite/success/Nsatz_domain.v
@@ -0,0 +1,274 @@
+Require Import Nsatz_domain ZArith Reals List Ring_polynom.
+
+Variable A: Type.
+Variable Ad: Domain A.
+
+Add Ring Ar1: (@ring_ring A (@domain_ring _ Ad)).
+
+Instance Ari : Ring A := {
+ ring0 := @ring0 A (@domain_ring _ Ad);
+ ring1 := @ring1 A (@domain_ring _ Ad);
+ ring_plus := @ring_plus A (@domain_ring _ Ad);
+ ring_mult := @ring_mult A (@domain_ring _ Ad);
+ ring_sub := @ring_sub A (@domain_ring _ Ad);
+ ring_opp := @ring_opp A (@domain_ring _ Ad);
+ ring_ring := @ring_ring A (@domain_ring _ Ad)}.
+
+Instance Adi : Domain A := {
+ domain_ring := Ari;
+ domain_axiom_product := @domain_axiom_product A Ad;
+ domain_axiom_one_zero := @domain_axiom_one_zero A Ad}.
+
+Instance zero_ring2 : Zero A := {zero := ring0}.
+Instance one_ring2 : One A := {one := ring1}.
+Instance addition_ring2 : Addition A := {addition x y := ring_plus x y}.
+Instance multiplication_ring2 : Multiplication A := {multiplication x y := ring_mult x y}.
+Instance subtraction_ring2 : Subtraction A := {subtraction x y := ring_sub x y}.
+Instance opposite_ring2 : Opposite A := {opposite x := ring_opp x}.
+
+Goal forall x y:A, x = y -> x+0 = y*1+0.
+nsatz_domain.
+Qed.
+
+Goal forall a b c:A, a = b -> b = c -> c = a.
+nsatz_domain.
+Qed.
+
+Goal forall a b c:A, a = b -> b = c -> a = c.
+nsatz_domain.
+Qed.
+
+Goal forall a b c x:A, a = b -> b = c -> a*a = c*c.
+nsatz_domain.
+Qed.
+
+Goal forall x y:Z, x = y -> (x+0)%Z = (y*1+0)%Z.
+nsatz_domainZ.
+Qed.
+
+Goal forall x y:R, x = y -> (x+0)%R = (y*1+0)%R.
+nsatz_domainR.
+Qed.
+
+Goal forall a b c x:R, a = b -> b = c -> (a*a)%R = (c*c)%R.
+nsatz_domainR.
+Qed.
+
+Section Examples.
+
+Delimit Scope PE_scope with PE.
+Infix "+" := PEadd : PE_scope.
+Infix "*" := PEmul : PE_scope.
+Infix "-" := PEsub : PE_scope.
+Infix "^" := PEpow : PE_scope.
+Notation "[ n ]" := (@PEc Z n) (at level 0).
+
+Open Scope R_scope.
+
+Lemma example1 : forall x y,
+ x+y=0 ->
+ x*y=0 ->
+ x^2=0.
+Proof.
+ nsatz_domainR.
+Qed.
+
+Lemma example2 : forall x, x^2=0 -> x=0.
+Proof.
+ nsatz_domainR.
+Qed.
+
+(*
+Notation X := (PEX Z 3).
+Notation Y := (PEX Z 2).
+Notation Z_ := (PEX Z 1).
+*)
+Lemma example3 : forall x y z,
+ x+y+z=0 ->
+ x*y+x*z+y*z=0->
+ x*y*z=0 -> x^3=0.
+Proof.
+Time nsatz_domainR.
+simpl.
+discrR.
+Qed.
+
+(*
+Notation X := (PEX Z 4).
+Notation Y := (PEX Z 3).
+Notation Z_ := (PEX Z 2).
+Notation U := (PEX Z 1).
+*)
+Lemma example4 : forall x y z u,
+ x+y+z+u=0 ->
+ x*y+x*z+x*u+y*z+y*u+z*u=0->
+ x*y*z+x*y*u+x*z*u+y*z*u=0->
+ x*y*z*u=0 -> x^4=0.
+Proof.
+Time nsatz_domainR.
+Qed.
+
+(*
+Notation x_ := (PEX Z 5).
+Notation y_ := (PEX Z 4).
+Notation z_ := (PEX Z 3).
+Notation u_ := (PEX Z 2).
+Notation v_ := (PEX Z 1).
+Notation "x :: y" := (List.cons x y)
+(at level 60, right associativity, format "'[hv' x :: '/' y ']'").
+Notation "x :: y" := (List.app x y)
+(at level 60, right associativity, format "x :: y").
+*)
+
+Lemma example5 : forall x y z u v,
+ x+y+z+u+v=0 ->
+ x*y+x*z+x*u+x*v+y*z+y*u+y*v+z*u+z*v+u*v=0->
+ x*y*z+x*y*u+x*y*v+x*z*u+x*z*v+x*u*v+y*z*u+y*z*v+y*u*v+z*u*v=0->
+ x*y*z*u+y*z*u*v+z*u*v*x+u*v*x*y+v*x*y*z=0 ->
+ x*y*z*u*v=0 -> x^5=0.
+Proof.
+Time nsatz_domainR.
+Qed.
+
+End Examples.
+
+Section Geometry.
+
+Open Scope R_scope.
+
+Record point:Type:={
+ X:R;
+ Y:R}.
+
+Definition collinear(A B C:point):=
+ (X A - X B)*(Y C - Y B)-(Y A - Y B)*(X C - X B)=0.
+
+Definition parallel (A B C D:point):=
+ ((X A)-(X B))*((Y C)-(Y D))=((Y A)-(Y B))*((X C)-(X D)).
+
+Definition notparallel (A B C D:point)(x:R):=
+ x*(((X A)-(X B))*((Y C)-(Y D))-((Y A)-(Y B))*((X C)-(X D)))=1.
+
+Definition orthogonal (A B C D:point):=
+ ((X A)-(X B))*((X C)-(X D))+((Y A)-(Y B))*((Y C)-(Y D))=0.
+
+Definition equal2(A B:point):=
+ (X A)=(X B) /\ (Y A)=(Y B).
+
+Definition equal3(A B:point):=
+ ((X A)-(X B))^2+((Y A)-(Y B))^2 = 0.
+
+Definition nequal2(A B:point):=
+ (X A)<>(X B) \/ (Y A)<>(Y B).
+
+Definition nequal3(A B:point):=
+ not (((X A)-(X B))^2+((Y A)-(Y B))^2 = 0).
+
+Definition middle(A B I:point):=
+ 2*(X I)=(X A)+(X B) /\ 2*(Y I)=(Y A)+(Y B).
+
+Definition distance2(A B:point):=
+ (X B - X A)^2 + (Y B - Y A)^2.
+
+(* AB = CD *)
+Definition samedistance2(A B C D:point):=
+ (X B - X A)^2 + (Y B - Y A)^2 = (X D - X C)^2 + (Y D - Y C)^2.
+Definition determinant(A O B:point):=
+ (X A - X O)*(Y B - Y O) - (Y A - Y O)*(X B - X O).
+Definition scalarproduct(A O B:point):=
+ (X A - X O)*(X B - X O) + (Y A - Y O)*(Y B - Y O).
+Definition norm2(A O B:point):=
+ ((X A - X O)^2+(Y A - Y O)^2)*((X B - X O)^2+(Y B - Y O)^2).
+
+
+Lemma a1:forall A B C:Prop, ((A\/B)/\(A\/C)) -> (A\/(B/\C)).
+intuition.
+Qed.
+
+Lemma a2:forall A B C:Prop, ((A\/C)/\(B\/C)) -> ((A/\B)\/C).
+intuition.
+Qed.
+
+Lemma a3:forall a b c d:R, (a-b)*(c-d)=0 -> (a=b \/ c=d).
+intros.
+assert ( (a-b = 0) \/ (c-d = 0)).
+apply Rmult_integral.
+trivial.
+destruct H0.
+left; nsatz_domainR.
+right; nsatz_domainR.
+Qed.
+
+Ltac geo_unfold :=
+ unfold collinear; unfold parallel; unfold notparallel; unfold orthogonal;
+ unfold equal2; unfold equal3; unfold nequal2; unfold nequal3;
+ unfold middle; unfold samedistance2;
+ unfold determinant; unfold scalarproduct; unfold norm2; unfold distance2.
+
+Ltac geo_end :=
+ repeat (
+ repeat (match goal with h:_/\_ |- _ => decompose [and] h; clear h end);
+ repeat (apply a1 || apply a2 || apply a3);
+ repeat split).
+
+Ltac geo_rewrite_hyps:=
+ repeat (match goal with
+ | h:X _ = _ |- _ => rewrite h in *; clear h
+ | h:Y _ = _ |- _ => rewrite h in *; clear h
+ end).
+
+Ltac geo_begin:=
+ geo_unfold;
+ intros;
+ geo_rewrite_hyps;
+ geo_end.
+
+(* Examples *)
+
+Lemma Thales: forall O A B C D:point,
+ collinear O A C -> collinear O B D ->
+ parallel A B C D ->
+ (distance2 O B * distance2 O C = distance2 O D * distance2 O A
+ /\ distance2 O B * distance2 C D = distance2 O D * distance2 A B)
+ \/ collinear O A B.
+repeat geo_begin.
+
+Time nsatz_domainR.
+simpl;discrR.
+Time nsatz_domainR.
+simpl;discrR.
+Qed.
+
+Require Import NsatzR.
+
+Lemma hauteurs:forall A B C A1 B1 C1 H:point,
+ collinear B C A1 -> orthogonal A A1 B C ->
+ collinear A C B1 -> orthogonal B B1 A C ->
+ collinear A B C1 -> orthogonal C C1 A B ->
+ collinear A A1 H -> collinear B B1 H ->
+
+ collinear C C1 H
+ \/ collinear A B C.
+
+geo_begin.
+(* Time nsatzRpv 2%N 1%Z (@nil R) (@nil R).*)
+(*Finished transaction in 3. secs (2.363641u,0.s)*)
+(*Time nsatz_domainR. trop long! *)
+(* en fait nsatz_domain ne tient pas encore compte de la liste des variables! ;-) *)
+Time
+ let lv := constr:(Y A1
+ :: X A1
+ :: Y B1
+ :: X B1
+ :: Y A0
+ :: Y B
+ :: X B
+ :: X A0
+ :: X H
+ :: Y C
+ :: Y C1 :: Y H :: X C1 :: X C ::nil) in
+ nsatz_domainpv 2%N 1%Z (@List.nil R) lv ltac:simplR Rdi.
+(* Finished transaction in 6. secs (5.579152u,0.001s)
+Qed.
+
+End Geometry.