1-- Rational operations lifted from signed natural fractions2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Rat.Operations8import Order9import Algebra.Ring.Core1011-- The rational represented by (a-b)/m. The nonzero side condition belongs to12-- the theorems that use this construction; the definition itself is total.13def rationalClass (a b m : Set) : Set:=14 ⟦((a, b), m)⟧[rationalRepresentatives, rationalEquivalent]1516def rationalZero : Rational:= rationalClass(0, 0, 1)17def rationalOne : Rational:= rationalClass(1, 0, 1)1819def rationalClassNeg (a b m : Set) : Set:= rationalClass(b, a, m)2021-- (a-b)/m + (c-d)/n = ((n*a+m*c)-(n*b+m*d))/(m*n).22def rationalRepresentativeSum (a b m c d n : Set) : Set:=23 ((n * a + m * c, n * b + m * d), m * n)2425def rationalClassSum (a b m c d n : Set) : Set:=26 rationalClass(n * a + m * c, n * b + m * d, m * n)2728-- (a-b)(c-d) = (a*c+b*d)-(a*d+b*c).29def rationalRepresentativeMul (a b m c d n : Set) : Set:=30 ((a * c + b * d, a * d + b * c), m * n)3132def rationalClassMul (a b m c d n : Set) : Set:=33 rationalClass(a * c + b * d, a * d + b * c, m * n)3435-- Quotient-level operations are set-theoretic function graphs. Their36-- witnesses retain the representative calculation, while the bounded carrier37-- makes every public input and output a rational number.38def rationalAdd : Set:=39 { p ∈ ((ℚ × ℚ) × ℚ) |40∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧41∃ c, Nat(c) ∧∃ d, Nat(d) ∧∃ n, Nat(n) ∧ n ≠0∧42 p = ((rationalClass(a, b, m), rationalClass(c, d, n)) ↦43 rationalClassSum(a, b, m, c, d, n)) }4445def rationalMul : Set:=46 { p ∈ ((ℚ × ℚ) × ℚ) |47∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧48∃ c, Nat(c) ∧∃ d, Nat(d) ∧∃ n, Nat(n) ∧ n ≠0∧49 p = ((rationalClass(a, b, m), rationalClass(c, d, n)) ↦50 rationalClassMul(a, b, m, c, d, n)) }5152def rationalNeg : Set:=53 { p ∈ (ℚ × ℚ) |54∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧55 p = (rationalClass(a, b, m) ↦ rationalClassNeg(a, b, m)) }5657def rationalAddValue (x y : Rational) : Rational:= rationalAdd((x, y))58def rationalMulValue (x y : Rational) : Rational:= rationalMul((x, y))59def rationalNegValue (x : Rational) : Rational:= rationalNeg(x)6061theorem rationalClass.rational (a b m : Nat)62requires nonzero : m ≠063showsRational(rationalClass(a, b, m))64proof65unfoldRational66unfold ℚ67unfold rationalClass68apply quotient.contains_class69 . exact rationalEquivalent.equivalence70 . have representative := rationalRepresentatives.pair at a, b, m71specialize representative with*{1}72exact representative7374-- On displayed rational classes, strict order is exactly the familiar75-- cross-multiplication inequality. This is the quotient boundary used by76-- arithmetic clients: representative transport stays inside the API.77theorem rationalLess.classes (a b m c d n : Nat)78requires mNonzero : m ≠079requires nNonzero : n ≠080shows relates(rationalLess, rationalClass(a, b, m), rationalClass(c, d, n)) ↔81 n * a + m * d < m * c + n * b82proof83constructor84 . intro less85have leftRational := rationalClass.rational at a, b, m with mNonzero86have rightRational := rationalClass.rational at c, d, n with nNonzero87unfold rationalClass at leftRational88unfold rationalClass at rightRational89unfold rationalClass at less90obtain⟨u, uInLeft, uRepresentative, v, vInRight, vRepresentative, representativeLess⟩:=91 rationalLess.representatives at92 ⟦((a, b), m)⟧[rationalRepresentatives, rationalEquivalent],93 ⟦((c, d), n)⟧[rationalRepresentatives, rationalEquivalent] with94 leftRational, rightRational, less95have leftRepresentative := rationalRepresentatives.pair at a, b, m with mNonzero96have rightRepresentative := rationalRepresentatives.pair at c, d, n with nNonzero97have leftSelf := equivalenceClass.self with rationalEquivalent.equivalence, leftRepresentative98have rightSelf := equivalenceClass.self with rationalEquivalent.equivalence, rightRepresentative99have leftEquivalent :=Rational.members_related at100 ⟦((a, b), m)⟧[rationalRepresentatives, rationalEquivalent],101 u, ((a, b), m) with leftRational, uInLeft, leftSelf102have rightEquivalent :=Rational.members_related at103 ⟦((c, d), n)⟧[rationalRepresentatives, rationalEquivalent],104 v, ((c, d), n) with rightRational, vInRight, rightSelf105have displayedLess := rationalRepresentativeLess.transport with106 uRepresentative, vRepresentative, leftRepresentative, rightRepresentative, leftEquivalent, rightEquivalent, representativeLess107exact rationalRepresentativeLess.pair.forward with mNonzero, nNonzero, displayedLess108 . intro crossLess109unfold rationalClass110exact rationalLess.of_representatives with mNonzero, nNonzero, crossLess111112theoremRational.coordinates (q : Set)113requires rational : Rational(q)114shows∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧115 q = rationalClass(a, b, m)116proof117unfoldRationalat rational118unfold ℚ at rational119have quotientMember := quotient.membership.forward at120 rationalRepresentatives, rationalEquivalent, q121specialize quotientMember with rational122rcases quotientMember with⟨bounded, u, uRepresentative, classShape⟩123obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, representativeShape⟩:= rationalRepresentatives.coordinates with uRepresentative124witness a125witness b126witness m127constructor128exact mNonzero129unfold rationalClass130rw← representativeShape131exact classShape132133theorem rationalClass.eq (a b m c d n : Nat)134requires mNonzero : m ≠0135requires nNonzero : n ≠0136requires equivalent : n * a + m * d = m * c + n * b137shows rationalClass(a, b, m) = rationalClass(c, d, n)138proof139unfold rationalClass140apply equivalenceClass.eq141 . exact rationalEquivalent.equivalence142 . haveleft:= rationalRepresentatives.pair at a, b, m with mNonzero143exactleft144 . haveright:= rationalRepresentatives.pair at c, d, n with nNonzero145exactright146 . have characterization := rationalEquivalent.relates_representatives at a, b, m, c, d, n147specialize characterization with*{2}148apply characterization.backward149exact equivalent150151theorem rationalClass.equivalent_of_eq (a b m c d n : Nat)152requires mNonzero : m ≠0153requires nNonzero : n ≠0154requires same : rationalClass(a, b, m) = rationalClass(c, d, n)155shows n * a + m * d = m * c + n * b156proof157haveleft:= rationalRepresentatives.pair at a, b, m with*158haveright:= rationalRepresentatives.pair at c, d, n with*159have related := equivalenceClass.related_of_eq at160 rationalRepresentatives, rationalEquivalent,161 ((a, b), m), ((c, d), n)162simp [rationalClass] at same163specialize related with rationalEquivalent.equivalence, left, right, same164have characterization := rationalEquivalent.relates_representatives at a, b, m, c, d, n with*165apply characterization.forward166exact related167168theorem rationalZero.rational169showsRational(rationalZero)170proof171unfold rationalZero172apply rationalClass.rational173 . have oneNonzero := Naturals.disjoint.zero.succ at0174intro oneZero175apply oneNonzero176simp177178theorem rationalOne.rational179showsRational(rationalOne)180proof181unfold rationalOne182apply rationalClass.rational183 . have oneNonzero := Naturals.disjoint.zero.succ at0184intro oneZero185apply oneNonzero186simp187188theorem rationalClassNeg.well_defined (a b m c d n : Nat)189requires mNonzero : m ≠0190requires nNonzero : n ≠0191requires equivalent : n * a + m * d = m * c + n * b192shows rationalClassNeg(a, b, m) = rationalClassNeg(c, d, n)193proof194unfold rationalClassNeg195have reversed : n * b + m * c = m * d + n * a bylinear_combination equivalent196exact rationalClass.eq with*197198theorem rationalClassNeg.rational (a b m : Nat)199requires nonzero : m ≠0200showsRational(rationalClassNeg(a, b, m))201proof202unfold rationalClassNeg203exact rationalClass.rational with*204205theorem rationalRepresentativeSum.representative (a b m c d n : Nat)206requires mNonzero : m ≠0207requires nNonzero : n ≠0208shows rationalRepresentativeSum(a, b, m, c, d, n) ∈ rationalRepresentatives209proof210unfold rationalRepresentativeSum211apply rationalRepresentatives.pair212 . exact mul.nonzero with mNonzero, nNonzero213214-- Two equivalent choices for each summand produce equivalent sum215-- representatives. The certificate is the familiar common-denominator216-- calculation, expressed as a linear combination of the two input equations.217theorem rationalClassSum.well_defined (a b m a2 b2 m2 c d n c2 d2 n2 : Nat)218requires mNonzero : m ≠0219requires m2Nonzero : m2 ≠0220requires nNonzero : n ≠0221requires n2Nonzero : n2 ≠0222requires leftEquivalent : m2 * a + m * b2 = m * a2 + m2 * b223requires rightEquivalent : n2 * c + n * d2 = n * c2 + n2 * d224shows rationalClassSum(a, b, m, c, d, n) =225 rationalClassSum(a2, b2, m2, c2, d2, n2)226proof227unfold rationalClassSum228apply rationalClass.eq229 . exact mul.nonzero with mNonzero, nNonzero230 . exact mul.nonzero with m2Nonzero, n2Nonzero231 . linear_combination n * n2 * leftEquivalent + m * m2 * rightEquivalent232233theorem rationalClassSum.rational (a b m c d n : Nat)234requires mNonzero : m ≠0235requires nNonzero : n ≠0236showsRational(rationalClassSum(a, b, m, c, d, n))237proof238unfold rationalClassSum239apply rationalClass.rational240 . exact mul.nonzero with mNonzero, nNonzero241242theorem rationalClassSum.zero_right (a b m : Nat)243requires nonzero : m ≠0244shows rationalClassSum(a, b, m, 0, 0, 1) = rationalClass(a, b, m)245proof246simp [rationalClassSum, mul.left_unit, mul.right_unit, mul.right_zero, add.right_unit]247248theorem rationalClassSum.commutative (a b m c d n : Nat)249requires mNonzero : m ≠0250requires nNonzero : n ≠0251shows rationalClassSum(a, b, m, c, d, n) = rationalClassSum(c, d, n, a, b, m)252proof253unfold rationalClassSum254apply rationalClass.eq255 . exact mul.nonzero with mNonzero, nNonzero256 . exact mul.nonzero with nNonzero, mNonzero257 . ring258259theorem rationalClassSum.associative (a b m c d n e f k : Nat)260requires mNonzero : m ≠0261requires nNonzero : n ≠0262requires kNonzero : k ≠0263shows rationalClassSum(n * a + m * c, n * b + m * d, m * n, e, f, k) =264 rationalClassSum(a, b, m, k * c + n * e, k * d + n * f, n * k)265proof266unfold rationalClassSum267apply rationalClass.eq268 . have mnNonzero := mul.nonzero with mNonzero, nNonzero269exact mul.nonzero with mnNonzero, kNonzero270 . have nkNonzero := mul.nonzero with nNonzero, kNonzero271exact mul.nonzero with mNonzero, nkNonzero272 . ring273274theorem rationalClassSum.neg_right (a b m : Nat)275requires nonzero : m ≠0276shows rationalClassSum(a, b, m, b, a, m) = rationalZero277proof278unfold rationalClassSum279unfold rationalZero280apply rationalClass.eq281 . exact mul.nonzero with nonzero, nonzero282 . have oneNonzero := Naturals.disjoint.zero.succ at0283intro oneZero284apply oneNonzero285simp286 . ring287288theorem rationalRepresentativeMul.representative (a b m c d n : Nat)289requires mNonzero : m ≠0290requires nNonzero : n ≠0291shows rationalRepresentativeMul(a, b, m, c, d, n) ∈ rationalRepresentatives292proof293unfold rationalRepresentativeMul294apply rationalRepresentatives.pair295 . exact mul.nonzero with mNonzero, nNonzero296297-- Multiplication respects both quotient arguments. Expanding signed products298-- turns the goal into a polynomial combination of the two equivalence299-- equations; no representative is selected and no cancellation is assumed.300theorem rationalClassMul.well_defined (a b m a2 b2 m2 c d n c2 d2 n2 : Nat)301requires mNonzero : m ≠0302requires m2Nonzero : m2 ≠0303requires nNonzero : n ≠0304requires n2Nonzero : n2 ≠0305requires leftEquivalent : m2 * a + m * b2 = m * a2 + m2 * b306requires rightEquivalent : n2 * c + n * d2 = n * c2 + n2 * d307shows rationalClassMul(a, b, m, c, d, n) =308 rationalClassMul(a2, b2, m2, c2, d2, n2)309proof310unfold rationalClassMul311apply rationalClass.eq312 . exact mul.nonzero with mNonzero, nNonzero313 . exact mul.nonzero with m2Nonzero, n2Nonzero314 . linear_combination n2 * c * leftEquivalent - n2 * d * leftEquivalent + m * a2 * rightEquivalent - m * b2 * rightEquivalent315316theorem rationalClassMul.rational (a b m c d n : Nat)317requires mNonzero : m ≠0318requires nNonzero : n ≠0319showsRational(rationalClassMul(a, b, m, c, d, n))320proof321unfold rationalClassMul322apply rationalClass.rational323 . exact mul.nonzero with mNonzero, nNonzero324325theorem rationalClassMul.one_right (a b m : Nat)326requires nonzero : m ≠0327shows rationalClassMul(a, b, m, 1, 0, 1) = rationalClass(a, b, m)328proof329settlewith rationalClassMul, mul.left_unit, mul.right_unit, mul.left_zero,330 mul.right_zero, add.left_unit, add.right_unit331332theorem rationalClassMul.commutative (a b m c d n : Nat)333requires mNonzero : m ≠0334requires nNonzero : n ≠0335shows rationalClassMul(a, b, m, c, d, n) = rationalClassMul(c, d, n, a, b, m)336proof337unfold rationalClassMul338apply rationalClass.eq339 . exact mul.nonzero with mNonzero, nNonzero340 . exact mul.nonzero with nNonzero, mNonzero341 . ring342343theorem rationalClassMul.associative (a b m c d n e f k : Nat)344requires mNonzero : m ≠0345requires nNonzero : n ≠0346requires kNonzero : k ≠0347shows rationalClassMul(a * c + b * d, a * d + b * c, m * n, e, f, k) =348 rationalClassMul(a, b, m, c * e + d * f, c * f + d * e, n * k)349proof350unfold rationalClassMul351apply rationalClass.eq352 . have mnNonzero := mul.nonzero with mNonzero, nNonzero353exact mul.nonzero with mnNonzero, kNonzero354 . have nkNonzero := mul.nonzero with nNonzero, kNonzero355exact mul.nonzero with mNonzero, nkNonzero356 . ring357358theorem rationalClassMul.distributive_left (a b m c d n e f k : Nat)359requires mNonzero : m ≠0360requires nNonzero : n ≠0361requires kNonzero : k ≠0362shows rationalClassMul(a, b, m, k * c + n * e, k * d + n * f, n * k) =363 rationalClassSum(364 a * c + b * d, a * d + b * c, m * n,365 a * e + b * f, a * f + b * e, m * k)366proof367unfold rationalClassMul368unfold rationalClassSum369apply rationalClass.eq370 . have nkNonzero := mul.nonzero with nNonzero, kNonzero371exact mul.nonzero with mNonzero, nkNonzero372 . have mnNonzero := mul.nonzero with mNonzero, nNonzero373have mkNonzero := mul.nonzero at m, k with*374exact mul.nonzero with mnNonzero, mkNonzero375 . ring376377theorem rationalNeg.relates (a b m : Nat)378requires mNonzero : m ≠0379shows relates(rationalNeg, rationalClass(a, b, m), rationalClassNeg(a, b, m))380proof381unfold relates382apply rationalNeg.membership.backward383constructor384 . apply product.pair at rationalClass(a, b, m), rationalClassNeg(a, b, m), ℚ, ℚ385 . have input := rationalClass.rational at a, b, m with386*{3}, mNonzero387exact input388 . have output := rationalClassNeg.rational at a, b, m with389*{3}, mNonzero390exact output391 . refine⟨a, assumption, b, assumption, m, assumption, mNonzero, rfl⟩392393theorem rationalNeg.factors (x y : Set)394requires mapped : relates(rationalNeg, x, y)395shows∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧396 x = rationalClass(a, b, m) ∧ y = rationalClassNeg(a, b, m)397proof398unfold relates at mapped399simp [rationalNeg.membership] at mapped400rcases mapped with⟨bounded, a, aNat, b, bNat, m, mNat, mNonzero, shape⟩401obtain⟨inputShape, outputShape⟩:= orderedPair.injective with shape402refine⟨a, aNat, b, bNat, m, mNat, mNonzero, inputShape, outputShape⟩403404theorem rationalNeg.total405shows TotalBetween(rationalNeg, ℚ, ℚ)406proof407intros x xRational408have typedX : Rational(x) byexact xRational409obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=Rational.coordinates with typedX410witness rationalClassNeg(a, b, m)411constructor412 . have output := rationalClassNeg.rational at a, b, m with413 aNat, bNat, mNat, mNonzero414exact output415 . rw xShape416exact rationalNeg.relates with aNat, bNat, mNat, mNonzero417418theorem rationalNeg.functional419shows Functional(rationalNeg)420proof421intros x y xy z xz422obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, inputFirst, outputFirst⟩:= rationalNeg.factors with xy423obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, inputSecond, outputSecond⟩:= rationalNeg.factors with xz424rw inputFirst at inputSecond425have equivalent := rationalClass.equivalent_of_eq with426 aNat, bNat, mNat, cNat, dNat, nNat, mNonzero, nNonzero, inputSecond427have sameNegative := rationalClassNeg.well_defined with428 aNat, bNat, mNat, cNat, dNat, nNat, mNonzero, nNonzero, equivalent429 rwa [outputFirst, outputSecond]430431theorem rationalNeg.function432shows rationalNeg : ℚ → ℚ433proof434constructor435intros p hp436simp [rationalNeg.membership] at hp437rcases hp with⟨bounded, witnesses⟩438exact bounded439 . constructor440 . exact rationalNeg.functional441 . exact rationalNeg.total442443theorem rationalAdd.relates (a b m c d n : Nat)444requires mNonzero : m ≠0445requires nNonzero : n ≠0446shows relates(rationalAdd,447 (rationalClass(a, b, m), rationalClass(c, d, n)),448 rationalClassSum(a, b, m, c, d, n))449proof450unfold relates451apply rationalAdd.membership.backward at452 ((rationalClass(a, b, m), rationalClass(c, d, n)) ↦453 rationalClassSum(a, b, m, c, d, n))454constructor455 . apply product.pair at456 (rationalClass(a, b, m), rationalClass(c, d, n)),457 rationalClassSum(a, b, m, c, d, n), ℚ × ℚ, ℚ458 . apply product.pair at rationalClass(a, b, m), rationalClass(c, d, n), ℚ, ℚ459 . haveleft:= rationalClass.rational at a, b, m with mNonzero460exactleft461 . haveright:= rationalClass.rational at c, d, n with nNonzero462exactright463 . have sum := rationalClassSum.rational at a, b, m, c, d, n464specialize sum with*{2}465exact sum466refine⟨a, assumption, b, assumption, m, assumption, mNonzero, c, assumption, d, assumption, n, assumption, nNonzero, rfl⟩467468theorem rationalAdd.factors (x y : Set)469requires h : relates(rationalAdd, x, y)470shows∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧471∃ c, Nat(c) ∧∃ d, Nat(d) ∧∃ n, Nat(n) ∧ n ≠0∧472 x = (rationalClass(a, b, m), rationalClass(c, d, n)) ∧473 y = rationalClassSum(a, b, m, c, d, n)474proof475unfold relates at h476simp [rationalAdd.membership] at h477rcases h with⟨bounded, a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, shape⟩478have coordinates := orderedPair.injective at x, y,479 (rationalClass(a, b, m), rationalClass(c, d, n)),480 rationalClassSum(a, b, m, c, d, n)481specialize coordinates with shape482rcases coordinates with⟨inputShape, outputShape⟩483refine⟨a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, inputShape, outputShape⟩484485theorem rationalAdd.total486shows TotalBetween(rationalAdd, ℚ × ℚ, ℚ)487proof488intros input hInput489obtain⟨bounded, q, qRational, r, rRational, inputShape⟩:= product.membership.forward with hInput490have qTyped : Rational(q) byexact qRational491have rTyped : Rational(r) byexact rRational492obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, qShape⟩:=Rational.coordinates with qTyped493obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, rShape⟩:=Rational.coordinates with rTyped494witness rationalClassSum(a, b, m, c, d, n)495constructor496 . exact rationalClassSum.rational at a, b, m, c, d, n with mNonzero, nNonzero497 . rw [inputShape, qShape, rShape]498exact rationalAdd.relates with aNat, bNat, mNat, cNat, dNat, nNat, mNonzero, nNonzero499500theorem rationalAdd.functional501shows Functional(rationalAdd)502proof503intros input y hY z hZ504obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, inputFirst, outputFirst⟩:= rationalAdd.factors with hY505obtain⟨a2, a2Nat, b2, b2Nat, m2, m2Nat, m2Nonzero, c2, c2Nat, d2, d2Nat, n2, n2Nat, n2Nonzero, inputSecond, outputSecond⟩:= rationalAdd.factors with hZ506rw inputFirst at inputSecond507have inputs := orderedPair.injective at508 rationalClass(a, b, m), rationalClass(c, d, n),509 rationalClass(a2, b2, m2), rationalClass(c2, d2, n2)510specialize inputs with inputSecond511rcases inputs with⟨leftSame, rightSame⟩512have leftEquivalent := rationalClass.equivalent_of_eq with513 aNat, bNat, mNat, a2Nat, b2Nat, m2Nat, mNonzero, m2Nonzero, leftSame514have rightEquivalent := rationalClass.equivalent_of_eq with515 cNat, dNat, nNat, c2Nat, d2Nat, n2Nat, nNonzero, n2Nonzero, rightSame516have sameSum := rationalClassSum.well_defined at517 a, b, m, a2, b2, m2, c, d, n, c2, d2, n2518specialize sameSum with519 mNonzero, m2Nonzero, nNonzero, n2Nonzero, leftEquivalent, rightEquivalent520 rwa [outputFirst, outputSecond]521522theorem rationalAdd.function523shows rationalAdd : ℚ × ℚ → ℚ524proof525constructor526intros p hp527simp [rationalAdd.membership] at hp528rcases hp with⟨bounded, witnesses⟩529exact bounded530 . constructor531 . exact rationalAdd.functional532 . exact rationalAdd.total533534theorem rationalMul.relates (a b m c d n : Nat)535requires mNonzero : m ≠0536requires nNonzero : n ≠0537shows relates(rationalMul,538 (rationalClass(a, b, m), rationalClass(c, d, n)),539 rationalClassMul(a, b, m, c, d, n))540proof541unfold relates542apply rationalMul.membership.backward at543 ((rationalClass(a, b, m), rationalClass(c, d, n)) ↦544 rationalClassMul(a, b, m, c, d, n))545constructor546 . apply product.pair at547 (rationalClass(a, b, m), rationalClass(c, d, n)),548 rationalClassMul(a, b, m, c, d, n), ℚ × ℚ, ℚ549 . apply product.pair at rationalClass(a, b, m), rationalClass(c, d, n), ℚ, ℚ550 . haveleft:= rationalClass.rational at a, b, m with mNonzero551exactleft552 . haveright:= rationalClass.rational at c, d, n with nNonzero553exactright554 . have product := rationalClassMul.rational at a, b, m, c, d, n555specialize product with*{2}556exact product557refine⟨a, assumption, b, assumption, m, assumption, mNonzero, c, assumption, d, assumption, n, assumption, nNonzero, rfl⟩558559theorem rationalMul.factors (x y : Set)560requires h : relates(rationalMul, x, y)561shows∃ a, Nat(a) ∧∃ b, Nat(b) ∧∃ m, Nat(m) ∧ m ≠0∧562∃ c, Nat(c) ∧∃ d, Nat(d) ∧∃ n, Nat(n) ∧ n ≠0∧563 x = (rationalClass(a, b, m), rationalClass(c, d, n)) ∧564 y = rationalClassMul(a, b, m, c, d, n)565proof566unfold relates at h567simp [rationalMul.membership] at h568rcases h with⟨bounded, a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, shape⟩569have coordinates := orderedPair.injective at x, y,570 (rationalClass(a, b, m), rationalClass(c, d, n)),571 rationalClassMul(a, b, m, c, d, n)572specialize coordinates with shape573rcases coordinates with⟨inputShape, outputShape⟩574refine⟨a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, inputShape, outputShape⟩575576theorem rationalMul.total577shows TotalBetween(rationalMul, ℚ × ℚ, ℚ)578proof579intros input hInput580obtain⟨bounded, q, qRational, r, rRational, inputShape⟩:= product.membership.forward with hInput581have qTyped : Rational(q) byexact qRational582have rTyped : Rational(r) byexact rRational583obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, qShape⟩:=Rational.coordinates with qTyped584obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, rShape⟩:=Rational.coordinates with rTyped585witness rationalClassMul(a, b, m, c, d, n)586constructor587 . exact rationalClassMul.rational at a, b, m, c, d, n with mNonzero, nNonzero588 . rw [inputShape, qShape, rShape]589exact rationalMul.relates with aNat, bNat, mNat, cNat, dNat, nNat, mNonzero, nNonzero590591theorem rationalMul.functional592shows Functional(rationalMul)593proof594intros input y hY z hZ595obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, c, cNat, d, dNat, n, nNat, nNonzero, inputFirst, outputFirst⟩:= rationalMul.factors with hY596obtain⟨a2, a2Nat, b2, b2Nat, m2, m2Nat, m2Nonzero, c2, c2Nat, d2, d2Nat, n2, n2Nat, n2Nonzero, inputSecond, outputSecond⟩:= rationalMul.factors with hZ597rw inputFirst at inputSecond598have inputs := orderedPair.injective at599 rationalClass(a, b, m), rationalClass(c, d, n),600 rationalClass(a2, b2, m2), rationalClass(c2, d2, n2)601specialize inputs with inputSecond602rcases inputs with⟨leftSame, rightSame⟩603have leftEquivalent := rationalClass.equivalent_of_eq with604 aNat, bNat, mNat, a2Nat, b2Nat, m2Nat, mNonzero, m2Nonzero, leftSame605have rightEquivalent := rationalClass.equivalent_of_eq with606 cNat, dNat, nNat, c2Nat, d2Nat, n2Nat, nNonzero, n2Nonzero, rightSame607have sameProduct := rationalClassMul.well_defined at608 a, b, m, a2, b2, m2, c, d, n, c2, d2, n2609specialize sameProduct with610 mNonzero, m2Nonzero, nNonzero, n2Nonzero, leftEquivalent, rightEquivalent611 rwa [outputFirst, outputSecond]612613theorem rationalMul.function614shows rationalMul : ℚ × ℚ → ℚ615proof616constructor617intros p hp618simp [rationalMul.membership] at hp619rcases hp with⟨bounded, witnesses⟩620exact bounded621 . constructor622 . exact rationalMul.functional623 . exact rationalMul.total624625instance rationalAdd.operation626shows AddOperation(ℚ, rationalAdd)627proof628exact rationalAdd.function629630instance rationalMul.operation631shows MulOperation(ℚ, rationalMul)632proof633exact rationalMul.function634635instance rationalNeg.operation636shows NegOperation(ℚ, rationalNeg)637proof638exact rationalNeg.function639640instance rationalZero.of_nat641shows OfNat(ℚ, 0, rationalZero)642proof643constructor644 . typecheck645 . exact rationalZero.rational646647instance rationalOne.of_nat648shows OfNat(ℚ, 1, rationalOne)649proof650constructor651 . typecheck652 . exact rationalOne.rational653654notationinfixl60"+"=> call2 via AddOperation(ℚ, _) forRational655notationinfixl70"*"=> call2 via MulOperation(ℚ, _) forRational656notationprefix75"-"=>applyvia NegOperation(ℚ, _) forRational657notation numeral "0"via OfNat(ℚ, 0, _) forRational658notation numeral "1"via OfNat(ℚ, 1, _) forRational659def rationalSubValue (x y : Rational) : Rational:= x + (-y)660notationinfixl60"-"=> rationalSubValue forRational661662-- Compatibility equations connect the instance-selected graph presentation663-- to the established public value names.664theorem rationalAddValue.notation (x y : Set)665shows rationalAdd(x, y) = rationalAddValue(x, y)666proof667unfold call2668unfold rationalAddValue669rfl670671theorem rationalMulValue.notation (x y : Set)672shows rationalMul(x, y) = rationalMulValue(x, y)673proof674unfold call2675unfold rationalMulValue676rfl677678theorem rationalNegValue.notation (x : Set)679shows rationalNeg(x) = rationalNegValue(x)680proof681unfold rationalNegValue682rfl683684theorem rationalNegValue.rational (x : Rational)685showsRational(-x)686proof687rw rationalNegValue.notation688have xMember : x ∈ ℚ bysimp [Rational]689obtain⟨y, yMember, mapped⟩:= FunctionBetween.exists_value with rationalNeg.function, xMember690have applied := FunctionBetween.apply_value with rationalNeg.function, mapped691unfold rationalNegValue692rw applied693exact yMember694695theorem rationalNegValue.classes (a b m : Nat)696requires mNonzero : m ≠0697shows rationalNegValue(rationalClass(a, b, m)) = rationalClassNeg(a, b, m)698proof699have input := rationalClass.rational at a, b, m with700*{3}, mNonzero701have inputMember := input702unfoldRationalat inputMember703have mapped := rationalNeg.relates at a, b, m with704*{3}, mNonzero705unfold rationalNegValue706exact FunctionBetween.apply_value with rationalNeg.function, inputMember, mapped707708theorem rationalAddValue.rational (x y : Rational)709showsRational(x + y)710proof711rw rationalAddValue.notation712have xMember : x ∈ ℚ bysimp [Rational]713have yMember : y ∈ ℚ bysimp [Rational]714have inputMember := product.pair with xMember, yMember715obtain⟨z, zMember, mapped⟩:= FunctionBetween.exists_value with rationalAdd.function, inputMember716have applied := FunctionBetween.apply_value with rationalAdd.function, inputMember, mapped717unfold rationalAddValue718rw applied719exact zMember720721theorem rationalMulValue.rational (x y : Rational)722showsRational(x * y)723proof724rw rationalMulValue.notation725have xMember : x ∈ ℚ bysimp [Rational]726have yMember : y ∈ ℚ bysimp [Rational]727have inputMember := product.pair with xMember, yMember728obtain⟨z, zMember, mapped⟩:= FunctionBetween.exists_value with rationalMul.function, inputMember729have applied := FunctionBetween.apply_value with rationalMul.function, inputMember, mapped730unfold rationalMulValue731rw applied732exact zMember733734theorem rationalNegValue.rational_raw (x : Rational)735showsRational(rationalNegValue(x))736proof737have result := rationalNegValue.rational at x738 rwa rationalNegValue.notation at result739740theorem rationalAddValue.rational_raw (x y : Rational)741showsRational(rationalAddValue(x, y))742proof743have result := rationalAddValue.rational at x, y with*744 rwa rationalAddValue.notation at result745746theorem rationalMulValue.rational_raw (x y : Rational)747showsRational(rationalMulValue(x, y))748proof749have result := rationalMulValue.rational at x, y with*750 rwa rationalMulValue.notation at result751752-- The public operations compute by choosing the unique graph value. These753-- equations let a proof move cleanly between quotient notation and a concrete754-- representative calculation without unfolding the function graph.755theorem rationalAddValue.classes (a b m c d n : Nat)756requires mNonzero : m ≠0757requires nNonzero : n ≠0758shows rationalAddValue(rationalClass(a, b, m), rationalClass(c, d, n)) =759 rationalClassSum(a, b, m, c, d, n)760proof761haveleft:= rationalClass.rational at a, b, m with*762haveright:= rationalClass.rational at c, d, n with*763have input := product.pair at764 rationalClass(a, b, m), rationalClass(c, d, n), ℚ, ℚ765specialize input withleft, right766have mapped := rationalAdd.relates at a, b, m, c, d, n with767*{6},768 mNonzero, nNonzero769unfold rationalAddValue770exact FunctionBetween.apply_value with rationalAdd.function, input, mapped771772theorem rationalMulValue.classes (a b m c d n : Nat)773requires mNonzero : m ≠0774requires nNonzero : n ≠0775shows rationalMulValue(rationalClass(a, b, m), rationalClass(c, d, n)) =776 rationalClassMul(a, b, m, c, d, n)777proof778haveleft:= rationalClass.rational at a, b, m with*779haveright:= rationalClass.rational at c, d, n with*780have input := product.pair at781 rationalClass(a, b, m), rationalClass(c, d, n), ℚ, ℚ782specialize input withleft, right783have mapped := rationalMul.relates at a, b, m, c, d, n with784*{6},785 mNonzero, nNonzero786unfold rationalMulValue787exact FunctionBetween.apply_value with rationalMul.function, input, mapped788789theorem rationalAddValue.commutative (x y : Rational)790shows x + y = y + x791proof792rw [rationalAddValue.notation, rationalAddValue.notation]793obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=794Rational.coordinates at x withassumption795obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=796Rational.coordinates at y withassumption797have mnNonzero := mul.nonzero with mNonzero, nNonzero798rw [xShape, yShape, rationalAddValue.classes, rationalAddValue.classes]799exact rationalClassSum.commutative with aNat, bNat, mNat, cNat, dNat, nNat, mNonzero, nNonzero800801theorem rationalAddValue.zero_right (x : Rational)802shows x +0= x803proof804rw rationalAddValue.notation805obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=806Rational.coordinates withassumption807have zeroNat : Nat(0) bytypecheck808have oneNat : Nat(1) bytypecheck809have oneNonzero : 1≠0810intro oneZero811arith812have computed := rationalAddValue.classes with813 aNat, bNat, mNat, zeroNat, zeroNat, oneNat, mNonzero, oneNonzero814have identity := rationalClassSum.zero_right with aNat, bNat, mNat, mNonzero815have computedZero : rationalAddValue(rationalClass(a, b, m), rationalZero) = rationalClassSum(a, b, m, 0, 0, 1)816 simpa [rationalZero] using computed817have classIdentity : rationalAddValue(rationalClass(a, b, m), rationalZero) = rationalClass(a, b, m)818calc819 rationalAddValue(rationalClass(a, b, m), rationalZero) =820 rationalClassSum(a, b, m, 0, 0, 1) := computedZero821 _ = rationalClass(a, b, m) := identity822 simpa [xShape] using classIdentity823824theorem rationalAddValue.zero_left (x : Rational)825shows0+ x = x826proof827calc828 rationalZero + x = x + rationalZero :=829 rationalAddValue.commutative at rationalZero, x with830 rationalZero.rational, assumption831 _ = x := rationalAddValue.zero_right at x withassumption832833theorem rationalAddValue.neg_right (x : Rational)834shows x + (-x) =0835proof836rw [rationalAddValue.notation, rationalNegValue.notation]837obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=838Rational.coordinates withassumption839have negative := rationalNegValue.classes with aNat, bNat, mNat, mNonzero840have sum := rationalAddValue.classes with aNat, bNat, mNat, bNat, aNat, mNat, mNonzero, mNonzero841have sumNegative : rationalAddValue(rationalClass(a, b, m), rationalClassNeg(a, b, m)) = rationalClassSum(a, b, m, b, a, m)842 simpa [rationalClassNeg] using sum843have inverse := rationalClassSum.neg_right with aNat, bNat, mNat, mNonzero844have classInverse : rationalAddValue(rationalClass(a, b, m), rationalNegValue(rationalClass(a, b, m))) = rationalZero845 rwa [negative, sumNegative]846 simpa [xShape] using classInverse847848theorem rationalAddValue.neg_left (x : Rational)849shows (-x) + x =0850proof851calc852 (-x) + x = x + (-x) :=853 rationalAddValue.commutative at -x, x with854 rationalNegValue.rational with*{2}855 _ = rationalZero := rationalAddValue.neg_right at x withassumption856857theorem rationalAddValue.associative (x y z : Rational)858shows (x + y) + z = x + (y + z)859proof860rw [rationalAddValue.notation, rationalAddValue.notation, rationalAddValue.notation, rationalAddValue.notation]861obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=862Rational.coordinates at x withassumption863obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=864Rational.coordinates at y withassumption865obtain⟨e, eNat, f, fNat, k, kNat, kNonzero, zShape⟩:=866Rational.coordinates at z withassumption867have leftNumeratorNat : Nat(n * a + m * c) bytypecheck868have leftDenumeratorNat : Nat(n * b + m * d) bytypecheck869have mnNat : Nat(m * n) bytypecheck870have rightNumeratorNat : Nat(k * c + n * e) bytypecheck871have rightDenumeratorNat : Nat(k * d + n * f) bytypecheck872have nkNat : Nat(n * k) bytypecheck873have mnNonzero := mul.nonzero with mNat, nNat, mNonzero, nNonzero874have nkNonzero := mul.nonzero with nNat, kNat, nNonzero, kNonzero875have leftOuterClasses := rationalAddValue.classes with876 leftNumeratorNat, leftDenumeratorNat, mnNat, eNat, fNat, kNat, mnNonzero, kNonzero877have leftOuter : rationalAddValue(rationalClassSum(a, b, m, c, d, n), rationalClass(e, f, k)) = rationalClassSum(n * a + m * c, n * b + m * d, m * n, e, f, k)878 simpa [rationalClassSum] using leftOuterClasses879have rightOuterClasses := rationalAddValue.classes with880 aNat, bNat, mNat, rightNumeratorNat, rightDenumeratorNat, nkNat, mNonzero, nkNonzero881have rightOuter : rationalAddValue(rationalClass(a, b, m), rationalClassSum(c, d, n, e, f, k)) = rationalClassSum(a, b, m, k * c + n * e, k * d + n * f, n * k)882 simpa [rationalClassSum] using rightOuterClasses883rw [xShape, yShape, zShape, rationalAddValue.classes, rationalAddValue.classes, leftOuter, rightOuter]884exact rationalClassSum.associative with885 aNat, bNat, mNat, cNat, dNat, nNat, eNat, fNat, kNat, mNonzero, nNonzero, kNonzero886887theorem rationalMulValue.commutative (x y : Rational)888shows x * y = y * x889proof890rw [rationalMulValue.notation, rationalMulValue.notation]891obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=892Rational.coordinates at x withassumption893obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=894Rational.coordinates at y withassumption895rw [xShape, yShape, rationalMulValue.classes, rationalMulValue.classes]896exact rationalClassMul.commutative with mNonzero, nNonzero897898theorem rationalMulValue.associative (x y z : Rational)899shows (x * y) * z = x * (y * z)900proof901rw [rationalMulValue.notation, rationalMulValue.notation, rationalMulValue.notation, rationalMulValue.notation]902obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=903Rational.coordinates at x withassumption904obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=905Rational.coordinates at y withassumption906obtain⟨e, eNat, f, fNat, k, kNat, kNonzero, zShape⟩:=907Rational.coordinates at z withassumption908have leftNumeratorNat : Nat(a * c + b * d) bytypecheck909have leftDenominatorNat : Nat(a * d + b * c) bytypecheck910have mnNat : Nat(m * n) bytypecheck911have rightNumeratorNat : Nat(c * e + d * f) bytypecheck912have rightDenominatorNat : Nat(c * f + d * e) bytypecheck913have nkNat : Nat(n * k) bytypecheck914have mnNonzero := mul.nonzero with mNat, nNat, mNonzero, nNonzero915have nkNonzero := mul.nonzero with nNat, kNat, nNonzero, kNonzero916have leftOuterClasses := rationalMulValue.classes with917 leftNumeratorNat, leftDenominatorNat, mnNat, eNat, fNat, kNat, mnNonzero, kNonzero918have leftOuter : rationalMulValue(919 rationalClassMul(a, b, m, c, d, n), rationalClass(e, f, k)) =920 rationalClassMul(a * c + b * d, a * d + b * c, m * n, e, f, k)921 simpa [rationalClassMul] using leftOuterClasses922have rightOuterClasses := rationalMulValue.classes with923 aNat, bNat, mNat, rightNumeratorNat, rightDenominatorNat, nkNat, mNonzero, nkNonzero924have rightOuter : rationalMulValue(925 rationalClass(a, b, m), rationalClassMul(c, d, n, e, f, k)) =926 rationalClassMul(a, b, m,927 c * e + d * f, c * f + d * e, n * k)928 simpa [rationalClassMul] using rightOuterClasses929rw [xShape, yShape, zShape, rationalMulValue.classes, rationalMulValue.classes, leftOuter, rightOuter]930exact rationalClassMul.associative with mNonzero, nNonzero, kNonzero931932theorem rationalMulValue.one_right (x : Rational)933shows x * rationalOne = x934proof935rw rationalMulValue.notation936obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=937Rational.coordinates withassumption938have oneNonzero : 1≠0939intro oneZero940arith941rw xShape942unfold rationalOne943have computed := rationalMulValue.classes at944 a, b, m, 1, 0, 1with mNonzero, oneNonzero945rw computed946exact rationalClassMul.one_right with mNonzero947948theorem rationalMulValue.one_left (x : Rational)949shows rationalOne * x = x950proof951calc952 rationalOne * x = x * rationalOne :=953 rationalMulValue.commutative at rationalOne, x with954 rationalOne.rational, assumption955 _ = x := rationalMulValue.one_right at x withassumption956957theorem rationalMulValue.zero_right (x : Rational)958shows x * rationalZero = rationalZero959proof960rw rationalMulValue.notation961obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=962Rational.coordinates withassumption963have oneNonzero : 1≠0964intro oneZero965arith966rw xShape967unfold rationalZero968rw rationalMulValue.classes969unfold rationalClassMul970apply rationalClass.eq971 . exact mul.nonzero with mNonzero, oneNonzero972 . exact oneNonzero973 . ring974975theorem rationalMulValue.zero_left (x : Rational)976shows rationalZero * x = rationalZero977proof978calc979 rationalZero * x = x * rationalZero :=980 rationalMulValue.commutative at rationalZero, x with981 rationalZero.rational, assumption982 _ = rationalZero := rationalMulValue.zero_right at x withassumption983984theorem rationalMulValue.neg_right (x y : Rational)985shows x * (-y) = -(x * y)986proof987rw [rationalMulValue.notation, rationalNegValue.notation, rationalNegValue.notation, rationalMulValue.notation]988obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=989Rational.coordinates at x withassumption990obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=991Rational.coordinates at y withassumption992have productDenominatorNonzero := mul.nonzero with mNonzero, nNonzero993rw [xShape, yShape, rationalNegValue.classes]994unfold rationalClassNeg995rw rationalMulValue.classes996unfold rationalClassMul997rw rationalMulValue.classes998unfold rationalClassMul999have negComputed := rationalNegValue.classes at1000 a * c + b * d, a * d + b * c, m * n with1001 productDenominatorNonzero1002rw negComputed1003unfold rationalClassNeg1004apply rationalClass.eq1005 . exact productDenominatorNonzero1006 . exact productDenominatorNonzero1007 . ring10081009theorem rationalMulValue.neg_left (x y : Rational)1010shows (-x) * y = -(x * y)1011proof1012have commutativeLeft := rationalMulValue.commutative at -x, y with1013 rationalNegValue.rational with*{2}1014have commutativeRight := rationalMulValue.commutative at y, x with1015*{2}1016rw [commutativeLeft, rationalMulValue.neg_right, commutativeRight]1017rfl10181019theorem rationalMulValue.distributive_left (x y z : Rational)1020shows x * (y + z) = x * y + x * z1021proof1022rw [rationalMulValue.notation, rationalAddValue.notation, rationalMulValue.notation, rationalMulValue.notation, rationalAddValue.notation]1023obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=1024Rational.coordinates at x withassumption1025obtain⟨c, cNat, d, dNat, n, nNat, nNonzero, yShape⟩:=1026Rational.coordinates at y withassumption1027obtain⟨e, eNat, f, fNat, k, kNat, kNonzero, zShape⟩:=1028Rational.coordinates at z withassumption1029have nkNonzero := mul.nonzero with nNonzero, kNonzero1030have mnNonzero := mul.nonzero with mNonzero, nNonzero1031have mkNonzero := mul.nonzero with mNonzero, kNonzero1032have sumComputed := rationalAddValue.classes at1033 c, d, n, e, f, k with nNonzero, kNonzero1034have leftComputed := rationalMulValue.classes at1035 a, b, m, k * c + n * e, k * d + n * f, n * k with1036 mNonzero, nkNonzero1037have xyComputed := rationalMulValue.classes at1038 a, b, m, c, d, n with mNonzero, nNonzero1039have xzComputed := rationalMulValue.classes at1040 a, b, m, e, f, k with mNonzero, kNonzero1041have rightComputed := rationalAddValue.classes at1042 a * c + b * d, a * d + b * c, m * n,1043 a * e + b * f, a * f + b * e, m * k with1044 mnNonzero, mkNonzero1045rw [xShape, yShape, zShape]1046calc1047 rationalMulValue(rationalClass(a, b, m),1048 rationalAddValue(rationalClass(c, d, n), rationalClass(e, f, k))) =1049 rationalMulValue(rationalClass(a, b, m),1050 rationalClassSum(c, d, n, e, f, k)) :=bysimp [sumComputed]1051 _ = rationalClassMul(a, b, m,1052 k * c + n * e, k * d + n * f, n * k) :=1053by simpa [rationalClassSum] using leftComputed1054 _ = rationalClassSum(1055 a * c + b * d, a * d + b * c, m * n,1056 a * e + b * f, a * f + b * e, m * k) :=1057 rationalClassMul.distributive_left at1058 a, b, m, c, d, n, e, f, k with1059 mNonzero, nNonzero, kNonzero1060 _ = rationalAddValue(1061 rationalClassMul(a, b, m, c, d, n),1062 rationalClassMul(a, b, m, e, f, k)) :=1063by simpa [rationalClassMul] using rightComputed1064 _ = rationalAddValue(1065 rationalMulValue(rationalClass(a, b, m), rationalClass(c, d, n)),1066 rationalMulValue(rationalClass(a, b, m), rationalClass(e, f, k))) :=1067bysimp [xyComputed, xzComputed]10681069theorem rationalMulValue.distributive_right (x y z : Rational)1070shows (x + y) * z = x * z + y * z1071proof1072have sumRational := rationalAddValue.rational at x, y with1073*{2}1074have outerCommutative := rationalMulValue.commutative at x + y, z with1075 sumRational, assumption1076have distributed := rationalMulValue.distributive_left at z, x, y with1077*{3}1078have firstCommutative := rationalMulValue.commutative at z, x with1079*{2}1080have secondCommutative := rationalMulValue.commutative at z, y with1081*{2}1082rw [outerCommutative, distributed, firstCommutative, secondCommutative]1083rfl10841085theorem rationalSubValue.rational (x y : Rational)1086showsRational(x - y)1087proof1088unfold rationalSubValue1089exact rationalAddValue.rational at x, -y with1090assumption, rationalNegValue.rational at y withassumption10911092theorem rationalAddValue.add_sub_cancel_left (x y : Rational)1093shows x + (y - x) = y1094proof1095unfold rationalSubValue1096have associative := rationalAddValue.associative at x, y, -x with1097*{2}, rationalNegValue.rational at x withassumption1098have associativeYX := rationalAddValue.associative at y, x, -x with1099*{2}, rationalNegValue.rational at x withassumption1100have commutative := rationalAddValue.commutative at x, y with1101*{2}1102have inverse := rationalAddValue.neg_right at x1103have identity := rationalAddValue.zero_right at y1104have regroup : x + (y + (-x)) = (x + y) + (-x)1105rw associative1106rfl1107have swap : (x + y) + (-x) = (y + x) + (-x)1108rw commutative1109rfl1110have cancel : y + (x + (-x)) = y + rationalZero1111rw inverse1112rfl1113calc1114 x + (y + (-x)) = (x + y) + (-x) := regroup1115 _ = (y + x) + (-x) := swap1116 _ = y + (x + (-x)) := associativeYX1117 _ = y + rationalZero := cancel1118 _ = y := identity11191120theorem rationalAddValue.add_sub_cancel_right (x y : Rational)1121shows (x + y) - y = x1122proof1123unfold rationalSubValue1124have associative := rationalAddValue.associative at x, y, -y with1125*{2}, rationalNegValue.rational at y withassumption1126have inverse := rationalAddValue.neg_right at y1127have identity := rationalAddValue.zero_right at x1128have cancel : x + (y + (-y)) = x + rationalZero1129rw inverse1130rfl1131calc1132 (x + y) + (-y) = x + (y + (-y)) := associative1133 _ = x + rationalZero := cancel1134 _ = x := identity11351136theorem rationalAddValue.sum_sub_left (x y : Rational)1137shows (x + y) - x = y1138proof1139have commutative := rationalAddValue.commutative at x, y with1140*{2}1141have swapped : (x + y) - x = (y + x) - x1142rw commutative1143rfl1144calc1145 (x + y) - x = (y + x) - x := swapped1146 _ = y := rationalAddValue.add_sub_cancel_right at y, x with1147*{2}11481149-- Subtracting a sum from its left summand leaves the negative right summand.1150-- The statement stays at the quotient level; representative arithmetic is1151-- used only as the checked certificate below.1152theorem rationalSubValue.sub_sum_left (x y : Rational)1153shows x - (x + y) = -y1154proof1155obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=1156Rational.coordinates at x withassumption1157obtain⟨c, cNatural, d, dNatural, n, nNatural, nNonzero, yShape⟩:=1158Rational.coordinates at y withassumption1159have mnNonzero := mul.nonzero with mNonzero, nNonzero1160have sumComputed := rationalAddValue.classes at1161 a, b, m, c, d, n with mNonzero, nNonzero1162have negSumComputed := rationalNegValue.classes at1163 n * a + m * c, n * b + m * d, m * n with mnNonzero1164have outerComputed := rationalAddValue.classes at1165 a, b, m,1166 n * b + m * d, n * a + m * c, m * n with1167 mNonzero, mnNonzero1168have negYComputed := rationalNegValue.classes at c, d, n with nNonzero1169rw← rationalAddValue.notation at sumComputed1170rw← rationalNegValue.notation at negSumComputed1171rw← rationalAddValue.notation at outerComputed1172rw← rationalNegValue.notation at negYComputed1173have negSumShape : rationalNeg(rationalClassSum(a, b, m, c, d, n)) =1174 rationalClassNeg(n * a + m * c, n * b + m * d, m * n)1175unfold rationalClassSum1176exact negSumComputed1177have outerShape : call2(rationalAdd, rationalClass(a, b, m),1178 rationalClassNeg(n * a + m * c, n * b + m * d, m * n)) =1179 rationalClassSum(a, b, m,1180 n * b + m * d, n * a + m * c, m * n)1181unfold rationalClassNeg1182exact outerComputed1183have computedEquality : rationalClass(1184 (m * n) * a + m * (n * b + m * d),1185 (m * n) * b + m * (n * a + m * c),1186 m * (m * n)) = rationalClass(d, c, n)1187apply rationalClass.eq1188 . exact mul.nonzero at m, m * n with mNonzero, mnNonzero1189 . exact nNonzero1190 . ring1191 simpa [xShape, yShape, rationalSubValue,1192 rationalClassSum, rationalClassNeg] using computedEquality11931194theorem rationalNegValue.involutive (x : Rational)1195shows -(-x) = x1196proof1197rw [rationalNegValue.notation, rationalNegValue.notation]1198obtain⟨a, aNat, b, bNat, m, mNat, mNonzero, xShape⟩:=1199Rational.coordinates withassumption1200have first := rationalNegValue.classes with aNat, bNat, mNat, mNonzero1201have second := rationalNegValue.classes with bNat, aNat, mNat, mNonzero1202rw [xShape, first]1203 simpa [rationalClassNeg] using second12041205-- The quotient operations form the same checked algebraic interface used by1206-- ring normalization on the reals. All laws above were proved on ℚ.1207instance rationalAdd.comm_monoid1208shows IsCommMonoid(ℚ, rationalAdd, rationalZero)1209proof1210constructor1211constructor1212constructor1213exact rationalAdd.function1214intros A rationalA B rationalB C rationalC1215have typedA : Rational(A) bytypecheck1216have typedB : Rational(B) bytypecheck1217have typedC : Rational(C) bytypecheck1218 simpa [rationalAddValue.notation] using rationalAddValue.associative at A, B, C with typedA, typedB, typedC1219constructor1220 . exact rationalZero.rational1221 . intros A rationalA1222have typedA : Rational(A) bytypecheck1223constructor1224 . simpa [rationalAddValue.notation] using rationalAddValue.zero_left at A with typedA1225 . simpa [rationalAddValue.notation] using rationalAddValue.zero_right at A with typedA1226intros A rationalA B rationalB1227have typedA : Rational(A) bytypecheck1228have typedB : Rational(B) bytypecheck1229 simpa [rationalAddValue.notation] using rationalAddValue.commutative at A, B with typedA, typedB12301231instance rationalAdd.abelian_group1232shows IsAbelianGroup(ℚ, rationalAdd, rationalZero, rationalNeg)1233proof1234constructor1235constructor1236 . have additive := rationalAdd.comm_monoid1237simp [IsCommMonoid]1238constructor1239 . exact rationalNeg.function1240 . intros A rationalA1241have typedA : Rational(A) bytypecheck1242constructor1243 . simpa [rationalAddValue.notation, rationalNegValue.notation] using rationalAddValue.neg_left at A with typedA1244 . simpa [rationalAddValue.notation, rationalNegValue.notation] using rationalAddValue.neg_right at A with typedA1245 . have additive := rationalAdd.comm_monoid1246simp [IsCommMonoid]12471248instance rationalMul.monoid1249shows IsMonoid(ℚ, rationalMul, rationalOne)1250proof1251constructor1252constructor1253exact rationalMul.function1254intros A rationalA B rationalB C rationalC1255have typedA : Rational(A) bytypecheck1256have typedB : Rational(B) bytypecheck1257have typedC : Rational(C) bytypecheck1258 simpa [rationalMulValue.notation] using rationalMulValue.associative at A, B, C with typedA, typedB, typedC1259constructor1260 . exact rationalOne.rational1261 . intros A rationalA1262have typedA : Rational(A) bytypecheck1263constructor1264 . simpa [rationalMulValue.notation] using rationalMulValue.one_left at A with typedA1265 . simpa [rationalMulValue.notation] using rationalMulValue.one_right at A with typedA12661267instance rationalMul.distributive1268shows Distributive(ℚ, rationalAdd, rationalMul)1269proof1270intros A rationalA B rationalB C rationalC1271have typedA : Rational(A) bytypecheck1272have typedB : Rational(B) bytypecheck1273have typedC : Rational(C) bytypecheck1274constructor1275 . simpa [rationalAddValue.notation, rationalMulValue.notation] using rationalMulValue.distributive_left at A, B, C with typedA, typedB, typedC1276 . simpa [rationalAddValue.notation, rationalMulValue.notation] using rationalMulValue.distributive_right at A, B, C with typedA, typedB, typedC12771278instance rationalMul.commutative1279shows Commutative(ℚ, rationalMul)1280proof1281intros A rationalA B rationalB1282have typedA : Rational(A) bytypecheck1283have typedB : Rational(B) bytypecheck1284 simpa [rationalMulValue.notation] using rationalMulValue.commutative at A, B with typedA, typedB12851286instance rationals.comm_ring1287shows IsCommRing(ℚ, rationalAdd, rationalZero, rationalNeg, rationalMul, rationalOne)1288proof1289constructor1290constructor1291 . exact rationalAdd.abelian_group1292 . constructor1293 . exact rationalMul.monoid1294 . exact rationalMul.distributive1295 . exact rationalMul.commutative1296