1-- Order compatibility of rational operations2-- 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.OrderedOperations8import Density910-- The mainstream typed interface to the set-level transitivity certificate.11theorem rationalLess.transitive (x y z : Rational)12requires xy : x < y13requires yz : y < z14shows x < z15proof16have transitive := rationalLess.transitive_on17exact transitive with x, y, z, xy, yz1819-- Adding the same displayed rational preserves strict order. The quotient20-- calculation is isolated here so clients can use the ordered-group21-- law without exposing representatives.22-- No rational is below itself.23theorem rationalLess.irreflexive (x : Rational)24shows¬(x < x)25proof26intro less27have irreflexive := rationalLess.irreflexive_on28exact irreflexive with x, less2930-- Two rationals compare one way, are equal, or compare the other way.31theorem rationalLess.trichotomy (x y : Rational)32shows x < y ∨ x = y ∨ y < x33proof34by_contra none35have distinct : x ≠ y36intro equal37apply none38right39left40exact equal41have connected := rationalLess.connected_on42have comparison := connected with x, y, distinct43apply none44cases comparison with xy | yx45 . left46exact xy47 . right48right49exact yx5051theorem rationalLess.add_right_classes (a b m c d n e f k : Nat)52requires mNonzero : m ≠053requires nNonzero : n ≠054requires kNonzero : k ≠055requires less : relates(rationalLess,56 rationalClass(a, b, m), rationalClass(c, d, n))57shows relates(rationalLess,58 rationalAddValue(rationalClass(a, b, m), rationalClass(e, f, k)),59 rationalAddValue(rationalClass(c, d, n), rationalClass(e, f, k)))60proof61have crossLess := rationalLess.classes.forward with mNonzero, nNonzero, less62have squareNatural := mul.closed at k, k with*63have squareNonzero := mul.nonzero with kNonzero, kNonzero64have leftNatural : Nat(n * a + m * d) bysimp [mul.closed, add.closed]65have rightNatural : Nat(m * c + n * b) bysimp [mul.closed, add.closed]66have scaled := Less.mul_left with squareNonzero, crossLess67have commonNatural : Nat(((m * n) * k) * e + ((m * n) * k) * f) bysimp [mul.closed, add.closed]68have commonReflexive := LessEqual.reflexive with commonNatural69have augmented := Less.add_LessEqual at70 (k * k) * (n * a + m * d), (k * k) * (m * c + n * b),71 ((m * n) * k) * e + ((m * n) * k) * f,72 ((m * n) * k) * e + ((m * n) * k) * f with73*{2}, commonNatural, commonNatural, scaled, commonReflexive74have leftShape : (k * k) * (n * a + m * d) + (((m * n) * k) * e + ((m * n) * k) * f) = (n * k) * (k * a + m * e) + (m * k) * (k * d + n * f)75ring76have rightShape : (k * k) * (m * c + n * b) + (((m * n) * k) * e + ((m * n) * k) * f) = (m * k) * (k * c + n * e) + (n * k) * (k * b + m * f)77ring78rw [leftShape, rightShape] at augmented79have leftSum := rationalAddValue.classes at80 a, b, m, e, f, k with mNonzero, kNonzero81have rightSum := rationalAddValue.classes at82 c, d, n, e, f, k with nNonzero, kNonzero83rw [leftSum, rightSum]84have mkNonzero := mul.nonzero with mNonzero, kNonzero85have nkNonzero := mul.nonzero with nNonzero, kNonzero86unfold rationalClassSum87exact rationalLess.classes.backward with mkNonzero, nkNonzero, augmented8889-- Translation invariance stated at the public rational boundary.90theorem rationalLess.add_right (x y z : Rational)91requires less : x < y92shows x + z < y + z93proof94obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=95Rational.coordinates at x withassumption96obtain⟨c, cNatural, d, dNatural, n, nNatural, nNonzero, yShape⟩:=97Rational.coordinates at y withassumption98obtain⟨e, eNatural, f, fNatural, k, kNatural, kNonzero, zShape⟩:=99Rational.coordinates at z withassumption100rw [xShape, yShape] at less101rw [xShape, yShape, zShape, rationalAddValue.notation, rationalAddValue.notation]102exact rationalLess.add_right_classes with mNonzero, nNonzero, kNonzero, less103104-- Commutativity turns right translation into the corresponding left law.105theorem rationalLess.add_left (x y z : Rational)106requires less : x < y107shows z + x < z + y108proof109have translated := rationalLess.add_right at x, y, z with less110obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=111Rational.coordinates at x withassumption112obtain⟨c, cNatural, d, dNatural, n, nNatural, nNonzero, yShape⟩:=113Rational.coordinates at y withassumption114obtain⟨e, eNatural, f, fNatural, k, kNatural, kNonzero, zShape⟩:=115Rational.coordinates at z withassumption116have xzCommutative := rationalClassSum.commutative at117 a, b, m, e, f, k with mNonzero, kNonzero118have yzCommutative := rationalClassSum.commutative at119 c, d, n, e, f, k with nNonzero, kNonzero120have xzLeft := rationalAddValue.classes at121 a, b, m, e, f, k with mNonzero, kNonzero122have zxRight := rationalAddValue.classes at123 e, f, k, a, b, m with kNonzero, mNonzero124have yzLeft := rationalAddValue.classes at125 c, d, n, e, f, k with nNonzero, kNonzero126have zyRight := rationalAddValue.classes at127 e, f, k, c, d, n with kNonzero, nNonzero128rw [xShape, yShape, zShape] at translated129rw [xShape, yShape, zShape]130rw [rationalAddValue.notation, rationalAddValue.notation] at translated131rw [rationalAddValue.notation, rationalAddValue.notation]132rw [xzLeft, yzLeft] at translated133rw [zxRight, zyRight]134 rwa [xzCommutative, yzCommutative] at translated135136theorem rationalLess.of_add_right (x y z : Rational)137requires translated : x + z < y + z138shows x < y139proof140have leftRational := rationalAddValue.rational at x, z with141*{2}142have rightRational := rationalAddValue.rational at y, z with143*{2}144have negativeZ := rationalNegValue.rational at z145have shiftedBack := rationalLess.add_right with leftRational, rightRational, negativeZ, translated146have leftCancel := rationalAddValue.add_sub_cancel_right at x, z with147*{2}148have rightCancel := rationalAddValue.add_sub_cancel_right at y, z with149*{2}150unfold rationalSubValue at leftCancel151unfold rationalSubValue at rightCancel152 rwa [leftCancel, rightCancel] at shiftedBack153154-- The product of two positive rationals is positive. At displayed155-- representatives, positivity says b<a and d<c; normalization isolates the156-- positive remainder (a-b)(c-d) without introducing integer subtraction.157theorem rationalLess.mul_positive (x y : Rational)158requires positiveX : rationalZero < x159requires positiveY : rationalZero < y160shows rationalZero < x * y161proof162obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=163Rational.coordinates at x withassumption164obtain⟨c, cNatural, d, dNatural, n, nNatural, nNonzero, yShape⟩:=165Rational.coordinates at y withassumption166have oneNonzero : 1≠0167intro oneZero168arith169have displayedX := positiveX170have displayedY := positiveY171rw xShape at displayedX172rw yShape at displayedY173unfold rationalZero at displayedX174unfold rationalZero at displayedY175have bLessA : b < a176have cross := rationalLess.classes.forward with oneNonzero, mNonzero, displayedX177 simpa [mul.left_zero, mul.right_zero, mul.left_unit,178 mul.right_unit, add.left_unit, add.right_unit] using cross179have dLessC : d < c180have cross := rationalLess.classes.forward with oneNonzero, nNonzero, displayedY181 simpa [mul.left_zero, mul.right_zero, mul.left_unit,182 mul.right_unit, add.left_unit, add.right_unit] using cross183obtain⟨k, kNatural, aShape⟩:= bLessA184obtain⟨l, lNatural, cShape⟩:= dLessC185have succKNonzero : succ(k) ≠0186intro succKZero187have zeroNotSuccK := Naturals.disjoint.zero.succ at k188apply zeroNotSuccK189rw succKZero190rfl191have succLNonzero : succ(l) ≠0192intro succLZero193have zeroNotSuccL := Naturals.disjoint.zero.succ at l194apply zeroNotSuccL195rw succLZero196rfl197have remainderNonzero := mul.nonzero with succKNonzero, succLNonzero198have positiveRemainder := Less.add_positive at199 a * d + b * c, succ(k) * succ(l) with200 remainderNonzero201have productGap : a * d + b * c + succ(k) * succ(l) = a * c + b * d202rw [← aShape, ← cShape]203ring204rw productGap at positiveRemainder205rw [xShape, yShape, rationalMulValue.notation, rationalMulValue.classes]206unfold rationalClassMul207unfold rationalZero208have mnNonzero := mul.nonzero with mNonzero, nNonzero209apply rationalLess.classes.backward with oneNonzero, mnNonzero210ring_nf211exact positiveRemainder212213theorem rationalLess.sub_positive (x y : Rational)214requires less : x < y215shows rationalZero < y - x216proof217have negX := rationalNegValue.rational at x218have shifted := rationalLess.add_right at x, y, -x with219*{2}, negX, less220have inverse := rationalAddValue.neg_right at x221rw inverse at shifted222unfold rationalSubValue223exact shifted224225-- Multiplication by a positive rational preserves strict order. The proof is226-- the textbook difference argument z(y-x)>0, with distributivity supplying227-- z*y = z*x + z*(y-x).228theorem rationalLess.mul_left (x y z : Rational)229requires positiveZ : rationalZero < z230requires less : x < y231shows z * x < z * y232proof233have gapRational := rationalSubValue.rational at y, x with234*{2}235have positiveGap := rationalLess.sub_positive with less236have positiveProduct := rationalLess.mul_positive with positiveZ, positiveGap237have zxRational := rationalMulValue.rational at z, x with238*{2}239have productRational := rationalMulValue.rational at z, y - x with240assumption, gapRational241have shifted := rationalLess.add_left with242 rationalZero.rational, productRational, zxRational, positiveProduct243have leftIdentity := rationalAddValue.zero_right with zxRational244rw leftIdentity at shifted245have gapCloses := rationalAddValue.add_sub_cancel_left at x, y with246*{2}247have decomposition : z * x + z * (y - x) = z * y248have distributed := rationalMulValue.distributive_left at z, x, y - x with249*{2}, gapRational250rw gapCloses at distributed251rw← distributed252rfl253 rwa decomposition at shifted254255theorem rationalLess.mul_right (x y z : Rational)256requires positiveZ : rationalZero < z257requires less : x < y258shows x * z < y * z259proof260have scaled := rationalLess.mul_left with positiveZ, less261have leftCommutative := rationalMulValue.commutative at z, x with262*{2}263have rightCommutative := rationalMulValue.commutative at z, y with264*{2}265 rwa [leftCommutative, rightCommutative] at scaled266267-- Cancellation by a positive rational. Together with mul_left this says268-- that positive scaling is an order embedding.269theorem rationalLess.of_mul_left (x y z : Rational)270requires positiveZ : rationalZero < z271requires scaled : z * x < z * y272shows x < y273proof274have xDistinctY : x ≠ y275intro equal276rw equal at scaled277have irreflexive := rationalLess.irreflexive_on278exact irreflexive with z * y, scaled279have connected := rationalLess.connected_on280have comparison := connected with x, y, xDistinctY281cases comparison with xLessY | yLessX282 . exact xLessY283 . have reverse := rationalLess.mul_left at y, x, z with284*{3}, positiveZ, yLessX285have cycle := rationalLess.transitive with scaled, reverse286have irreflexive := rationalLess.irreflexive_on287exfalso288exact irreflexive with z * x, cycle289290theorem rationalLess.neg_reverse (x y : Rational)291requires less : x < y292shows -y < -x293proof294have negX := rationalNegValue.rational at x295have negY := rationalNegValue.rational at y296have translated := rationalLess.add_right at x, y, -x with297*{2}, negX, less298have inverseX := rationalAddValue.neg_right at x299rw inverseX at translated300have sumRational := rationalAddValue.rational at y, -x withassumption, negX301have shifted := rationalLess.add_left with rationalZero.rational, sumRational, negY, translated302have leftIdentity := rationalAddValue.zero_right with negY303rw leftIdentity at shifted304have associative := rationalAddValue.associative at -y, y, -x with305 negY, assumption, negX306rw← associative at shifted307have inverseY := rationalAddValue.neg_left at y308rw inverseY at shifted309have rightIdentity := rationalAddValue.zero_left with negX310 rwa rightIdentity at shifted311312-- A positive gap y-x has the expected sign, stated without exposing quotient313-- representatives. This is the witness-selection lemma used by open real314-- cuts: if x < y, then x-y belongs to the rational cut at zero.315theorem rationalLess.sub_self_negative (x y : Rational)316requires less : x < y317shows x - y < rationalZero318proof319have translated := rationalLess.add_right at x, y, -y with less320have inverse := rationalAddValue.neg_right at y321rw inverse at translated322unfold rationalSubValue323exact translated324325theorem rationalLess.sub_left (x y z : Rational)326requires less : x < y + z327shows x - y < z328proof329have translated := rationalLess.add_right at x, y + z, -y with less330have cancellation := rationalAddValue.sum_sub_left at y, z with331*{2}332unfold rationalSubValue at cancellation333rw cancellation at translated334unfold rationalSubValue335exact translated336337theorem rationalLess.add_left_of_sub_left (x y z : Rational)338requires less : x - y < z339shows x < y + z340proof341have translated := rationalLess.add_left at x - y, z, y with less342have cancellation := rationalAddValue.add_sub_cancel_left at y, x with343*{2}344 rwa cancellation at translated345346-- The rational arithmetic progression beginning at (a-b)/n with mesh 1/D.347-- It is kept as a quotient-level helper so the Archimedean proof can reason348-- about a finite grid without introducing a new coercion primitive.349def rationalGrid (a b n D k : Nat) : Set:=350 rationalClass(D * a + k * n, D * b, n * D)351352theorem rationalGrid.rational (a b n D k : Nat)353requires nNonzero : n ≠0354requires DNonzero : D ≠0355showsRational(rationalGrid(a, b, n, D, k))356proof357unfold rationalGrid358apply rationalClass.rational359 . exact mul.nonzero with nNonzero, DNonzero360361theorem rationalGrid.zero (a b n D : Nat)362requires nNonzero : n ≠0363requires DNonzero : D ≠0364shows rationalGrid(a, b, n, D, 0) = rationalClass(a, b, n)365proof366unfold rationalGrid367apply rationalClass.eq368 . exact mul.nonzero with nNonzero, DNonzero369 . exact nNonzero370 . settlewith mul.left_zero, mul.right_zero, add.right_unit, mul.associative371372theorem rationalGrid.successor (a b n D k : Nat)373requires nNonzero : n ≠0374requires DNonzero : D ≠0375shows rationalGrid(a, b, n, D, succ(k)) =376 rationalAddValue(rationalGrid(a, b, n, D, k), rationalClass(1, 0, D))377proof378have nDNonzero := mul.nonzero with nNonzero, DNonzero379have gridComputed := rationalAddValue.classes at380 D * a + k * n, D * b, n * D, 1, 0, D with381 nDNonzero, DNonzero382have stepEquality : rationalGrid(a, b, n, D, succ(k)) =383 rationalClassSum(D * a + k * n, D * b, n * D, 1, 0, D)384unfold rationalGrid385unfold rationalClassSum386apply rationalClass.eq387 . exact nDNonzero388 . exact mul.nonzero with nDNonzero, DNonzero389 . simpwith mul.right_zero, mul.left_zero, add.right_unit,390 mul.right_unit, mul.left_unit391ring392have computedReverse : rationalClassSum(393 D * a + k * n, D * b, n * D, 1, 0, D) =394 rationalAddValue(rationalGrid(a, b, n, D, k), rationalClass(1, 0, D))395unfold rationalGrid396simp397calc398 rationalGrid(a, b, n, D, succ(k)) =399 rationalClassSum(D * a + k * n, D * b, n * D, 1, 0, D) := stepEquality400 _ = rationalAddValue(rationalGrid(a, b, n, D, k), rationalClass(1, 0, D)) := computedReverse401402theorem rationalGrid.natural_step (a b n D k : Nat)403requires nNonzero : n ≠0404requires DNonzero : D ≠0405shows rationalGrid(a, b, n, D, D * k) =406 rationalAddValue(rationalClass(a, b, n), rationalClass(k, 0, 1))407proof408have oneNonzero : 1≠0409intro oneZero410arith411have sumComputed := rationalAddValue.classes at412 a, b, n, k, 0, 1with nNonzero, oneNonzero413rw sumComputed414unfold rationalGrid415unfold rationalClassSum416apply rationalClass.eq417 . exact mul.nonzero with nNonzero, DNonzero418 . exact mul.nonzero with nNonzero, oneNonzero419 . ring420421-- Every rational lies below a displayed natural number. The witness is422-- canonical: for (a-b)/m we may take a+1. This is the first423-- Archimedean boundary lemma; clients need not inspect representatives.424theoremRational.below_natural (x : Rational)425shows∃ n, Nat(n) ∧426 x < rationalClass(n, 0, 1)427proof428obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=429Rational.coordinates withassumption430witness succ(a)431rw xShape432have oneNonzero : 1≠0433intro oneZero434arith435have cross : Less(a, add(mul(m, succ(a)), b))436have shape := natural.zero_or_successor with mNatural437cases shape with zero | successor438 . exfalso439apply mNonzero440exact zero441 . obtain⟨j, jNatural, mShape⟩:= successor442rw mShape443have successorNatural := Naturals.constructor.succ with aNatural444have productStep := mul.succ_left with jNatural, successorNatural445rw productStep446have jProductNatural : Nat(mul(j, succ(a))) bytypecheck447have aLessSuccessor : a < succ(a)448apply Less.of_membership449 . exact membership.self_successor with aNatural450have productNonnegative := Grace.Core.Nat.Order.LessEqual.zero with jProductNatural451have first := Less.add_LessEqual with452 aNatural, successorNatural, Naturals.constructor.zero, jProductNatural, aLessSuccessor, productNonnegative453have aZero := add.right_unit with aNatural454rw aZero at first455have bNonnegative := Grace.Core.Nat.Order.LessEqual.zero with bNatural456have sumNatural : Nat(add(succ(a), mul(j, succ(a)))) bytypecheck457have final := Less.add_LessEqual with458 aNatural, sumNatural, Naturals.constructor.zero, bNatural, first, bNonnegative459 rwa aZero at final460have classLaw := rationalLess.classes at461 a, b, m, succ(a), 0, 1with mNonzero, oneNonzero462have leftShape : add(mul(1, a), mul(m, 0)) = a byring463have rightShape : add(mul(m, succ(a)), mul(1, b)) =464 add(mul(m, succ(a)), b)465ring466rw [leftShape, rightShape] at classLaw467exact classLaw.backward with cross468469-- The symmetric half of rational unboundedness: every rational lies above a470-- negative displayed natural. Negation transports the preceding witness,471-- so no second representative calculation is needed.472theoremRational.above_negative_natural (x : Rational)473shows∃ n, Nat(n) ∧474 rationalClass(0, n, 1) < x475proof476have negativeRational := rationalNegValue.rational at x477obtain⟨n, nNatural, below⟩:=Rational.below_natural with negativeRational478witness n479have oneNatural := Naturals.constructor.succ with Naturals.constructor.zero480have oneNonzero : 1≠0481intro oneZero482arith483have naturalRational := rationalClass.rational with484 nNatural, Naturals.constructor.zero, oneNatural, oneNonzero485have reversed := rationalLess.neg_reverse with below486have involutive := rationalNegValue.involutive at x487rw [involutive, rationalNegValue.notation] at reversed488have negativeClass := rationalNegValue.classes with489 nNatural, Naturals.constructor.zero, oneNatural, oneNonzero490rw negativeClass at reversed491unfold rationalClassNeg at reversed492exact reversed493494theorem rationalLess.natural_successor (n : Nat)495shows relates(rationalLess,496 rationalClass(n, 0, 1), rationalClass(succ(n), 0, 1))497proof498have oneNonzero : 1≠0499intro oneZero500arith501apply rationalLess.classes.backward with oneNonzero, oneNonzero502have succNatural := Naturals.constructor.succ at n503have nUnit := mul.left_unit at n504have zeroUnit := mul.left_unit with Naturals.constructor.zero505have succUnit := mul.left_unit with succNatural506have nZero := add.right_unit at n507have succAddZero := add.right_unit with succNatural508rw [nUnit, zeroUnit, succUnit, nZero, succAddZero]509apply Less.of_membership510 . exact membership.self_successor at n511512theorem rationalLess.positive_natural_successor (n : Nat)513shows relates(rationalLess, rationalZero, rationalClass(succ(n), 0, 1))514proof515have oneNonzero : 1≠0516intro oneZero517arith518unfold rationalZero519apply rationalLess.classes.backward with oneNonzero, oneNonzero520have succNatural := Naturals.constructor.succ at n521have zeroUnit := mul.left_unit with Naturals.constructor.zero522have succUnit := mul.left_unit with succNatural523have zeroZero := add.right_unit with Naturals.constructor.zero524have succAddZero := add.right_unit with succNatural525rw [zeroUnit, succUnit, zeroZero, succAddZero]526have succNonzero : succ(n) ≠0527intro succZero528have zeroNotSucc := Naturals.disjoint.zero.succ at n529apply zeroNotSucc530rw succZero531rfl532have positive := Less.add_positive at0, succ(n) with succNonzero533 simpa [add.left_unit] using positive534535-- Every positive rational dominates a positive unit fraction. This is the536-- mesh-selection form of the Archimedean property used for finite rational537-- grids; clients never need to inspect the chosen denominator.538theorem rationalZero.lt_one539shows rationalZero < rationalOne540proof541have step := rationalLess.positive_natural_successor at0with*542unfold rationalOne543exact step544545theorem rationalLess.exists_positive_unit_fraction (x : Rational)546requires positive : rationalZero < x547shows∃ D, Nat(D) ∧ D ≠0∧548 rationalZero < rationalClass(1, 0, D) ∧549 rationalClass(1, 0, D) < x550proof551obtain⟨a, aNatural, b, bNatural, m, mNatural, mNonzero, xShape⟩:=552Rational.coordinates withassumption553have oneNatural := Naturals.constructor.succ with Naturals.constructor.zero554have oneNonzero : 1≠0555intro oneZero556arith557have displayedPositive := positive558rw xShape at displayedPositive559unfold rationalZero at displayedPositive560have numeratorPositive := rationalLess.classes.forward with oneNonzero, mNonzero, displayedPositive561have bLessA : b < a562 simpa [mul.left_zero, mul.right_zero, mul.left_unit,563 mul.right_unit, add.left_unit, add.right_unit] using numeratorPositive564witness2* m565have twoNonzero : 2≠0566intro twoZero567arith568have denominatorNonzero := mul.nonzero with twoNonzero, mNonzero569constructor570 . exact denominatorNonzero571constructor572 . unfold rationalZero573apply rationalLess.classes.backward with oneNonzero, denominatorNonzero574have zeroLessOne : 0 < 1575apply Less.of_membership576 . exact membership.self_successor with Naturals.constructor.zero577ring_nf578exact zeroLessOne579 . rw xShape580apply rationalLess.classes.backward with denominatorNonzero, mNonzero581have oneLessTwo : 1 < 2582apply Less.of_membership583 . exact membership.self_successor with oneNatural584have scaled := Less.mul_left with mNonzero, oneLessTwo585have unit : m *1= m byring586have twoMComm : m *2=2* m byring587rw [unit, twoMComm] at scaled588have mLessTwoM := scaled589have productNatural : Nat((2* m) * b) bytypecheck590have productReflexive := LessEqual.reflexive with productNatural591have lower := Less.add_LessEqual with mLessTwoM, productReflexive592have succBLeA := bLessA593have upper := LessEqual.mul_left at succ(b), a, 2* m with594 succBLeA595have lowerShape : m + (2* m) * b = m *1+ (2* m) * b byring596have middleShape : (2* m) + (2* m) * b = (2* m) * succ(b) byring597have upperShape : (2* m) * a = (2* m) * a + m *0byring598rw [lowerShape, middleShape] at lower599rw upperShape at upper600exact Less.transitive_LessEqual with lower, upper601602-- Given positive rationals a and g, choose a positive rational delta below603-- one whose product with a is smaller than g. This is the reusable604-- Archimedean approximation step behind multiplication of open real cuts.605theorem rationalLess.exists_small_positive_multiplier (a g : Rational)606requires positiveA : rationalZero < a607requires positiveG : rationalZero < g608shows∃ delta ∈ ℚ,609 rationalZero < delta ∧ delta < rationalOne ∧ a * delta < g610proof611obtain⟨D, dNatural, dNonzero, unitPositive, unitBelowG⟩:= rationalLess.exists_positive_unit_fraction with612 positiveG613obtain⟨N, nNatural, aBelowN⟩:=614Rational.below_natural at a withassumption615have oneNatural : Nat(1) bytypecheck616have oneNonzero : 1≠0617intro oneZero618arith619have twoNonzero : 2≠0620intro twoZero621arith622have nNonzero : N≠0623intro nZero624have aBelowZero := aBelowN625rw nZero at aBelowZero626have zeroShape : rationalClass(0, 0, 1) = rationalZero627unfold rationalZero628rfl629rw zeroShape at aBelowZero630have cycle := rationalLess.transitive with positiveA, aBelowZero631have impossible := rationalLess.irreflexive_on632exact impossible with rationalZero, cycle633have dnNonzero := mul.nonzero with dNonzero, nNonzero634have eNonzero := mul.nonzero with twoNonzero, dnNonzero635have deltaRational := rationalClass.rational at1, 0, 2* (D * N) with636 eNonzero637have naturalRational := rationalClass.rational at N, 0, 1with638 oneNonzero639have deltaPositive : rationalZero < rationalClass(1, 0, 2* (D * N))640unfold rationalZero641apply rationalLess.classes.backward with oneNonzero, eNonzero642have zeroLessOne : 0 < 1643apply Less.of_membership644 . exact membership.self_successor at0with Naturals.constructor.zero645ring_nf646exact zeroLessOne647have oneLessTwo : 1 < 2648apply Less.of_membership649 . exact membership.self_successor at1with oneNatural650have dnPositive := Less.add_positive at0, D * N with dnNonzero651have oneLeDN : 1≤ D * N652unfold Less at dnPositive653 simpa [add.left_unit] using dnPositive654have dnLessE := Less.mul_left with dnNonzero, oneLessTwo655have eShape : (D * N) *2=2* (D * N) byring656rw eShape at dnLessE657simp [mul.right_unit] at dnLessE658have oneLessE : 1 < 2* (D * N) byexact LessEqual.transitive_Less with oneLeDN, dnLessE659have deltaBelowOne : rationalClass(1, 0, 2* (D * N)) < rationalOne660unfold rationalOne661apply rationalLess.classes.backward with eNonzero, oneNonzero662ring_nf663ring_nfat oneLessE664exact oneLessE665have scaled := rationalLess.mul_right with deltaPositive, aBelowN666have naturalTimesDelta : rationalClass(N, 0, 1) *667 rationalClass(1, 0, 2* (D * N)) = rationalClass(1, 0, 2* D)668rw [rationalMulValue.notation, rationalMulValue.classes]669unfold rationalClassMul670apply rationalClass.eq671 . exact mul.nonzero at1, 2* (D * N) with oneNonzero, eNonzero672 . exact mul.nonzero at2, D with twoNonzero, dNonzero673 . ring674rw naturalTimesDelta at scaled675have dLessTwoD := Less.mul_left with dNonzero, oneLessTwo676ring_nfat dLessTwoD677have twoDNonzero := mul.nonzero with twoNonzero, dNonzero678have halfUnitRational := rationalClass.rational at1, 0, 2* D with679 twoDNonzero680have unitRational := rationalClass.rational at1, 0, D with dNonzero681have halfUnitBelowUnit : rationalClass(1, 0, 2* D) < rationalClass(1, 0, D)682apply rationalLess.classes.backward with twoDNonzero, dNonzero683ring_nf684exact dLessTwoD685have productBelowG : a * rationalClass(1, 0, 2* (D * N)) < g686calc687 a * rationalClass(1, 0, 2* (D * N)) < rationalClass(1, 0, 2* D) := scaled688 _ < rationalClass(1, 0, D) := halfUnitBelowUnit689 _ < g := unitBelowG690witness rationalClass(1, 0, 2* (D * N))691constructor692exact deltaRational693 . refine⟨deltaPositive, deltaBelowOne, productBelowG⟩694695-- If q < a with a positive, a multiplier can be chosen strictly between zero696-- and one while keeping q below the scaled value. Written this way, clients697-- of open cuts can use the lemma without inspecting its Archimedean witness.698theorem rationalLess.exists_scale_below_one (q a : Rational)699requires positiveA : rationalZero < a700requires qLessA : q < a701shows∃ b ∈ ℚ,702 rationalZero < b ∧ b < rationalOne ∧ q < a * b703proof704have gapRational := rationalSubValue.rational at a, q with705*{2}706have gapPositive := rationalLess.sub_positive with qLessA707obtain⟨delta, deltaInQ, deltaPositive, deltaBelowOne, productSmall⟩:=708 rationalLess.exists_small_positive_multiplier at a, a - q with709assumption, gapRational, positiveA, gapPositive710have deltaRational : Rational(delta) bytypecheck711have oneRational := rationalOne.rational712have bRational := rationalSubValue.rational with oneRational, deltaRational713have bPositive := rationalLess.sub_positive with deltaBelowOne714have translatedDelta := rationalLess.add_right with715 rationalZero.rational, deltaRational, bRational, deltaPositive716have zeroAtB := rationalAddValue.zero_left with bRational717have deltaCancel := rationalAddValue.add_sub_cancel_left with deltaRational, oneRational718rw [zeroAtB, deltaCancel] at translatedDelta719have bBelowOne : rationalOne - delta < rationalOne byexact translatedDelta720have productRational := rationalMulValue.rational at a, delta with721assumption, deltaRational722have shifted := rationalLess.add_left at723 a * delta, a - q, q with724 productRational, gapRational, assumption, productSmall725have gapCloses := rationalAddValue.add_sub_cancel_left at q, a with726*{2}727rw gapCloses at shifted728have sumRational := rationalAddValue.rational at q, a * delta with729assumption, productRational730have negProductRational := rationalNegValue.rational with productRational731have shiftedBack := rationalLess.add_right at732 q + a * delta, a, -(a * delta) with733 sumRational, assumption, negProductRational, shifted734have leftCancel := rationalAddValue.add_sub_cancel_right at q, a * delta with735assumption, productRational736unfold rationalSubValue at leftCancel737rw leftCancel at shiftedBack738have productShape : a * (rationalOne - delta) = a - a * delta739unfold rationalSubValue740have distributed := rationalMulValue.distributive_left at741 a, rationalOne, -delta with742assumption, oneRational,743 rationalNegValue.rational at delta with deltaRational744have oneProduct := rationalMulValue.one_right at a745have negProduct := rationalMulValue.neg_right at a, delta with746assumption, deltaRational747 rwa [oneProduct, negProduct] at distributed748have shiftedBackSub : q < a - a * delta749unfold rationalSubValue750exact shiftedBack751rw← productShape at shiftedBackSub752witness rationalOne - delta753constructor754exact bRational755 . refine⟨bPositive, bBelowOne, shiftedBackSub⟩756