1-- Multiplication of nonnegative Dedekind real numbers2-- 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.Real.Multiplication8import Negation910-- The multiplicative unit is the rational cut at one, with its11-- overloaded numeral available as soon as the real carrier is known.12def realOne : Real:= rationalCut(rationalOne)1314theorem realOne.real15showsReal(realOne)16proof17unfold realOne18exact rationalCut.real with rationalOne.rational1920instance realOne.of_nat21shows OfNat(ℝ, 1, realOne)22proof23constructor24 . typecheck25 . exact realOne.real2627notation numeral "1"via OfNat(ℝ, 1, _) forReal2829theorem realZero.lt_one30shows0 < realOne31proof32have rationalPositive := rationalLess.positive_natural_successor with Naturals.constructor.zero33have zeroLessOne : rationalZero < rationalOne by simpa [rationalOne] using rationalPositive34have strict := rationalCut.strict_mono with rationalZero.rational, rationalOne.rational, zeroLessOne35apply realLess.characterization.backward36unfold realZero37unfold realOne38exact strict3940theorem realZero.ne_one41shows realZero ≠ realOne42proof43intro equal44have positive := realZero.lt_one45rw equal at positive46have impossible := realLess.irreflexive_on47exact impossible with realOne, positive4849-- For nonnegative cuts A and B, their product contains every negative50-- rational and every rational strictly below a product of positive members.51-- The explicit rational bounds on a and b make all arithmetic notation52-- independently readable and resolvable.53def realPosMulCut (A B : Set) : Set:=54 { q ∈ ℚ |55 q < rationalZero ∨56∃ a ∈ ℚ, a ∈ A ∧∃ b ∈ ℚ, b ∈ B ∧57 rationalZero < a ∧ rationalZero < b ∧ q < a * b }5859-- Every cut omits a positive rational. Starting from any omitted rational,60-- move above it to the next displayed natural; downward closure shows that61-- this larger rational remains outside the cut.62theorem DedekindCut.exists_positive_upper (A : Set)63requires cut : DedekindCut(A)64shows∃ u ∈ ℚ, rationalZero < u ∧¬(u ∈ A)65proof66have proper := DedekindCut.proper with cut67obtain⟨r, rInQ, rMissing⟩:= ProperSubset.missing with proper68have rRational : Rational(r) bytypecheck69obtain⟨n, nNatural, rBelowN⟩:=Rational.below_natural with rRational70have oneNonzero : 1≠071intro oneZero72arith73have nRational := rationalClass.rational at n, 0, 1with oneNonzero74have nBelowSucc := rationalLess.natural_successor with nNatural75have uRational := rationalClass.rational at succ(n), 0, 1with oneNonzero76have rBelowU : r < rationalClass(succ(n), 0, 1)77calc78 r < rationalClass(n, 0, 1) := rBelowN79 _ < rationalClass(succ(n), 0, 1) := nBelowSucc80witness rationalClass(succ(n), 0, 1)81constructor82exact uRational83constructor84 . exact rationalLess.positive_natural_successor at n with nNatural85 . intro uInA86have rInA := DedekindCut.downward with cut, uInA, rInQ, rBelowU87exact rMissing with rInA8889theorem realPosMulCut.subset_rationals (A B : Set)90shows realPosMulCut(A, B) ⊆ ℚ91proof92simp9394theorem realPosMulCut.nonempty (A B : Set)95shows Nonempty(realPosMulCut(A, B))96proof97obtain⟨q, qInQ, qNegative⟩:= rationalLess.exists_below with rationalZero.rational98witness q99apply realPosMulCut.membership.backward100refine⟨qInQ, _⟩101left102exact qNegative103104theorem realPosMulCut.nonnegative (A B : Set)105shows realZero ⊆ realPosMulCut(A, B)106proof107intros q qInZero108unfold realZero at qInZero109obtain⟨qInQ, qNegative⟩:= rationalCut.membership.forward with qInZero110apply realPosMulCut.membership.backward111refine⟨qInQ, _⟩112left113exact qNegative114115theorem realPosMulCut.downward (A B p q : Set)116requires qInProduct : q ∈ realPosMulCut(A, B)117requires pInQ : p ∈ ℚ118requires pLessQ : relates(rationalLess, p, q)119shows p ∈ realPosMulCut(A, B)120proof121obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct122cases rest with negative | product123 . have pNegative := rationalLess.transitive at p, q, rationalZero with124 pLessQ, negative125apply realPosMulCut.membership.backward126refine⟨pInQ, _⟩127left128exact pNegative129 . rcases product with130⟨a, aInQ, aInA, b, bInQ, bInB, positiveA, positiveB, qLessProduct⟩131have pLessProduct := rationalLess.transitive with pLessQ, qLessProduct132apply realPosMulCut.membership.backward133refine⟨pInQ, _⟩134right135refine⟨a, aInQ, aInA, b, bInQ, bInB,136 positiveA, positiveB, pLessProduct⟩137138theorem realPosMulCut.no_greatest (A B q : Set)139requires qInProduct : q ∈ realPosMulCut(A, B)140shows∃ s ∈ realPosMulCut(A, B), relates(rationalLess, q, s)141proof142obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct143have qRational : Rational(q) bytypecheck144cases rest with negative | product145 . obtain⟨t, tInQ, qLessT, tNegative⟩:=146 rationalLess.dense at q, rationalZero with147 qRational, rationalZero.rational, negative148refine⟨t, _, qLessT⟩149apply realPosMulCut.membership.backward150refine⟨tInQ, _⟩151left152exact tNegative153 . rcases product with154⟨a, aInQ, aInA, b, bInQ, bInB, positiveA, positiveB, qLessProduct⟩155obtain⟨s2, s2InQ, qLessS2, s2LessProduct⟩:= rationalLess.dense with qLessProduct156refine⟨s2, _, qLessS2⟩157apply realPosMulCut.membership.backward158refine⟨s2InQ, _⟩159right160refine⟨a, aInQ, aInA, b, bInQ, bInB,161 positiveA, positiveB, s2LessProduct⟩162163theorem realPosMulCut.proper (A B : Real)164shows realPosMulCut(A, B) ≠ ℚ165proof166have cutA :=Real.characterization.forward at A withassumption167have cutB :=Real.characterization.forward at B withassumption168obtain⟨u, uInQ, positiveU, uMissing⟩:= DedekindCut.exists_positive_upper with cutA169obtain⟨v, vInQ, positiveV, vMissing⟩:= DedekindCut.exists_positive_upper with cutB170have uRational : Rational(u) bytypecheck171have vRational : Rational(v) bytypecheck172have uvRational := rationalMulValue.rational with uRational, vRational173have positiveUV := rationalLess.mul_positive with positiveU, positiveV174intro allRationals175have uvInProduct : u * v ∈ realPosMulCut(A, B)176rw allRationals177exact uvRational178obtain⟨uvInQ, rest⟩:= realPosMulCut.membership.forward with uvInProduct179cases rest with negative | product180 . have cycle := rationalLess.transitive at181 rationalZero, u * v, rationalZero with positiveUV, negative182have impossible := rationalLess.irreflexive_on183exact impossible with rationalZero, cycle184 . rcases product with185⟨a, aInQ, aInA, b, bInQ, bInB, positiveA, positiveB, uvLessAB⟩186have aLessU := DedekindCut.lt_missing with cutA, aInA, uInQ, uMissing187have bLessV := DedekindCut.lt_missing with cutB, bInB, vInQ, vMissing188have abLessUB := rationalLess.mul_right with positiveB, aLessU189have ubLessUV := rationalLess.mul_left with positiveU, bLessV190have abLessUV : a * b < u * v191calc192 a * b < u * b := abLessUB193 _ < u * v := ubLessUV194have cycle : u * v < u * v195calc196 u * v < a * b := uvLessAB197 _ < u * v := abLessUV198have impossible := rationalLess.irreflexive_on199exact impossible with u * v, uvInQ, cycle200201theorem realPosMulCut.cut (A B : Real)202shows DedekindCut(realPosMulCut(A, B))203proof204have subset := realPosMulCut.subset_rationals at A, B205have inhabited := realPosMulCut.nonempty at A, B206have proper := realPosMulCut.proper at A, B with*207unfold DedekindCut208refine⟨subset, inhabited, proper, _, _⟩209 . intros q qInProduct p pInQ pLessQ210exact realPosMulCut.downward with qInProduct, pInQ, pLessQ211 . intros q qInProduct212exact realPosMulCut.no_greatest with qInProduct213214theorem realPosMulCut.real (A B : Real)215showsReal(realPosMulCut(A, B))216proof217applyReal.characterization.backward218exact realPosMulCut.cut with*219220theorem realPosMulCut.commutative (A B : Real)221shows realPosMulCut(A, B) = realPosMulCut(B, A)222proof223ext q224constructor225 . intro qInProduct226obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct227cases rest with negative | product228 . apply realPosMulCut.membership.backward at B, A, q229refine⟨qInQ, _⟩230left231exact negative232 . rcases product with233⟨a, aInQ, aInA, b, bInQ, bInB, positiveA, positiveB, below⟩234have aRational : Rational(a) bytypecheck235have bRational : Rational(b) bytypecheck236have commutative := rationalMulValue.commutative with aRational, bRational237rw commutative at below238apply realPosMulCut.membership.backward239refine⟨qInQ, _⟩240right241refine⟨b, bInQ, bInB, a, aInQ, aInA,242 positiveB, positiveA, below⟩243 . intro qInProduct244obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct245cases rest with negative | product246 . apply realPosMulCut.membership.backward at A, B, q247refine⟨qInQ, _⟩248left249exact negative250 . rcases product with251⟨b2, b2InQ, b2InB, a2, a2InQ, a2InA, positiveB2, positiveA2, below2⟩252have a2Rational : Rational(a2) bytypecheck253have b2Rational : Rational(b2) bytypecheck254have commutative2 := rationalMulValue.commutative with b2Rational, a2Rational255rw commutative2 at below2256apply realPosMulCut.membership.backward257refine⟨qInQ, _⟩258right259refine⟨a2, a2InQ, a2InA, b2, b2InQ, b2InB,260 positiveA2, positiveB2, below2⟩261262-- The one-sided associativity argument records the only approximation needed263-- for open products. A boundary product b*c is moved slightly inward by a264-- positive factor t<1; rational associativity preserves the outer bound.265theorem realPosMulCut.assoc_subset (A B C : Real)266shows realPosMulCut(realPosMulCut(A, B), C) ⊆267 realPosMulCut(A, realPosMulCut(B, C))268proof269intros q qInLeft270obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInLeft271apply realPosMulCut.membership.backward272refine⟨qInQ, _⟩273cases rest with qNegative | product274 . left275exact qNegative276 . rcases product with277⟨x, xInQ, xInAB, c, cInQ, cInC, positiveX, positiveC, qBelowXC⟩278have cRational : Rational(c) bytypecheck279obtain⟨xInQAgain, innerRest⟩:= realPosMulCut.membership.forward with xInAB280cases innerRest with xNegative | factors281 . have cycle := rationalLess.transitive at282 rationalZero, x, rationalZero with positiveX, xNegative283have impossible := rationalLess.irreflexive_on284exfalso285exact impossible with rationalZero, cycle286 . rcases factors with287⟨a, aInQ, aInA, b, bInQ, bInB,288 positiveA, positiveB, xBelowAB⟩289have aRational : Rational(a) bytypecheck290have bRational : Rational(b) bytypecheck291have bcRational := rationalMulValue.rational with bRational, cRational292have abcRational := rationalMulValue.rational with aRational, bcRational293have positiveBC := rationalLess.mul_positive with positiveB, positiveC294have positiveABC := rationalLess.mul_positive with positiveA, positiveBC295have scaledX := rationalLess.mul_right with positiveC, xBelowAB296have qBelowGrouped : q < (a * b) * c297calc298 q < x * c := qBelowXC299 _ < (a * b) * c := scaledX300have associative := rationalMulValue.associative with aRational, bRational, cRational301have qBelowABC : q < a * (b * c) by rwa ← associative302obtain⟨t, tInQ, positiveT, tBelowOne, qBelowScaled⟩:=303 rationalLess.exists_scale_below_one at q, a * (b * c) with304 abcRational, positiveABC, qBelowABC305have tRational : Rational(t) bytypecheck306have yRational := rationalMulValue.rational with bcRational, tRational307have positiveY := rationalLess.mul_positive with positiveBC, positiveT308have yBelowOneScaled := rationalLess.mul_left with positiveBC, tBelowOne309have oneProduct := rationalMulValue.one_right with bcRational310rw oneProduct at yBelowOneScaled311have scaledAssociative := rationalMulValue.associative with aRational, bcRational, tRational312rw scaledAssociative at qBelowScaled313have yInBC : (b * c) * t ∈ realPosMulCut(B, C)314apply realPosMulCut.membership.backward315refine⟨yRational, _⟩316right317refine⟨b, bInQ, bInB, c, cInQ, cInC,318 positiveB, positiveC, yBelowOneScaled⟩319right320refine⟨a, aInQ, aInA, (b * c) * t, yRational, yInBC,321 positiveA, positiveY, qBelowScaled⟩322323theorem realPosMulCut.associative (A B C : Real)324shows realPosMulCut(realPosMulCut(A, B), C) =325 realPosMulCut(A, realPosMulCut(B, C))326proof327apply Subset.antisymmetric328 . exact realPosMulCut.assoc_subset at A, B, C with329*{3}330 . have reverse := realPosMulCut.assoc_subset at C, B, A with331*{3}332have cb := realPosMulCut.commutative at C, B with*333have ba := realPosMulCut.commutative at B, A with*334rw [cb, ba] at reverse335have bcReal := realPosMulCut.real at B, C with*336have abReal := realPosMulCut.real at A, B with*337have outerLeft := realPosMulCut.commutative at338 realPosMulCut(B, C), A with bcReal, assumption339have outerRight := realPosMulCut.commutative at340 C, realPosMulCut(A, B) withassumption, abReal341 rwa [outerLeft, outerRight] at reverse342343theorem realPosMulCut.zero_left (B : Real)344shows realPosMulCut(realZero, B) = realZero345proof346ext q347constructor348 . intro qInProduct349obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct350cases rest with negative | product351 . unfold realZero352apply rationalCut.membership.backward353constructor354 . exact qInQ355 . exact negative356 . rcases product with357⟨a, aInQ, aInZero, b, bInQ, bInB, positiveA, positiveB, below⟩358unfold realZero at aInZero359obtain⟨aAgain, negativeA⟩:= rationalCut.membership.forward with aInZero360have cycle : rationalZero < rationalZero361calc362 rationalZero < a := positiveA363 _ < rationalZero := negativeA364have impossible := rationalLess.irreflexive_on365exfalso366exact impossible with rationalZero, cycle367 . intro qInZero368unfold realZero at qInZero369obtain⟨qInQ, negative⟩:= rationalCut.membership.forward with qInZero370apply realPosMulCut.membership.backward371refine⟨qInQ, _⟩372left373exact negative374375theorem realPosMulCut.zero_right (A : Real)376shows realPosMulCut(A, realZero) = realZero377proof378calc379 realPosMulCut(A, realZero) = realPosMulCut(realZero, A) :=380 realPosMulCut.commutative with realZero.real381 _ = realZero := realPosMulCut.zero_left at A withassumption382383-- The positive-cut product has the expected right unit on nonnegative cuts.384-- The reverse inclusion is the open-cut step: after moving from q to a larger385-- positive member a, rational approximation chooses 0 < b < 1 with q < a*b.386theorem realPosMulCut.one_right (A : Real)387requires nonnegative : realZero ⊆ A388shows realPosMulCut(A, realOne) = A389proof390have cutA :=Real.characterization.forward withassumption391have subsetA := DedekindCut.subset_rationals with cutA392ext q393constructor394 . intro qInProduct395obtain⟨qInQ, rest⟩:= realPosMulCut.membership.forward with qInProduct396cases rest with negative | product397apply nonnegative with q398unfold realZero399exact rationalCut.membership.backward with⟨qInQ, negative⟩400 . rcases product with401⟨a, aInQ, aInA, b, bInQ, bInOne,402 positiveA, positiveB, qBelowProduct⟩403have aRational : Rational(a) bytypecheck404unfold realOne at bInOne405obtain⟨bAgain, bBelowOne⟩:= rationalCut.membership.forward with bInOne406have scaled := rationalLess.mul_left with positiveA, bBelowOne407have oneProduct := rationalMulValue.one_right with aRational408rw oneProduct at scaled409have qBelowA := rationalLess.transitive with qBelowProduct, scaled410exact DedekindCut.downward with cutA, aInA, qInQ, qBelowA411 . intro qInA412by_contra qMissingProduct413have qInQ := subsetA with q, qInA414have qRational : Rational(q) bytypecheck415obtain⟨c, cInA, qBelowC⟩:= DedekindCut.no_greatest with cutA, qInA416have cInQ := subsetA with c, cInA417have cRational : Rational(c) bytypecheck418have distinct : rationalZero ≠ c419intro zeroC420have qNegative := qBelowC421rw← zeroC at qNegative422apply qMissingProduct423apply realPosMulCut.membership.backward424refine⟨qInQ, _⟩425left426exact qNegative427have connected := rationalLess.connected_on428have zeroInQ := rationalZero.rational429have comparison := connected with430 rationalZero, zeroInQ, c, cInQ, distinct431cases comparison with positiveC | cNegative432 . obtain⟨d, dInQ, positiveD, dBelowOne, qBelowProduct⟩:=433 rationalLess.exists_scale_below_one at q, c with434 qRational, cRational, positiveC, qBelowC435have dInOne : d ∈ realOne436unfold realOne437exact rationalCut.membership.backward with⟨dInQ, dBelowOne⟩438apply qMissingProduct439apply realPosMulCut.membership.backward440refine⟨qInQ, _⟩441right442refine⟨c, cInQ, cInA, d, dInQ, dInOne,443 positiveC, positiveD, qBelowProduct⟩444 . have qNegative := rationalLess.transitive at445 q, c, rationalZero with qBelowC, cNegative446apply qMissingProduct447apply realPosMulCut.membership.backward448refine⟨qInQ, _⟩449left450exact qNegative451452theorem realPosMulCut.one_left (A : Real)453requires nonnegative : realZero ⊆ A454shows realPosMulCut(realOne, A) = A455proof456calc457 realPosMulCut(realOne, A) = realPosMulCut(A, realOne) :=458 realPosMulCut.commutative with realOne.real459 _ = A := realPosMulCut.one_right at A with nonnegative460461-- The positive and negative parts are joins with zero. This definition is462-- canonical for lower cuts and avoids making multiplication depend on an463-- arbitrary sign-case presentation.464def realPositivePart (A : Set) : Set:= A ∪ realZero465466theorem realPositivePart.real (A : Real)467showsReal(realPositivePart(A))468proof469have cutA :=Real.characterization.forward withassumption470have cutZero :=Real.characterization.forward with realZero.real471have comparable := DedekindCut.comparable with cutA, cutZero472cases comparable with subsetAZero | subsetZeroA473 . have unionSubset := union2.subset at A, realZero, realZero with474 subsetAZero, Subset.reflexive at realZero475have zeroSubset := union2.subset_right at A, realZero476have equal := Subset.antisymmetric with unionSubset, zeroSubset477unfold realPositivePart478rw equal479exact realZero.real480 . have unionSubset := union2.subset at A, realZero, A with481 Subset.reflexive at A, subsetZeroA482have aSubset := union2.subset_left at A, realZero483have equal := Subset.antisymmetric with unionSubset, aSubset484unfold realPositivePart485 rwa equal486487theorem realPositivePart.zero488shows realPositivePart(realZero) = realZero489proof490unfold realPositivePart491exact union2.idempotent492493theorem realPositivePart.eq_of_nonnegative (A : Real)494requires nonnegative : realZero ⊆ A495shows realPositivePart(A) = A496proof497unfold realPositivePart498have unionSubset := union2.subset at A, realZero, A with499 Subset.reflexive at A, nonnegative500have leftSubset := union2.subset_left at A, realZero501exact Subset.antisymmetric with unionSubset, leftSubset502503theorem realPositivePart.nonnegative (A : Set)504shows realZero ⊆ realPositivePart(A)505proof506unfold realPositivePart507exact union2.subset_right508509theorem realPositivePart.eq_zero_of_nonpositive (A : Real)510requires nonpositive : A ⊆ realZero511shows realPositivePart(A) = realZero512proof513unfold realPositivePart514have unionSubset := union2.subset at A, realZero, realZero with515 nonpositive, Subset.reflexive at realZero516have zeroSubset := union2.subset_right at A, realZero517exact Subset.antisymmetric with unionSubset, zeroSubset518519def realNegativePart (A : Set) : Set:= realPositivePart(realNegCut(A))520521theorem realNegativePart.real (A : Real)522showsReal(realNegativePart(A))523proof524unfold realNegativePart525have negative := realNegCut.real at A526exact realPositivePart.real with negative527528theorem realNegativePart.zero529shows realNegativePart(realZero) = realZero530proof531unfold realNegativePart532rw realNegCut.zero533exact realPositivePart.zero534535theorem realNegativePart.eq_zero_of_nonnegative (A : Real)536requires nonnegative : realZero ⊆ A537shows realNegativePart(A) = realZero538proof539have reversed := realNegCut.subset_reverse with realZero.real, nonnegative540rw realNegCut.zero at reversed541unfold realNegativePart542unfold realPositivePart543have unionSubset := union2.subset at realNegCut(A), realZero, realZero with544 reversed, Subset.reflexive at realZero545have zeroSubset := union2.subset_right at realNegCut(A), realZero546exact Subset.antisymmetric with unionSubset, zeroSubset547548theorem realNegativePart.nonnegative (A : Set)549shows realZero ⊆ realNegativePart(A)550proof551unfold realNegativePart552exact realPositivePart.nonnegative553554theorem realNegativePart.eq_neg_of_nonpositive (A : Real)555requires nonpositive : A ⊆ realZero556shows realNegativePart(A) = realNegCut(A)557proof558have reversed := realNegCut.subset_reverse at A, realZero with559assumption, realZero.real, nonpositive560rw realNegCut.zero at reversed561unfold realNegativePart562exact realPositivePart.eq_of_nonnegative with reversed563564-- Every real is its positive part minus its negative part. Comparable cuts565-- make this the two-case sign argument, but the resulting identity566-- is canonical and can be used without further case splits.567theorem realParts.decomposition (A : Real)568shows realAddCut(realPositivePart(A), realNegCut(realNegativePart(A))) = A569proof570have cutA :=Real.characterization.forward withassumption571have cutZero :=Real.characterization.forward with realZero.real572have comparable := DedekindCut.comparable with cutA, cutZero573cases comparable with nonpositive | nonnegative574 . have positive := realPositivePart.eq_zero_of_nonpositive with nonpositive575have negative := realNegativePart.eq_neg_of_nonpositive with nonpositive576simp [positive, negative, realNegCut.involutive,577 realAddCut.zero_left]578 . have positive := realPositivePart.eq_of_nonnegative with nonnegative579have negative := realNegativePart.eq_zero_of_nonnegative with nonnegative580simp [positive, negative, realNegCut.zero, realAddCut.zero_right]581582-- Canonical signed product: A⁺B⁺ + A⁻B⁻ - A⁺B⁻ - A⁻B⁺. It is expressed583-- entirely through already checked cut constructors, so totality is immediate584-- and later ring laws can reason algebraically instead of splitting on signs.585def realMulCut (A B : Set) : Set:=586 realAddCut(587 realAddCut(588 realPosMulCut(realPositivePart(A), realPositivePart(B)),589 realPosMulCut(realNegativePart(A), realNegativePart(B))),590 realNegCut(591 realAddCut(592 realPosMulCut(realPositivePart(A), realNegativePart(B)),593 realPosMulCut(realNegativePart(A), realPositivePart(B)))))594595theorem realMulCut.real (A B : Real)596showsReal(realMulCut(A, B))597proof598have positiveA := realPositivePart.real at A599have positiveB := realPositivePart.real at B600have negativeA := realNegativePart.real at A601have negativeB := realNegativePart.real at B602have pp := realPosMulCut.real with positiveA, positiveB603have nn := realPosMulCut.real with negativeA, negativeB604have pn := realPosMulCut.real with positiveA, negativeB605have np := realPosMulCut.real with negativeA, positiveB606have positiveSum := realAddCut.real with pp, nn607have negativeSum := realAddCut.real with pn, np608have negatedNegativeSum := realNegCut.real at609 realAddCut(610 realPosMulCut(realPositivePart(A), realNegativePart(B)),611 realPosMulCut(realNegativePart(A), realPositivePart(B))) with negativeSum612unfold realMulCut613exact realAddCut.real at614 realAddCut(615 realPosMulCut(realPositivePart(A), realPositivePart(B)),616 realPosMulCut(realNegativePart(A), realNegativePart(B))),617 realNegCut(618 realAddCut(619 realPosMulCut(realPositivePart(A), realNegativePart(B)),620 realPosMulCut(realNegativePart(A), realPositivePart(B)))) with621 positiveSum, negatedNegativeSum622623theorem realMulCut.of_nonnegative (A B : Real)624requires nonnegativeA : realZero ⊆ A625requires nonnegativeB : realZero ⊆ B626shows realMulCut(A, B) = realPosMulCut(A, B)627proof628have positiveA := realPositivePart.eq_of_nonnegative with nonnegativeA629have positiveB := realPositivePart.eq_of_nonnegative with nonnegativeB630have negativeA := realNegativePart.eq_zero_of_nonnegative with nonnegativeA631have negativeB := realNegativePart.eq_zero_of_nonnegative with nonnegativeB632simp [realMulCut, positiveA, positiveB, negativeA, negativeB,633 realPosMulCut.zero_left, realPosMulCut.zero_right,634 realAddCut.zero_left, realAddCut.zero_right, realNegCut.zero]635636theorem realMulCut.zero_left (B : Real)637shows realMulCut(realZero, B) = realZero638proof639simp [realMulCut, realPositivePart.zero, realNegativePart.zero,640 realPosMulCut.zero_left, realPosMulCut.zero_right,641 realAddCut.zero_left, realAddCut.zero_right, realNegCut.zero]642643theorem realMulCut.commutative (A B : Real)644shows realMulCut(A, B) = realMulCut(B, A)645proof646have positiveA := realPositivePart.real at A647have positiveB := realPositivePart.real at B648have negativeA := realNegativePart.real at A649have negativeB := realNegativePart.real at B650have pp := realPosMulCut.commutative with positiveA, positiveB651have nn := realPosMulCut.commutative with negativeA, negativeB652have pn := realPosMulCut.commutative with positiveA, negativeB653have np := realPosMulCut.commutative with negativeA, positiveB654have crossLeft := realPosMulCut.real with negativeB, positiveA655have crossRight := realPosMulCut.real with positiveB, negativeA656have cross := realAddCut.commutative with crossLeft, crossRight657simp [realMulCut, pp, nn, pn, np, cross]658659theorem realMulCut.zero_right (A : Real)660shows realMulCut(A, realZero) = realZero661proof662calc663 realMulCut(A, realZero) = realMulCut(realZero, A) :=664 realMulCut.commutative with realZero.real665 _ = realZero := realMulCut.zero_left at A withassumption666667theorem realMulCut.one_right (A : Real)668shows realMulCut(A, realOne) = A669proof670have positiveA := realPositivePart.real at A671have negativeA := realNegativePart.real at A672obtain⟨zeroReal, oneReal, properOne⟩:= realLess.characterization.forward with realZero.lt_one673have nonnegativeOne := ProperSubset.subset with properOne674have positiveOne := realPositivePart.eq_of_nonnegative with nonnegativeOne675have negativeOne := realNegativePart.eq_zero_of_nonnegative with nonnegativeOne676have positiveProduct := realPosMulCut.one_right with positiveA, realPositivePart.nonnegative at A677have negativeProduct := realPosMulCut.one_right with negativeA, realNegativePart.nonnegative at A678simp [realMulCut, positiveOne, negativeOne, positiveProduct, negativeProduct,679 realPosMulCut.zero_left, realPosMulCut.zero_right,680 realAddCut.zero_left, realAddCut.zero_right, realParts.decomposition]681682theorem realMulCut.one_left (A : Real)683shows realMulCut(realOne, A) = A684proof685calc686 realMulCut(realOne, A) = realMulCut(A, realOne) :=687 realMulCut.commutative with realOne.real688 _ = A := realMulCut.one_right at A withassumption689690theorem realMulCut.associative_of_nonnegative (A B C : Real)691requires nonnegativeA : realZero ⊆ A692requires nonnegativeB : realZero ⊆ B693requires nonnegativeC : realZero ⊆ C694shows realMulCut(realMulCut(A, B), C) =695 realMulCut(A, realMulCut(B, C))696proof697have abReduction := realMulCut.of_nonnegative with nonnegativeA, nonnegativeB698have bcReduction := realMulCut.of_nonnegative with nonnegativeB, nonnegativeC699have nonnegativeAB := realPosMulCut.nonnegative at A, B700have nonnegativeBC := realPosMulCut.nonnegative at B, C701have leftReduction := realMulCut.of_nonnegative with nonnegativeAB, nonnegativeC702have rightReduction := realMulCut.of_nonnegative with nonnegativeA, nonnegativeBC703have reverseRight : realPosMulCut(A, realPosMulCut(B, C)) =704 realMulCut(A, realPosMulCut(B, C))705rw rightReduction706rfl707calc708 realMulCut(realMulCut(A, B), C) =709 realMulCut(realPosMulCut(A, B), C) :=bysimp [abReduction]710 _ = realPosMulCut(realPosMulCut(A, B), C) := leftReduction711 _ = realPosMulCut(A, realPosMulCut(B, C)) :=712 realPosMulCut.associative at A, B, C with713*{3}714 _ = realMulCut(A, realPosMulCut(B, C)) := reverseRight715 _ = realMulCut(A, realMulCut(B, C)) :=bysimp [bcReduction]716717-- Total real multiplication as a set-valued function graph.718def realMul : Set:=719 { p ∈ ((ℝ × ℝ) × ℝ) |720∃ A ∈ ℝ, ∃ B ∈ ℝ,721 p = ((A, B) ↦ realMulCut(A, B)) }722723def realMulValue (A B : Real) : Real:= realMul((A, B))724725theorem realMul.relates (A B : Real)726shows relates(realMul, (A, B), realMulCut(A, B))727proof728have realA : A ∈ ℝ bysimp [Real]729have realB : B ∈ ℝ bysimp [Real]730unfold relates731apply realMul.membership.backward732constructor733 . apply product.pair at (A, B), realMulCut(A, B), ℝ × ℝ, ℝ734 . exact product.pair with realA, realB735 . exact realMulCut.real at A, B with*{2}736 . refine⟨A, realA, B, realB, rfl⟩737738theorem realMul.factors (input output : Set)739requires mapped : relates(realMul, input, output)740shows∃ A ∈ ℝ, ∃ B ∈ ℝ,741 input = (A, B) ∧ output = realMulCut(A, B)742proof743unfold relates at mapped744simp [realMul.membership] at mapped745rcases mapped with⟨bounded, A, realA, B, realB, shape⟩746obtain⟨inputShape, outputShape⟩:= orderedPair.injective with shape747refine⟨A, realA, B, realB, inputShape, outputShape⟩748749theorem realMul.total750shows TotalBetween(realMul, ℝ × ℝ, ℝ)751proof752intros input inputInProduct753obtain⟨bounded, A, realA, B, realB, inputShape⟩:= product.membership.forward with inputInProduct754have typedA : Real(A) byexact realA755have typedB : Real(B) byexact realB756witness realMulCut(A, B)757constructor758 . exact realMulCut.real with typedA, typedB759 . rw inputShape760exact realMul.relates with typedA, typedB761762theorem realMul.functional763shows Functional(realMul)764proof765intros input y inputY z inputZ766obtain⟨A, realA, B, realB, inputFirst, outputFirst⟩:= realMul.factors with inputY767obtain⟨C, realC, D, realD, inputSecond, outputSecond⟩:= realMul.factors with inputZ768rw inputFirst at inputSecond769obtain⟨sameLeft, sameRight⟩:= orderedPair.injective with inputSecond770rw [outputFirst, outputSecond, sameLeft, sameRight]771rfl772773theorem realMul.function774shows realMul : ℝ × ℝ → ℝ775proof776constructor777intros p hp778simp [realMul.membership] at hp779rcases hp with⟨bounded, witnesses⟩780exact bounded781 . refine⟨realMul.functional, _⟩782exact realMul.total783784instance realMul.operation785shows MulOperation(ℝ, realMul)786proof787exact realMul.function788789notationinfixl70"*"=> call2 via MulOperation(ℝ, _) forReal790791theorem realMulValue.real (A B : Real)792showsReal(A * B)793proof794have realA : A ∈ ℝ bysimp [Real]795have realB : B ∈ ℝ bysimp [Real]796have input := product.pair with realA, realB797obtain⟨C, realC, mapped⟩:= FunctionBetween.exists_value with realMul.function, input798have applied := FunctionBetween.apply_value with realMul.function, input, mapped799unfold call2800rw applied801exact realC802803theorem realMulValue.cut (A B : Real)804shows A * B = realMulCut(A, B)805proof806have realA : A ∈ ℝ bysimp [Real]807have realB : B ∈ ℝ bysimp [Real]808have input := product.pair with realA, realB809have mapped := realMul.relates at A, B with*810unfold call2811exact FunctionBetween.apply_value with realMul.function, input, mapped812813theorem realMulValue.commutative (A B : Real)814shows A * B = B * A815proof816rw [realMulValue.cut, realMulValue.cut]817exact realMulCut.commutative with*818819theorem realMulValue.zero_left (A : Real)820shows0* A =0821proof822calc823 realZero * A = realMulCut(realZero, A) :=824 realMulValue.cut with realZero.real825 _ = realZero := realMulCut.zero_left at A withassumption826827theorem realMulValue.zero_right (A : Real)828shows A *0=0829proof830calc831 A * realZero = realZero * A :=832 realMulValue.commutative with realZero.real833 _ = realZero := realMulValue.zero_left at A withassumption834835theorem realMulValue.one_right_of_nonnegative (A : Real)836requires nonnegative : realZero ⊆ A837shows A *1= A838proof839obtain⟨zeroReal, oneReal, properOne⟩:= realLess.characterization.forward with realZero.lt_one840have nonnegativeOne := ProperSubset.subset with properOne841calc842 A * realOne = realMulCut(A, realOne) :=843 realMulValue.cut with realOne.real844 _ = realPosMulCut(A, realOne) :=845 realMulCut.of_nonnegative at A, realOne with846assumption, realOne.real, nonnegative, nonnegativeOne847 _ = A := realPosMulCut.one_right at A with nonnegative848849theorem realMulValue.one_left_of_nonnegative (A : Real)850requires nonnegative : realZero ⊆ A851shows1* A = A852proof853calc854 realOne * A = A * realOne :=855 realMulValue.commutative with realOne.real856 _ = A := realMulValue.one_right_of_nonnegative at A with857assumption, nonnegative858859theorem realMulValue.one_right (A : Real)860shows A *1= A861proof862calc863 A * realOne = realMulCut(A, realOne) :=864 realMulValue.cut with realOne.real865 _ = A := realMulCut.one_right at A withassumption866867theorem realMulValue.one_left (A : Real)868shows1* A = A869proof870calc871 realOne * A = A * realOne :=872 realMulValue.commutative with realOne.real873 _ = A := realMulValue.one_right at A withassumption874875theorem realMulValue.associative_of_nonnegative (A B C : Real)876requires nonnegativeA : realZero ⊆ A877requires nonnegativeB : realZero ⊆ B878requires nonnegativeC : realZero ⊆ C879shows (A * B) * C = A * (B * C)880proof881have abReal := realMulValue.real at A, B with*882have bcReal := realMulValue.real at B, C with*883have abCut := realMulValue.cut at A, B with*884have bcCut := realMulValue.cut at B, C with*885have leftCut := realMulValue.cut at A * B, C with abReal, assumption886have rightCut := realMulValue.cut at A, B * C withassumption, bcReal887have leftInner : realMulCut(A * B, C) =888 realMulCut(realMulCut(A, B), C)889rw abCut890rfl891have rightInner : realMulCut(A, realMulCut(B, C)) =892 realMulCut(A, B * C)893rw bcCut894rfl895have reverseRight : realMulCut(A, B * C) = A * (B * C)896rw rightCut897rfl898calc899 (A * B) * C = realMulCut(A * B, C) := leftCut900 _ = realMulCut(realMulCut(A, B), C) := leftInner901 _ = realMulCut(A, realMulCut(B, C)) :=902 realMulCut.associative_of_nonnegative at A, B, C with903 nonnegativeA, nonnegativeB, nonnegativeC904 _ = realMulCut(A, B * C) := rightInner905 _ = A * (B * C) := reverseRight906907instance realMul.identity908shows Identity(ℝ, realMul, realOne)909proof910constructor911 . exact realOne.real912 . intros A realA913have typedA : Real(A) byexact realA914constructor915 . exact realMulValue.one_left with typedA916 . exact realMulValue.one_right with typedA917918-- A real strictly above zero contains a strictly positive rational. This is919-- the witness form of positivity used by multiplication: proper inclusion920-- supplies a new member, roundedness moves above it, and connectedness rules921-- out the larger member being nonpositive.922theorem RealLess.exists_positive_member (A : Real)923requires positive : 0 < A924shows∃ a ∈ A, rationalZero < a925proof926obtain⟨zeroReal, realA, proper⟩:= realLess.characterization.forward with positive927obtain⟨q, qInA, qMissingZero⟩:= ProperSubset.missing with proper928have cutA :=Real.characterization.forward at A withassumption929obtain⟨a, aInA, qLessA⟩:= DedekindCut.no_greatest with cutA, qInA930have subsetA := DedekindCut.subset_rationals with cutA931have qInQ := subsetA with q, qInA932have aInQ := subsetA with a, aInA933have zeroInQ := rationalZero.rational934have distinct : rationalZero ≠ a935intro equal936have qNegative : q < rationalZero by rwa equal937apply qMissingZero938unfold realZero939apply rationalCut.membership.backward940constructor941 . exact qInQ942 . exact qNegative943have connected := rationalLess.connected_on944have comparison := connected with945 rationalZero, zeroInQ, a, aInQ, distinct946cases comparison with positiveA | aNegative947 . refine⟨a, aInA, positiveA⟩948 . have qNegative := rationalLess.transitive at q, a, rationalZero with949 qLessA, aNegative950exfalso951apply qMissingZero952unfold realZero953apply rationalCut.membership.backward954constructor955 . exact qInQ956 . exact qNegative957958-- The positive-cut product of two positive reals is positive. The proof959-- exposes the familiar mathematical witnesses a > 0 and b > 0, then uses960-- rational density to put a member of the product above zero.961theorem realPosMulCut.positive (A B : Real)962requires positiveA : 0 < A963requires positiveB : 0 < B964shows realZero < realPosMulCut(A, B)965proof966have productReal := realPosMulCut.real at A, B with*967have zeroSubset : realZero ⊆ realPosMulCut(A, B)968intros q qInZero969unfold realZero at qInZero970obtain⟨qInQ, qNegative⟩:= rationalCut.membership.forward with qInZero971apply realPosMulCut.membership.backward972refine⟨qInQ, _⟩973left974exact qNegative975obtain⟨a, aInA, positiveRationalA⟩:= RealLess.exists_positive_member with positiveA976obtain⟨b, bInB, positiveRationalB⟩:= RealLess.exists_positive_member with positiveB977have cutA :=Real.characterization.forward at A withassumption978have cutB :=Real.characterization.forward at B withassumption979have subsetA := DedekindCut.subset_rationals with cutA980have subsetB := DedekindCut.subset_rationals with cutB981have aInQ := subsetA with a, aInA982have bInQ := subsetB with b, bInB983have aRational : Rational(a) bytypecheck984have bRational : Rational(b) bytypecheck985have productPositive := rationalLess.mul_positive with positiveRationalA, positiveRationalB986have productRational := rationalMulValue.rational with aRational, bRational987obtain⟨s, sInQ, sPositive, sBelowProduct⟩:= rationalLess.dense with988 rationalZero.rational, productRational, productPositive989have sInProduct : s ∈ realPosMulCut(A, B)990apply realPosMulCut.membership.backward991refine⟨sInQ, _⟩992right993refine⟨a, aInQ, aInA, b, bInQ, bInB,994 positiveRationalA, positiveRationalB, sBelowProduct⟩995have sMissingZero : ¬(s ∈ realZero)996intro sInZero997unfold realZero at sInZero998obtain⟨sAgain, sNegative⟩:= rationalCut.membership.forward with sInZero999have cycle := rationalLess.transitive with sPositive, sNegative1000have impossible := rationalLess.irreflexive_on1001exact impossible with rationalZero, cycle1002have unequal : realZero ≠ realPosMulCut(A, B)1003intro equal1004apply sMissingZero1005 rwa equal1006have proper : realZero ⊂ realPosMulCut(A, B)1007constructor1008 . exact zeroSubset1009 . exact unequal1010apply realLess.characterization.backward1011unfold RealLess1012refine⟨realZero.real, productReal, proper⟩10131014-- Positivity for the public, signed multiplication operation. Strict1015-- positivity supplies the two nonnegative inclusions, so the canonical sign1016-- decomposition reduces definitionally to the positive-cut product.1017theorem realMulValue.positive (A B : Real)1018requires positiveA : 0 < A1019requires positiveB : 0 < B1020shows0 < A * B1021proof1022have orderA := realLess.characterization.forward with positiveA1023have orderB := realLess.characterization.forward with positiveB1024rcases orderA with⟨zeroRealA, realA, properA⟩1025rcases orderB with⟨zeroRealB, realB, properB⟩1026have nonnegativeA := ProperSubset.subset with properA1027have nonnegativeB := ProperSubset.subset with properB1028have cutPositive := realPosMulCut.positive with positiveA, positiveB1029have valueCut := realMulValue.cut at A, B with*1030have reduction := realMulCut.of_nonnegative with nonnegativeA, nonnegativeB1031 rwa [valueCut, reduction]10321033instance realMul.positive1034shows MulPositive(ℝ, realMul, realZero, realLess)1035proof1036intros A realA B realB positiveA positiveB1037exact realMulValue.positive with positiveA, positiveB10381039instance realMul.magma1040shows IsMagma(ℝ, realMul)1041proof1042exact realMul.function10431044instance realMul.commutative1045shows Commutative(ℝ, realMul)1046proof1047intros A realA B realB1048have typedA : Real(A) bytypecheck1049have typedB : Real(B) bytypecheck1050exact realMulValue.commutative with typedA, typedB10511052theorem reals.nontrivial1053shows Nontrivial(ℝ, realZero, realOne)1054proof1055constructor1056 . exact realZero.real1057constructor1058 . exact realOne.real1059 . exact realZero.ne_one10601061theorem realMulValue.type (A B : Real)1062showsReal(realMulValue(A, B))1063proof1064have closed := realMulValue.real at A, B with*1065unfold realMulValue1066unfold call2 at closed1067exact closed1068