Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Import Field. Require Import QArith. Require Import Znumtheory. Require Import Eqdep_dec.
Qc : A canonical representation of rational numbers.
based on the setoid representation Q.
Record Qc : Set := Qcmake { this :> Q ; canon : Qred this = this }. Declare Scope Qc_scope. Delimit Scope Qc_scope with Qc. Bind Scope Qc_scope with Qc. Arguments Qcmake this%Q _. Open Scope Qc_scope.
An alternative statement of Qred q = q via Z.gcd
forall q : Q, Z.gcd (Qnum q) (QDen q) = 1 -> Qred q = qforall q : Q, Z.gcd (Qnum q) (QDen q) = 1 -> Qred q = qa:Zb:positiveH:Z.gcd a (Z.pos b) = 1(let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # ba:Zb:positiveH:fst (Z.ggcd a (Z.pos b)) = 1(let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # ba:Zb:positiveH:fst (Z.ggcd a (Z.pos b)) = 1(let '(g, (aa, bb)) := Z.ggcd a (Z.pos b) in a = g * aa /\ Z.pos b = g * bb) -> (let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # ba:Zb:positiveaa, bb:Za = 1 * aa /\ Z.pos b = 1 * bb -> aa # Z.to_pos bb = a # bnow intros (<-,<-). Qed.a:Zb:positiveaa, bb:Za = aa /\ Z.pos b = bb -> aa # Z.to_pos bb = a # bforall q : Q, Qred q = q -> Z.gcd (Qnum q) (QDen q) = 1forall q : Q, Qred q = q -> Z.gcd (Qnum q) (QDen q) = 1a:Zb:positiveH:(let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # bZ.gcd a (Z.pos b) = 1a:Zb:positiveH:(let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # b0 <= Z.gcd a (Z.pos b) -> (let '(g, (aa, bb)) := Z.ggcd a (Z.pos b) in a = g * aa /\ Z.pos b = g * bb) -> Z.gcd a (Z.pos b) = 1a:Zb:positiveH:(let (r1, r2) := snd (Z.ggcd a (Z.pos b)) in r1 # Z.to_pos r2) = a # b0 <= fst (Z.ggcd a (Z.pos b)) -> (let '(g, (aa, bb)) := Z.ggcd a (Z.pos b) in a = g * aa /\ Z.pos b = g * bb) -> fst (Z.ggcd a (Z.pos b)) = 1a:Zb:positiveg, aa, bb:ZH:aa # Z.to_pos bb = a # b0 <= g -> a = g * aa /\ Z.pos b = g * bb -> g = 1g, aa, bb:Z0 <= g -> aa = g * aa /\ Z.pos (Z.to_pos bb) = g * bb -> g = 1g, aa, bb:ZH:0 <= gH':Z.pos (Z.to_pos bb) = g * bbg = 1g:positiveaa, bb:ZH:0 <= Z.pos gH':Z.pos (Z.to_pos bb) = Z.pos g * bbZ.pos g = 1g:positiveaa:Zb:positiveH:0 <= Z.pos gH':Z.pos b = Z.pos (g * b)Z.pos g = 1g:positiveaa:Zb:positiveH:0 <= Z.pos gH':b = (g * b)%positiveZ.pos g = 1g:positiveaa:Zb:positiveH:0 <= Z.pos gH':b = (g * b)%positiveg = 1%positivenow rewrite Pos.mul_1_l. Qed.g:positiveaa:Zb:positiveH:0 <= Z.pos gH':b = (g * b)%positive(g * b)%positive = (1 * b)%positiveforall q : Q, Qred q = q <-> Z.gcd (Qnum q) (QDen q) = 1forall q : Q, Qred q = q <-> Z.gcd (Qnum q) (QDen q) = 1q:QH:Qred q = qZ.gcd (Qnum q) (QDen q) = 1q:QH:Z.gcd (Qnum q) (QDen q) = 1Qred q = qapply Qred_identity; auto. Qed.q:QH:Z.gcd (Qnum q) (QDen q) = 1Qred q = q
Coercion from Qc to Q and equality
forall q q' : Qc, q == q' -> q = q'forall q q' : Qc, q == q' -> q = q'q:Qhq:Qred q = qq':Qhq':Qred q' = q'H:{| this := q; canon := hq |} == {| this := q'; canon := hq' |}{| this := q; canon := hq |} = {| this := q'; canon := hq' |}q:Qhq:Qred q = qq':Qhq':Qred q' = q'H:q == q'{| this := q; canon := hq |} = {| this := q'; canon := hq' |}q:Qhq:Qred q = qq':Qhq':Qred q' = q'H:q == q'H':Qred q = Qred q'{| this := q; canon := hq |} = {| this := q'; canon := hq' |}q:Qhq:Qred q = qq':Qhq':Qred q' = q'H:q == q'H':q = q'{| this := q; canon := hq |} = {| this := q'; canon := hq' |}q:Qhq:Qred q = qH:q == qhq':Qred q = q{| this := q; canon := hq |} = {| this := q; canon := hq' |}q:Qhq:Qred q = qH:q == qhq':Qred q = qhq = hq'q:Qhq:Qred q = qH:q == qhq':Qred q = qforall x y : Q, x = y \/ x <> yrepeat decide equality. Qed. Hint Resolve Qc_is_canon : core.q:Qhq:Qred q = qH:q == qhq':Qred q = qx, y:Qx = y \/ x <> yforall q q' : Qc, (q : Q) = q' -> q = q'forall q q' : Qc, (q : Q) = q' -> q = q'q, q':QcH:(q : Q) = q'q = q'now rewrite H. Qed.q, q':QcH:(q : Q) = q'q == q'
Q2Qc : a conversion from Q to Qc.
forall q : Q, Qred (Qred q) = Qred qforall q : Q, Qred (Qred q) = Qred qapply Qred_correct. Qed. Definition Q2Qc (q:Q) : Qc := Qcmake (Qred q) (Qred_involutive q). Arguments Q2Qc q%Q.q:QQred q == qq, q':QQ2Qc q = Q2Qc q' <-> q == q'q, q':QQ2Qc q = Q2Qc q' <-> q == q'q, q':QH:Q2Qc q = Q2Qc q'q == q'q, q':QH:q == q'Q2Qc q = Q2Qc q'now injection H as H%Qred_eq_iff.q, q':QH:Q2Qc q = Q2Qc q'q == q'q, q':QH:q == q'Q2Qc q = Q2Qc q'q, q':QH:q == q'Q2Qc q == Q2Qc q'now rewrite H. Qed. Notation " 0 " := (Q2Qc 0) : Qc_scope. Notation " 1 " := (Q2Qc 1) : Qc_scope. Definition Qcle (x y : Qc) := (x <= y)%Q. Definition Qclt (x y : Qc) := (x < y)%Q. Notation Qcgt := (fun x y : Qc => Qlt y x). Notation Qcge := (fun x y : Qc => Qle y x). Infix "<" := Qclt : Qc_scope. Infix "<=" := Qcle : Qc_scope. Infix ">" := Qcgt : Qc_scope. Infix ">=" := Qcge : Qc_scope. Notation "x <= y <= z" := (x<=y/\y<=z) : Qc_scope. Notation "x < y < z" := (x<y/\y<z) : Qc_scope. Definition Qccompare (p q : Qc) := (Qcompare p q). Notation "p ?= q" := (Qccompare p q) : Qc_scope.q, q':QH:q == q'Qred q == Qred q'forall p q : Qc, p = q <-> (p ?= q) = Eqforall p q : Qc, p = q <-> (p ?= q) = Eqforall p q : Qc, p = q <-> (p ?= q)%Q = Eqp, q:Qcp = q <-> p == qnow intros <-. Qed.p, q:Qcp = q -> p == qforall p q : Qc, p < q <-> (p ?= q) = Ltintros; exact (Qlt_alt p q). Qed.forall p q : Qc, p < q <-> (p ?= q) = Ltforall p q : Qc, (fun x0 y0 : Qc => (y0 < x0)%Q) p q <-> (p ?= q) = Gtintros; exact (Qgt_alt p q). Qed.forall p q : Qc, (fun x0 y0 : Qc => (y0 < x0)%Q) p q <-> (p ?= q) = Gtforall p q : Qc, p <= q <-> (p ?= q) <> Gtintros; exact (Qle_alt p q). Qed.forall p q : Qc, p <= q <-> (p ?= q) <> Gtforall p q : Qc, (fun x0 y0 : Qc => (y0 <= x0)%Q) p q <-> (p ?= q) <> Ltintros; exact (Qge_alt p q). Qed.forall p q : Qc, (fun x0 y0 : Qc => (y0 <= x0)%Q) p q <-> (p ?= q) <> Lt
equality on Qc is decidable:
forall x y : Qc, {x = y} + {x <> y}forall x y : Qc, {x = y} + {x <> y}x, y:Qc{x = y} + {x <> y}right; contradict H; subst; auto with qarith. Defined.x, y:QcH:~ x == y{x = y} + {x <> y}
The addition, multiplication and opposite are defined
in the straightforward way:
Definition Qcplus (x y : Qc) := Q2Qc (x+y). Infix "+" := Qcplus : Qc_scope. Definition Qcmult (x y : Qc) := Q2Qc (x*y). Infix "*" := Qcmult : Qc_scope. Definition Qcopp (x : Qc) := Q2Qc (-x). Notation "- x" := (Qcopp x) : Qc_scope. Definition Qcminus (x y : Qc) := x+-y. Infix "-" := Qcminus : Qc_scope. Definition Qcinv (x : Qc) := Q2Qc (/x). Notation "/ x" := (Qcinv x) : Qc_scope. Definition Qcdiv (x y : Qc) := x*/y. Infix "/" := Qcdiv : Qc_scope.
0 and 1 are apart
1 <> 01 <> 0intros H; discriminate H. Qed. Ltac qc := match goal with | q:Qc |- _ => destruct q; qc | _ => apply Qc_is_canon; simpl; rewrite !Qred_correct end. Opaque Qred.{| this := Qred 1; canon := Qred_involutive 1 |} <> {| this := Qred 0; canon := Qred_involutive 0 |}
Addition is associative:
forall x y z : Qc, x + (y + z) = x + y + zintros; qc; apply Qplus_assoc. Qed.forall x y z : Qc, x + (y + z) = x + y + z
0 is a neutral element for addition:
forall x : Qc, 0 + x = xintros; qc; apply Qplus_0_l. Qed.forall x : Qc, 0 + x = xforall x : Qc, x + 0 = xintros; qc; apply Qplus_0_r. Qed.forall x : Qc, x + 0 = x
Commutativity of addition:
forall x y : Qc, x + y = y + xintros; qc; apply Qplus_comm. Qed.forall x y : Qc, x + y = y + x
Properties of Qopp
forall q : Qc, - - q = qintros; qc; apply Qopp_involutive. Qed.forall q : Qc, - - q = qforall q : Qc, q + - q = 0intros; qc; apply Qplus_opp_r. Qed.forall q : Qc, q + - q = 0
Multiplication is associative:
forall n m p : Qc, n * (m * p) = n * m * pintros; qc; apply Qmult_assoc. Qed.forall n m p : Qc, n * (m * p) = n * m * p
0 is absorbing for multiplication:
forall n : Qc, 0 * n = 0intros; qc; split. Qed.forall n : Qc, 0 * n = 0forall n : Qc, n * 0 = 0intros; qc; rewrite Qmult_comm; split. Qed.forall n : Qc, n * 0 = 0
1 is a neutral element for multiplication:
forall n : Qc, 1 * n = nintros; qc; apply Qmult_1_l. Qed.forall n : Qc, 1 * n = nforall n : Qc, n * 1 = nintros; qc; apply Qmult_1_r. Qed.forall n : Qc, n * 1 = n
Commutativity of multiplication
forall x y : Qc, x * y = y * xintros; qc; apply Qmult_comm. Qed.forall x y : Qc, x * y = y * x
Distributivity
forall x y z : Qc, x * (y + z) = x * y + x * zintros; qc; apply Qmult_plus_distr_r. Qed.forall x y z : Qc, x * (y + z) = x * y + x * zforall x y z : Qc, (x + y) * z = x * z + y * zintros; qc; apply Qmult_plus_distr_l. Qed.forall x y z : Qc, (x + y) * z = x * z + y * z
Integrality
forall x y : Qc, x * y = 0 -> x = 0 \/ y = 0forall x y : Qc, x * y = 0 -> x = 0 \/ y = 0x, y:QcH:x * y = 0x = 0 \/ y = 0x, y:QcH:x * y = 0x * y == 0x, y:QcH:Qred (x * y) = Qred 0x * y == 0x, y:QcH:Qred (x * y) = Qred 0Qred (x * y) == 0rewrite H; auto with qarith. Qed.x, y:QcH:Qred (x * y) = Qred 0Qred (x * y) == Qred 0forall x y : Qc, x <> 0 -> x * y = 0 -> y = 0intros; destruct (Qcmult_integral _ _ H0); tauto. Qed.forall x y : Qc, x <> 0 -> x * y = 0 -> y = 0
Inverse and division.
forall x : Qc, x <> 0 -> x * / x = 1intros; qc; apply Qmult_inv_r; auto. Qed.forall x : Qc, x <> 0 -> x * / x = 1forall x : Qc, x <> 0 -> / x * x = 1forall x : Qc, x <> 0 -> / x * x = 1x:QcH:x <> 0/ x * x = 1apply Qcmult_inv_r; auto. Qed.x:QcH:x <> 0x * / x = 1forall p q : Qc, / (p * q) = / p * / qintros; qc; apply Qinv_mult_distr. Qed.forall p q : Qc, / (p * q) = / p * / qforall x y : Qc, y <> 0 -> x * y / y = xforall x y : Qc, y <> 0 -> x * y / y = xforall x y : Qc, y <> 0 -> x * y * / y = xx, y:QcH:y <> 0x * y * / y = xx, y:QcH:y <> 0x * (y * / y) = xapply Qcmult_1_r. Qed.x, y:QcH:y <> 0x * 1 = xforall x y : Qc, y <> 0 -> y * (x / y) = xforall x y : Qc, y <> 0 -> y * (x / y) = xforall x y : Qc, y <> 0 -> y * (x * / y) = xx, y:QcH:y <> 0y * (x * / y) = xx, y:QcH:y <> 0y * x * / y = xx, y:QcH:y <> 0/ y * (y * x) = xx, y:QcH:y <> 0/ y * y * x = xapply Qcmult_1_l. Qed.x, y:QcH:y <> 01 * x = x
Properties of order upon Qc.
forall x : Qc, x <= xunfold Qcle; intros; simpl; apply Qle_refl. Qed.forall x : Qc, x <= xforall x y : Qc, x <= y -> y <= x -> x = yforall x y : Qc, x <= y -> y <= x -> x = yapply Qc_is_canon; apply Qle_antisym; auto. Qed.x, y:QcH:(x <= y)%QH0:(y <= x)%Qx = yforall x y z : Qc, x <= y -> y <= z -> x <= zunfold Qcle; intros; eapply Qle_trans; eauto. Qed.forall x y z : Qc, x <= y -> y <= z -> x <= zforall x y : Qc, x < y -> x <> yforall x y : Qc, x < y -> x <> yx, y:QcH:(x < y)%Qx <> ysubst; auto with qarith. Qed.x, y:QcH:(x < y)%QH0:x = yx == y
Large = strict or equal
forall x y : Qc, x < y -> x <= yunfold Qcle, Qclt; intros; apply Qlt_le_weak; auto. Qed.forall x y : Qc, x < y -> x <= yforall x y z : Qc, x <= y -> y < z -> x < zunfold Qcle, Qclt; intros; eapply Qle_lt_trans; eauto. Qed.forall x y z : Qc, x <= y -> y < z -> x < zforall x y z : Qc, x < y -> y <= z -> x < zunfold Qcle, Qclt; intros; eapply Qlt_le_trans; eauto. Qed.forall x y z : Qc, x < y -> y <= z -> x < zforall x y z : Qc, x < y -> y < z -> x < zunfold Qclt; intros; eapply Qlt_trans; eauto. Qed.forall x y z : Qc, x < y -> y < z -> x < z
x<y iff ~(y≤x)
forall x y : Qc, ~ x < y -> y <= xunfold Qcle, Qclt; intros; apply Qnot_lt_le; auto. Qed.forall x y : Qc, ~ x < y -> y <= xforall x y : Qc, ~ x <= y -> y < xunfold Qcle, Qclt; intros; apply Qnot_le_lt; auto. Qed.forall x y : Qc, ~ x <= y -> y < xforall x y : Qc, x < y -> ~ y <= xunfold Qcle, Qclt; intros; apply Qlt_not_le; auto. Qed.forall x y : Qc, x < y -> ~ y <= xforall x y : Qc, x <= y -> ~ y < xunfold Qcle, Qclt; intros; apply Qle_not_lt; auto. Qed.forall x y : Qc, x <= y -> ~ y < xforall x y : Qc, x <= y -> x < y \/ x = yforall x y : Qc, x <= y -> x < y \/ x = yx, y:QcH:(x <= y)%Q(x < y)%Q \/ x = ynow apply Qc_is_canon. Qed.x, y:QcH:(x <= y)%QH0:x == yx = y
Some decidability results about orders.
forall x y : Qc, {x < y} + {y < x} + {x = y}forall x y : Qc, {x < y} + {y < x} + {x = y}x, y:Qc{(x < y)%Q} + {(y < x)%Q} + {x = y}x, y:QcH:{(x < y)%Q} + {(y < x)%Q}{(x < y)%Q} + {(y < x)%Q} + {x = y}x, y:QcH:x == y{(x < y)%Q} + {(y < x)%Q} + {x = y}right; apply Qc_is_canon; auto. Defined.x, y:QcH:x == y{(x < y)%Q} + {(y < x)%Q} + {x = y}forall x y : Qc, {x < y} + {y <= x}unfold Qclt, Qcle; intros; apply Qlt_le_dec; auto. Defined.forall x y : Qc, {x < y} + {y <= x}
Compatibility of operations with respect to order.
forall p q : Qc, p <= q -> - q <= - pforall p q : Qc, p <= q -> - q <= - pp, q:QcH:(p <= q)%Q(Qred (- q) <= Qred (- p))%Qapply Qopp_le_compat; auto. Qed.p, q:QcH:(p <= q)%Q(- q <= - p)%Qforall p q : Qc, p <= q <-> 0 <= q + - pforall p q : Qc, p <= q <-> 0 <= q + - pp, q:Qc(p <= q)%Q <-> (Qred 0 <= Qred (q + Qred (- p)))%Qapply Qle_minus_iff; auto. Qed.p, q:Qc(p <= q)%Q <-> (0 <= q + - p)%Qforall p q : Qc, p < q <-> 0 < q + - pforall p q : Qc, p < q <-> 0 < q + - pp, q:Qc(p < q)%Q <-> (Qred 0 < Qred (q + Qred (- p)))%Qapply Qlt_minus_iff; auto. Qed.p, q:Qc(p < q)%Q <-> (0 < q + - p)%Qforall x y z t : Qc, x <= y -> z <= t -> x + z <= y + tforall x y z t : Qc, x <= y -> z <= t -> x + z <= y + tx, y, z, t:QcH:(x <= y)%QH0:(z <= t)%Q(Qred (x + z) <= Qred (y + t))%Qapply Qplus_le_compat; auto. Qed.x, y, z, t:QcH:(x <= y)%QH0:(z <= t)%Q(x + z <= y + t)%Qforall x y z : Qc, x <= y -> 0 <= z -> x * z <= y * zforall x y z : Qc, x <= y -> 0 <= z -> x * z <= y * zx, y, z:QcH:(x <= y)%QH0:(Qred 0 <= z)%Q(Qred (x * z) <= Qred (y * z))%Qapply Qmult_le_compat_r; auto. Qed.x, y, z:QcH:(x <= y)%QH0:(Qred 0 <= z)%Q(x * z <= y * z)%Qforall x y z : Qc, 0 < z -> x * z <= y * z -> x <= yforall x y z : Qc, 0 < z -> x * z <= y * z -> x <= yx, y, z:QcH:(Qred 0 < z)%QH0:(Qred (x * z) <= Qred (y * z))%Q(x <= y)%Qeapply Qmult_lt_0_le_reg_r; eauto. Qed.x, y, z:QcH:(0 < z)%QH0:(x * z <= y * z)%Q(x <= y)%Qforall x y z : Qc, 0 < z -> x < y -> x * z < y * zforall x y z : Qc, 0 < z -> x < y -> x * z < y * zx, y, z:QcH:(Qred 0 < z)%QH0:(x < y)%Q(Qred (x * z) < Qred (y * z))%Qeapply Qmult_lt_compat_r; eauto. Qed.x, y, z:QcH:(0 < z)%QH0:(x < y)%Q(x * z < y * z)%Q
Rational to the n-th power
Fixpoint Qcpower (q:Qc)(n:nat) : Qc := match n with | O => 1 | S n => q * (Qcpower q n) end. Notation " q ^ n " := (Qcpower q n) : Qc_scope.forall n : nat, 1 ^ n = 1forall n : nat, 1 ^ n = 1rewrite IHn; auto with qarith. Qed.n:natIHn:1 ^ n = 11 * 1 ^ n = 1forall n : nat, n <> 0%nat -> 0 ^ n = 0forall n : nat, n <> 0%nat -> 0 ^ n = 00%nat <> 0%nat -> 1 = 0n:natS n <> 0%nat -> 0 * 0 ^ n = 0n:natS n <> 0%nat -> 0 * 0 ^ n = 0now apply Qc_is_canon. Qed.n:natH:S n <> 0%nat0 * 0 ^ n = 0forall (p : Qc) (n : nat), 0 <= p -> 0 <= p ^ nforall (p : Qc) (n : nat), 0 <= p -> 0 <= p ^ np:Qc0 <= p -> 0 <= 1p:Qcn:natIHn:0 <= p -> 0 <= p ^ n0 <= p -> 0 <= p * p ^ np:Qcn:natIHn:0 <= p -> 0 <= p ^ n0 <= p -> 0 <= p * p ^ np:Qcn:natIHn:0 <= p -> 0 <= p ^ nH:0 <= p0 <= p * p ^ np:Qcn:natIHn:0 <= p -> 0 <= p ^ nH:0 <= p0 <= 0 * p ^ np:Qcn:natIHn:0 <= p -> 0 <= p ^ nH:0 <= p0 * p ^ n <= p * p ^ napply Qcmult_le_compat_r; auto. Qed.p:Qcn:natIHn:0 <= p -> 0 <= p ^ nH:0 <= p0 * p ^ n <= p * p ^ n
And now everything is easier concerning tactics:
A ring tactic for rational numbers
Definition Qc_eq_bool (x y : Qc) := if Qc_eq_dec x y then true else false.forall x y : Qc, Qc_eq_bool x y = true -> x = yforall x y : Qc, Qc_eq_bool x y = true -> x = yintros _ H; inversion H. Qed.x, y:Qcx <> y -> false = true -> x = yring_theory 0 1 Qcplus Qcmult Qcminus Qcopp eqring_theory 0 1 Qcplus Qcmult Qcminus Qcopp eqforall x : Qc, 0 + x = xforall x y : Qc, x + y = y + xforall x y z : Qc, x + (y + z) = x + y + zforall x : Qc, 1 * x = xforall x y : Qc, x * y = y * xforall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y : Qc, x + y = y + xforall x y z : Qc, x + (y + z) = x + y + zforall x : Qc, 1 * x = xforall x y : Qc, x * y = y * xforall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y z : Qc, x + (y + z) = x + y + zforall x : Qc, 1 * x = xforall x y : Qc, x * y = y * xforall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x : Qc, 1 * x = xforall x y : Qc, x * y = y * xforall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y : Qc, x * y = y * xforall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y z : Qc, x * (y * z) = x * y * zforall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y z : Qc, (x + y) * z = x * z + y * zforall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0forall x y : Qc, x - y = x + - yforall x : Qc, x + - x = 0exact Qcplus_opp_r. Qed.forall x : Qc, x + - x = 0field_theory 0 1 Qcplus Qcmult Qcminus Qcopp Qcdiv Qcinv eqfield_theory 0 1 Qcplus Qcmult Qcminus Qcopp Qcdiv Qcinv eqring_theory 0 1 Qcplus Qcmult Qcminus Qcopp eq1 <> 0forall p q : Qc, p / q = p * / qforall p : Qc, p <> 0 -> / p * p = 11 <> 0forall p q : Qc, p / q = p * / qforall p : Qc, p <> 0 -> / p * p = 1forall p q : Qc, p / q = p * / qforall p : Qc, p <> 0 -> / p * p = 1exact Qcmult_inv_l. Qed. Add Field Qcfield : Qcft.forall p : Qc, p <> 0 -> / p * p = 1
A field tactic for rational numbers
forall x y : Qc, y <> 0 -> x / y * y = xforall x y : Qc, y <> 0 -> x / y * y = xx, y:QcH:y <> 0x / y * y = xauto. Qed.x, y:QcH:y <> 0y <> 0