File: field_of_fractions.v

package info (click to toggle)
coq-math-classes 9.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 1,120 kB
  • sloc: python: 22; makefile: 21; sh: 2
file content (193 lines) | stat: -rw-r--r-- 6,039 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
From Coq Require Import Ring.
Require Import
  MathClasses.interfaces.abstract_algebra
  MathClasses.theory.rings MathClasses.theory.dec_fields.

Inductive Frac R `{Rap : Equiv R} `{Rzero : Zero R} : Type := frac { num: R; den: R; den_ne_0: den ≠ 0 }.
  (* We used to have [den] and [den_nonzero] bundled, which did work relatively nicely with Program, but the
   extra messyness in proofs etc turned out not to be worth it. *)
Arguments frac {R Rap Rzero} _ _ _.
Arguments num {R Rap Rzero} _.
Arguments den {R Rap Rzero} _.
Arguments den_ne_0 {R Rap Rzero} _ _.

Section contents.
Context `{IntegralDomain R} `{∀ x y, Decision (x = y)}.

Add Ring R: (stdlib_ring_theory R).

Global Instance Frac_equiv : Equiv (Frac R) | 0 := λ x y, num x * den y = num y * den x.

Instance: Setoid (Frac R).
Proof with auto.
  split; red; unfold equiv, Frac_equiv.
    reflexivity.
   intros x y E. now symmetry.
  intros [nx dx] [ny dy] [nz dz] V W. simpl in *.
  apply (left_cancellation_ne_0 (.*.) dy)...
  rewrite 2!associativity.
  rewrite 2!(commutativity dy).
  rewrite V, <- W. ring.
Qed.

Global Instance Frac_dec : ∀ x y: Frac R, Decision (x = y)
  := λ x y, decide_rel (=) (num x * den y) (num y * den x).

(* injection from R *)
Global Program Instance Frac_inject: Cast R (Frac R) := λ r, frac r 1 _.
Next Obligation. exact (is_ne_0 1). Qed.

Instance: Proper ((=) ==> (=)) Frac_inject.
Proof. intros x1 x2 E. unfold equiv, Frac_equiv. simpl. now rewrite E. Qed.

(* Relations, operations and constants *)
Global Program Instance Frac_plus: Plus (Frac R) :=
  λ x y, frac (num x * den y + num y * den x) (den x * den y) _.
Next Obligation. destruct x, y. simpl. now apply mult_ne_0. Qed.

