|
| 1 | +/- |
| 2 | +Copyright (c) 2023 Chris Hughes. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Chris Hughes |
| 5 | +-/ |
| 6 | + |
| 7 | +import Mathlib.ModelTheory.Syntax |
| 8 | +import Mathlib.ModelTheory.Semantics |
| 9 | +import Mathlib.Algebra.Ring.Equiv |
| 10 | + |
| 11 | +/-! |
| 12 | +
|
| 13 | +# First Order Language of Rings |
| 14 | +
|
| 15 | +This file defines the first order language of rings, as well as defining instance of `Add`, `Mul`, |
| 16 | +etc. on terms in the language. |
| 17 | +
|
| 18 | +## Main Definitions |
| 19 | +
|
| 20 | +* `FirstOrder.Language.ring` : the language of rings, with function symbols `+`, `*`, `-`, `0`, `1` |
| 21 | +* `FirstOrder.Ring.CompatibleRing` : A class stating that a type is a `Language.ring.Structure`, and |
| 22 | +that this structure is the same as the structure given by the classes `Add`, `Mul`, etc. already on |
| 23 | +`R`. |
| 24 | +* `FirstOrder.Ring.compatibleRingOfRing` : Given a type `R` with instances for each of the `Ring` |
| 25 | +operations, make a `compatibleRing` instance. |
| 26 | +
|
| 27 | +## Implementation Notes |
| 28 | +
|
| 29 | +There are implementation difficulties with the model theory of rings caused by the fact that there |
| 30 | +are two different ways to say that `R` is a `Ring`. We can say `Ring R` or |
| 31 | +`Language.ring.Structure R` and `Theory.ring.Model R` (The theory of rings is not implemented yet). |
| 32 | +
|
| 33 | +The recommended way to use this library is to use the hypotheses `CompatibleRing R` and `Ring R` |
| 34 | +on any theorem that requires both a `Ring` instance and a `Language.ring.Structure` instance |
| 35 | +in order to state the theorem. To apply such a theorem to a ring `R` with a `Ring` instance, |
| 36 | +use the tactic `let _ := compatibleRingOfRing R`. To apply the theorem to `K` |
| 37 | +a `Language.ring.Structure K` instance and for example an instance of `Theory.field.Model K`, |
| 38 | +you must add local instances with definitions like `ModelTheory.Field.fieldOfModelField K` and |
| 39 | +`FirstOrder.Ring.compatibleRingOfModelField K`. |
| 40 | +(in `Mathlib/ModelTheory/Algebra/Field/Basic.lean`), depending on the Theory. |
| 41 | +
|
| 42 | +-/ |
| 43 | + |
| 44 | +variable {α : Type*} |
| 45 | + |
| 46 | +namespace FirstOrder |
| 47 | + |
| 48 | +open FirstOrder |
| 49 | + |
| 50 | +/-- The type of Ring functions, to be used in the definition of the language of rings. |
| 51 | +It contains the operations (+,*,-,0,1) -/ |
| 52 | +inductive ringFunc : ℕ → Type |
| 53 | + | add : ringFunc 2 |
| 54 | + | mul : ringFunc 2 |
| 55 | + | neg : ringFunc 1 |
| 56 | + | zero : ringFunc 0 |
| 57 | + | one : ringFunc 0 |
| 58 | + deriving DecidableEq |
| 59 | + |
| 60 | +/-- The language of rings contains the operations (+,*,-,0,1) -/ |
| 61 | +def Language.ring : Language := |
| 62 | + { Functions := ringFunc |
| 63 | + Relations := fun _ => Empty } |
| 64 | + |
| 65 | +namespace Ring |
| 66 | + |
| 67 | +open ringFunc Language |
| 68 | + |
| 69 | +instance (n : ℕ) : DecidableEq (Language.ring.Functions n) := by |
| 70 | + dsimp [Language.ring]; infer_instance |
| 71 | + |
| 72 | +instance (n : ℕ) : DecidableEq (Language.ring.Relations n) := by |
| 73 | + dsimp [Language.ring]; infer_instance |
| 74 | + |
| 75 | +/-- `RingFunc.add`, but with the defeq type `Language.ring.Functions 2` instead |
| 76 | +of `RingFunc 2` -/ |
| 77 | +abbrev addFunc : Language.ring.Functions 2 := add |
| 78 | + |
| 79 | +/-- `RingFunc.mul`, but with the defeq type `Language.ring.Functions 2` instead |
| 80 | +of `RingFunc 2` -/ |
| 81 | +abbrev mulFunc : Language.ring.Functions 2 := mul |
| 82 | + |
| 83 | +/-- `RingFunc.neg`, but with the defeq type `Language.ring.Functions 1` instead |
| 84 | +of `RingFunc 1` -/ |
| 85 | +abbrev negFunc : Language.ring.Functions 1 := neg |
| 86 | + |
| 87 | +/-- `RingFunc.zero`, but with the defeq type `Language.ring.Functions 0` instead |
| 88 | +of `RingFunc 0` -/ |
| 89 | +abbrev zeroFunc : Language.ring.Functions 0 := zero |
| 90 | + |
| 91 | +/-- `RingFunc.one`, but with the defeq type `Language.ring.Functions 0` instead |
| 92 | +of `RingFunc 0` -/ |
| 93 | +abbrev oneFunc : Language.ring.Functions 0 := one |
| 94 | + |
| 95 | +instance (α : Type*) : Zero (Language.ring.Term α) := |
| 96 | +{ zero := Constants.term zeroFunc } |
| 97 | + |
| 98 | +theorem zero_def (α : Type*) : (0 : Language.ring.Term α) = Constants.term zeroFunc := rfl |
| 99 | + |
| 100 | +instance (α : Type*) : One (Language.ring.Term α) := |
| 101 | +{ one := Constants.term oneFunc } |
| 102 | + |
| 103 | +theorem one_def (α : Type*) : (1 : Language.ring.Term α) = Constants.term oneFunc := rfl |
| 104 | + |
| 105 | +instance (α : Type*) : Add (Language.ring.Term α) := |
| 106 | +{ add := addFunc.apply₂ } |
| 107 | + |
| 108 | +theorem add_def (α : Type*) (t₁ t₂ : Language.ring.Term α) : |
| 109 | + t₁ + t₂ = addFunc.apply₂ t₁ t₂ := rfl |
| 110 | + |
| 111 | +instance (α : Type*) : Mul (Language.ring.Term α) := |
| 112 | +{ mul := mulFunc.apply₂ } |
| 113 | + |
| 114 | +theorem mul_def (α : Type*) (t₁ t₂ : Language.ring.Term α) : |
| 115 | + t₁ * t₂ = mulFunc.apply₂ t₁ t₂ := rfl |
| 116 | + |
| 117 | +instance (α : Type*) : Neg (Language.ring.Term α) := |
| 118 | +{ neg := negFunc.apply₁ } |
| 119 | + |
| 120 | +theorem neg_def (α : Type*) (t : Language.ring.Term α) : |
| 121 | + -t = negFunc.apply₁ t := rfl |
| 122 | + |
| 123 | +instance : Fintype Language.ring.Symbols := |
| 124 | + ⟨⟨Multiset.ofList |
| 125 | + [Sum.inl ⟨2, .add⟩, |
| 126 | + Sum.inl ⟨2, .mul⟩, |
| 127 | + Sum.inl ⟨1, .neg⟩, |
| 128 | + Sum.inl ⟨0, .zero⟩, |
| 129 | + Sum.inl ⟨0, .one⟩], by |
| 130 | + dsimp [Language.Symbols]; decide⟩, by |
| 131 | + intro x |
| 132 | + dsimp [Language.Symbols] |
| 133 | + rcases x with ⟨_, f⟩ | ⟨_, f⟩ |
| 134 | + · cases f <;> decide |
| 135 | + · cases f ⟩ |
| 136 | + |
| 137 | +@[simp] |
| 138 | +theorem card_ring : card Language.ring = 5 := by |
| 139 | + have : Fintype.card Language.ring.Symbols = 5 := rfl |
| 140 | + simp [Language.card, this] |
| 141 | + |
| 142 | +open Language ring Structure |
| 143 | + |
| 144 | +/-- A Type `R` is a `CompatibleRing` if it is a structure for the language of rings and this |
| 145 | +structure is the same as the structure already given on `R` by the classes `Add`, `Mul` etc. |
| 146 | +
|
| 147 | +It is recommended to use this type class as a hypothesis to any theorem whose statement |
| 148 | +requires a type to have be both a `Ring` (or `Field` etc.) and a |
| 149 | +`Language.ring.Structure` -/ |
| 150 | +/- This class does not extend `Add` etc, because this way it can be used in |
| 151 | +combination with a `Ring`, or `Field` instance without having multiple different |
| 152 | +`Add` structures on the Type. -/ |
| 153 | +class CompatibleRing (R : Type*) [Add R] [Mul R] [Neg R] [One R] [Zero R] |
| 154 | + extends Language.ring.Structure R where |
| 155 | + /-- Addition in the `Language.ring.Structure` is the same as the addition given by the |
| 156 | + `Add` instance -/ |
| 157 | + ( funMap_add : ∀ x, funMap addFunc x = x 0 + x 1 ) |
| 158 | + /-- Multiplication in the `Language.ring.Structure` is the same as the multiplication given by the |
| 159 | + `Mul` instance -/ |
| 160 | + ( funMap_mul : ∀ x, funMap mulFunc x = x 0 * x 1 ) |
| 161 | + /-- Negation in the `Language.ring.Structure` is the same as the negation given by the |
| 162 | + `Neg` instance -/ |
| 163 | + ( funMap_neg : ∀ x, funMap negFunc x = -x 0 ) |
| 164 | + /-- The constant `0` in the `Language.ring.Structure` is the same as the constant given by the |
| 165 | + `Zero` instance -/ |
| 166 | + ( funMap_zero : ∀ x, funMap (zeroFunc : Language.ring.Constants) x = 0 ) |
| 167 | + /-- The constant `1` in the `Language.ring.Structure` is the same as the constant given by the |
| 168 | + `One` instance -/ |
| 169 | + ( funMap_one : ∀ x, funMap (oneFunc : Language.ring.Constants) x = 1 ) |
| 170 | + |
| 171 | +open CompatibleRing |
| 172 | + |
| 173 | +attribute [simp] funMap_add funMap_mul funMap_neg funMap_zero funMap_one |
| 174 | + |
| 175 | +section |
| 176 | + |
| 177 | +variable {R : Type*} [Add R] [Mul R] [Neg R] [One R] [Zero R] [CompatibleRing R] |
| 178 | + |
| 179 | +@[simp] |
| 180 | +theorem realize_add (x y : ring.Term α) (v : α → R) : |
| 181 | + Term.realize v (x + y) = Term.realize v x + Term.realize v y := by |
| 182 | + simp [add_def, funMap_add] |
| 183 | + |
| 184 | +@[simp] |
| 185 | +theorem realize_mul (x y : ring.Term α) (v : α → R) : |
| 186 | + Term.realize v (x * y) = Term.realize v x * Term.realize v y := by |
| 187 | + simp [mul_def, funMap_mul] |
| 188 | + |
| 189 | +@[simp] |
| 190 | +theorem realize_neg (x : ring.Term α) (v : α → R) : |
| 191 | + Term.realize v (-x) = -Term.realize v x := by |
| 192 | + simp [neg_def, funMap_neg] |
| 193 | + |
| 194 | +@[simp] |
| 195 | +theorem realize_zero (v : α → R) : Term.realize v (0 : ring.Term α) = 0 := by |
| 196 | + simp [zero_def, funMap_zero, constantMap] |
| 197 | + |
| 198 | +@[simp] |
| 199 | +theorem realize_one (v : α → R) : Term.realize v (1 : ring.Term α) = 1 := by |
| 200 | + simp [one_def, funMap_one, constantMap] |
| 201 | + |
| 202 | +end |
| 203 | + |
| 204 | +/-- Given a Type `R` with instances for each of the `Ring` operations, make a |
| 205 | +`Language.ring.Structure R` instance, along with a proof that the operations given |
| 206 | +by the `Language.ring.Structure` are the same as those given by the `Add` or `Mul` etc. |
| 207 | +instances. |
| 208 | +
|
| 209 | +This definition can be used when applying a theorem about the model theory of rings |
| 210 | +to a literal ring `R`, by writing `let _ := compatibleRingOfRing R`. After this, if, |
| 211 | +for example, `R` is a field, then Lean will be able to find the instance for |
| 212 | +`Theory.field.Model R`, and it will be possible to apply theorems about the model theory |
| 213 | +of fields. |
| 214 | +
|
| 215 | +This is a `def` and not an `instance`, because the path |
| 216 | +`Ring` => `Language.ring.Structure` => `Ring` cannot be made to |
| 217 | +commute by definition |
| 218 | +-/ |
| 219 | +def compatibleRingOfRing (R : Type*) [Add R] [Mul R] [Neg R] [One R] [Zero R] : |
| 220 | + CompatibleRing R := |
| 221 | + { funMap := fun {n} f => |
| 222 | + match n, f with |
| 223 | + | _, .add => fun x => x 0 + x 1 |
| 224 | + | _, .mul => fun x => x 0 * x 1 |
| 225 | + | _, .neg => fun x => -x 0 |
| 226 | + | _, .zero => fun _ => 0 |
| 227 | + | _, .one => fun _ => 1 |
| 228 | + RelMap := Empty.elim, |
| 229 | + funMap_add := fun _ => rfl, |
| 230 | + funMap_mul := fun _ => rfl, |
| 231 | + funMap_neg := fun _ => rfl, |
| 232 | + funMap_zero := fun _ => rfl, |
| 233 | + funMap_one := fun _ => rfl } |
| 234 | + |
| 235 | +/-- An isomorphism in the language of rings is a ring isomorphism -/ |
| 236 | +def languageEquivEquivRingEquiv {R S : Type*} |
| 237 | + [NonAssocRing R] [NonAssocRing S] |
| 238 | + [CompatibleRing R] [CompatibleRing S] : |
| 239 | + (Language.ring.Equiv R S) ≃ (R ≃+* S) := |
| 240 | + { toFun := fun f => |
| 241 | + { f with |
| 242 | + map_add' := by |
| 243 | + intro x y |
| 244 | + simpa using f.map_fun addFunc ![x, y] |
| 245 | + map_mul' := by |
| 246 | + intro x y |
| 247 | + simpa using f.map_fun mulFunc ![x, y] } |
| 248 | + invFun := fun f => |
| 249 | + { f with |
| 250 | + map_fun' := fun {n} f => by |
| 251 | + cases f <;> simp |
| 252 | + map_rel' := fun {n} f => by cases f }, |
| 253 | + left_inv := fun f => by ext; rfl |
| 254 | + right_inv := fun f => by ext; rfl } |
| 255 | + |
| 256 | +variable (R : Type*) [Language.ring.Structure R] |
| 257 | + |
| 258 | +/-- A def to put an `Add` instance on a type with a `Language.ring.Structure` instance. |
| 259 | +
|
| 260 | +To be used sparingly, usually only when defining a more useful definition like, |
| 261 | +`[Language.ring.Structure K] -> [Theory.field.Model K] -> Field K` -/ |
| 262 | +@[reducible] def addOfRingStructure : Add R := |
| 263 | + { add := fun x y => funMap addFunc ![x, y] } |
| 264 | + |
| 265 | +/-- A def to put an `Mul` instance on a type with a `Language.ring.Structure` instance. |
| 266 | +
|
| 267 | +To be used sparingly, usually only when defining a more useful definition like, |
| 268 | +`[Language.ring.Structure K] -> [Theory.field.Model K] -> Field K` -/ |
| 269 | +@[reducible] def mulOfRingStructure : Mul R := |
| 270 | + { mul := fun x y => funMap mulFunc ![x, y] } |
| 271 | + |
| 272 | +/-- A def to put an `Neg` instance on a type with a `Language.ring.Structure` instance. |
| 273 | +
|
| 274 | +To be used sparingly, usually only when defining a more useful definition like, |
| 275 | +`[Language.ring.Structure K] -> [Theory.field.Model K] -> Field K` -/ |
| 276 | +@[reducible] def negOfRingStructure : Neg R := |
| 277 | + { neg := fun x => funMap negFunc ![x] } |
| 278 | + |
| 279 | +/-- A def to put an `Zero` instance on a type with a `Language.ring.Structure` instance. |
| 280 | +
|
| 281 | +To be used sparingly, usually only when defining a more useful definition like, |
| 282 | +`[Language.ring.Structure K] -> [Theory.field.Model K] -> Field K` -/ |
| 283 | +@[reducible] def zeroOfRingStructure : Zero R := |
| 284 | + { zero := funMap zeroFunc ![] } |
| 285 | + |
| 286 | +/-- A def to put an `One` instance on a type with a `Language.ring.Structure` instance. |
| 287 | +
|
| 288 | +To be used sparingly, usually only when defining a more useful definition like, |
| 289 | +`[Language.ring.Structure K] -> [Theory.field.Model K] -> Field K` -/ |
| 290 | +@[reducible] def oneOfRingStructure : One R := |
| 291 | + { one := funMap oneFunc ![] } |
| 292 | + |
| 293 | +attribute [local instance] addOfRingStructure mulOfRingStructure negOfRingStructure |
| 294 | + zeroOfRingStructure oneOfRingStructure |
| 295 | + |
| 296 | +/-- |
| 297 | +Given a Type `R` with a `Language.ring.Structure R`, the instance given by |
| 298 | +`addOfRingStructure` etc are compatible with the `Language.ring.Structure` instance on `R`. |
| 299 | +
|
| 300 | +This definition is only to be used when `addOfRingStructure`, `mulOfRingStructure` etc |
| 301 | +are local instances. |
| 302 | +-/ |
| 303 | +@[reducible] def compatibleRingOfRingStructure : CompatibleRing R := |
| 304 | + { funMap_add := by |
| 305 | + simp only [Fin.forall_fin_succ_pi, Fin.cons_zero, Fin.forall_fin_zero_pi]; |
| 306 | + intros; rfl |
| 307 | + funMap_mul := by |
| 308 | + simp only [Fin.forall_fin_succ_pi, Fin.cons_zero, Fin.forall_fin_zero_pi]; |
| 309 | + intros; rfl |
| 310 | + funMap_neg := by |
| 311 | + simp only [Fin.forall_fin_succ_pi, Fin.cons_zero, Fin.forall_fin_zero_pi]; |
| 312 | + intros; rfl |
| 313 | + funMap_zero := by |
| 314 | + simp only [Fin.forall_fin_succ_pi, Fin.cons_zero, Fin.forall_fin_zero_pi]; |
| 315 | + intros; rfl |
| 316 | + funMap_one := by |
| 317 | + simp only [Fin.forall_fin_succ_pi, Fin.cons_zero, Fin.forall_fin_zero_pi]; |
| 318 | + intros; rfl } |
| 319 | + |
| 320 | +end Ring |
| 321 | + |
| 322 | +end FirstOrder |
0 commit comments