Global Instance Frac_0: Zero (Frac R) := ('0 : Frac R).
Global Instance Frac_1: One (Frac R) := ('1 : Frac R).

Global Instance Frac_negate: Negate (Frac R) := λ x, frac (- num x) (den x) (den_ne_0 x).

Global Program Instance Frac_mult: Mult (Frac R) := λ x y, frac (num x * num y) (den x * den y) _.
Next Obligation. destruct x, y. simpl. now apply mult_ne_0. Qed.

Ltac unfolds := unfold Frac_negate, Frac_plus, equiv, Frac_equiv in *; simpl in *.
Ltac ring_on_ring := repeat intro; unfolds; try ring.

Lemma Frac_nonzero_num x : x ≠ 0 ↔ num x ≠ 0.
Proof.
  split; intros E F; apply E; unfolds.
   rewrite F. ring.
  rewrite right_identity in F.
  rewrite F. apply left_absorb.
Qed.

Instance: Proper ((=) ==> (=) ==> (=)) Frac_plus.
Proof with try ring.
  intros x x' E y y' E'. unfolds.
  transitivity (num x * den x' * den y * den y' + num y * den y' * den x * den x')...
  rewrite E, E'...
Qed.

Instance: Proper ((=) ==> (=)) Frac_negate.
Proof.
  intros x y E. unfolds.
  rewrite <-negate_mult_distr_l, E. ring.
Qed.

Instance: Proper ((=) ==> (=) ==> (=)) Frac_mult.
Proof with try ring.
  intros x y E x0 y0 E'. unfolds.
  transitivity (num x * den y * (num x0 * den y0))...
  rewrite E, E'...
Qed.

Global Instance: Ring (Frac R).
Proof. repeat (split; try apply _); ring_on_ring. Qed.

Global Instance Frac_dec_recip: DecRecip (Frac R) := λ x,
  match decide_rel (=) (num x) 0 with
  | left _ => 0
  | right P => frac (den x) (num x) P
  end.

Instance: Setoid_Morphism Frac_dec_recip.
Proof.
  split; try apply _.
  intros [xn xd Px] [yn yd Py]. unfolds. unfold Frac_dec_recip. simpl.
  case (decide_rel (=) xn 0); case (decide_rel (=) yn 0); intros Ey Ex; simpl.
     reflexivity.
    rewrite Ex. intros E. destruct Ey.
    apply (right_cancellation_ne_0 (.*.) xd); trivial.
    rewrite <-E. ring.
   rewrite Ey. intros E. destruct Ex.
   apply (right_cancellation_ne_0 (.*.) yd); trivial.
   rewrite E. ring.
  symmetry.
  now rewrite (commutativity yd), (commutativity xd).
Qed.

Global Instance: DecField (Frac R).
Proof.
  constructor; try apply _.
    red. unfolds.
    rewrite 2!mult_1_r.
    apply (is_ne_0 1).
   unfold dec_recip, Frac_dec_recip.
   case (decide_rel); simpl; intuition.
  intros [xn xs] Ex.
  unfold dec_recip, Frac_dec_recip.
  simpl. case (decide_rel); simpl.
   intros E. destruct Ex. unfolds. rewrite E. ring.
  intros. ring_on_ring.
Qed.

Lemma Frac_dec_mult_num_den x :
  x = 'num x / 'den x.
Proof.
  unfold dec_recip, Frac_dec_recip.
  simpl. case (decide_rel); simpl; intros E.
   now destruct (den_ne_0 x).
  unfolds. ring.
Qed.

(* A final word about inject *)
Global Instance: SemiRing_Morphism Frac_inject.
Proof.
  repeat (constructor; try apply _); try reflexivity.
   intros x y. change ((x + y) * (1 * 1) = (x * 1 + y * 1) * 1). ring.
  intros x y. change ((x * y) * (1 * 1) = x * y * 1). ring.
Qed.

Global Instance: Injective Frac_inject.
Proof.
  repeat (constructor; try apply _).
  intros x y. unfolds. rewrite 2!mult_1_r. intuition.
Qed.
End contents.

Set Warnings "-unsupported-attributes". (* FIXME: remove when minimal Coq version is enough *)

#[global]
Typeclasses Opaque Frac_equiv.

Set Warnings "+unsupported-attributes".

Section morphisms.
Context `{IntegralDomain R1} `{∀ x y : R1, Decision (x = y)}.
Context `{IntegralDomain R2} `{∀ x y : R2, Decision (x = y)}.
Context `(f : R1 → R2) `{!SemiRing_Morphism f} `{!Injective f}.

Program Definition Frac_lift (x : Frac R1) : Frac R2 := frac (f (num x)) (f (den x)) _.
Next Obligation.
  apply injective_ne_0.
  now apply (den_ne_0 x).
Qed.

Instance: Proper ((=) ==> (=)) Frac_lift.
Proof.
  intros x y E.
  unfold equiv, Frac_equiv, Frac_lift in *. simpl.
  now rewrite <-2!preserves_mult, E.
Qed.

Global Instance: SemiRing_Morphism Frac_lift.
Proof.
  pose proof (_:Ring (Frac R1)).
  repeat (split; try apply _); unfold equiv, Frac_equiv, Frac_lift in *; simpl.
     intros x y. now rewrite preserves_plus, ?preserves_mult.
    now rewrite preserves_0, preserves_1.
   intros x y. now rewrite ?preserves_mult.
  now rewrite preserves_1.
Qed.

Global Instance: Injective Frac_lift.
Proof.
  split; try apply _.
  intros x  y E.
  unfold equiv, Frac_equiv, Frac_lift in *. simpl in *.
  apply (injective f). now rewrite 2!preserves_mult.
Qed.
End morphisms.