From 0255f0592210c5b44c7f8080803a6ab0ef725f2f Mon Sep 17 00:00:00 2001 From: Skip Garibaldi Date: Fri, 16 Oct 2026 16:27:00 -0700 Subject: [PATCH 1/6] Add CompositionAlgebrasOverRings Composition algebras over commutative rings, following Garibaldi, Petersson and Racine, Albert Algebras over Commutative Rings, Part I; with Witt cancellation over LG rings and Artin's theorem on alternative rings. Ported from skipgaribaldi/CompositionAlgebras-lean at v1.0 (87b1eeb), building against the pool pins, and reusing TauCeti where it already has a result. Co-Authored-By: Claude Opus 5.5 --- LeanPool/CompositionAlgebrasOverRings.lean | 281 ++++ .../Composition/Alternative.lean | 196 +++ .../Composition/BaseChange.lean | 64 + .../Composition/Basic.lean | 108 ++ .../Composition/CayleyDickson.lean | 116 ++ .../Composition/CayleyDicksonIff.lean | 164 +++ .../Composition/ComplexQuaternion.lean | 202 +++ .../Composition/Defs.lean | 158 +++ .../Composition/Doubling.lean | 174 +++ .../Composition/Examples.lean | 207 +++ .../Composition/Fields/Basic.lean | 232 ++++ .../Composition/Fields/Finite.lean | 234 ++++ .../Composition/Fields/FractionField.lean | 130 ++ .../Composition/Fields/Real.lean | 221 +++ .../Composition/Fields/SepClosed.lean | 229 ++++ .../Composition/Fields/SurjectiveNorm.lean | 105 ++ .../Composition/Inseparable.lean | 273 ++++ .../Composition/InseparableAnisotropic.lean | 179 +++ .../Composition/NormClassification.lean | 1125 +++++++++++++++ .../Composition/NormEquivalence.lean | 244 ++++ .../Composition/Octonion.lean | 235 ++++ .../Composition/QuadraticEtale.lean | 444 ++++++ .../Composition/QuadraticSubalgebra.lean | 613 +++++++++ .../Composition/RankDichotomy.lean | 203 +++ .../Composition/RankOneTwoFourEight.lean | 571 ++++++++ .../Composition/RankTwoSubalgebra.lean | 373 +++++ .../Composition/Reduced/Capstone.lean | 130 ++ .../Composition/Reduced/Classification.lean | 565 ++++++++ .../Composition/Reduced/Defs.lean | 396 ++++++ .../Composition/Reduced/Hyperbolic.lean | 183 +++ .../Composition/Reduced/Orientation.lean | 586 ++++++++ .../Reduced/OrientedRankEight.lean | 207 +++ .../Composition/Reduced/Peirce.lean | 770 +++++++++++ .../Composition/Reduced/RankEight.lean | 417 ++++++ .../Composition/Reduced/RankTwo.lean | 161 +++ .../Composition/Reduced/Reducedness.lean | 108 ++ .../Composition/Reduced/Split.lean | 244 ++++ .../Composition/Reduced/Splitness.lean | 273 ++++ .../Composition/Reduced/TwistedMatrix.lean | 609 +++++++++ .../Composition/Reduced/TwistedZorn.lean | 503 +++++++ .../Composition/Reduced/Zorn.lean | 334 +++++ .../Composition/Sedenion.lean | 210 +++ .../Composition/Tower.lean | 544 ++++++++ .../Conic/BaseChange.lean | 191 +++ .../Conic/BaseChangeMultiplicative.lean | 215 +++ .../Conic/Basic.lean | 384 ++++++ .../Conic/CayleyDickson.lean | 372 +++++ .../Conic/CayleyDicksonAlternative.lean | 222 +++ .../Conic/CayleyDicksonAssociative.lean | 184 +++ .../Conic/CayleyDicksonConverse.lean | 222 +++ .../Conic/CayleyDicksonMultiplicative.lean | 93 ++ .../Conic/Defs.lean | 120 ++ .../Conic/Division.lean | 188 +++ .../Conic/Doubling.lean | 359 +++++ .../Conic/Kirmse.lean | 215 +++ .../Conic/Multiplicative.lean | 291 ++++ .../Conic/Projective.lean | 242 ++++ .../Conic/QuadraticAlgebra.lean | 198 +++ .../Conic/Recognition.lean | 303 +++++ .../Conic/Subalgebra.lean | 90 ++ .../Conic/TraceDefectCounterexample.lean | 247 ++++ .../CompositionAlgebrasOverRings/Imports.lean | 113 ++ .../LGRing/ConstantRank.lean | 141 ++ .../LGRing/Defs.lean | 169 +++ .../LGRing/DirectLimit.lean | 182 +++ .../LGRing/Examples.lean | 67 + .../LGRing/Jacobson.lean | 200 +++ .../LGRing/NonExamples.lean | 93 ++ .../LGRing/Products.lean | 343 +++++ .../LGRing/Semilocal.lean | 154 +++ .../LGRing/Unimodular.lean | 212 +++ .../LGRing/ValueIdeal.lean | 168 +++ .../LGRing/ZeroDimensional.lean | 394 ++++++ .../Module/AlternatingBaseChange.lean | 305 +++++ .../Module/ExteriorPower.lean | 129 ++ .../Module/IdempotentDecomposition.lean | 135 ++ .../Module/IdempotentFactor.lean | 246 ++++ .../Module/Invertible.lean | 309 +++++ .../Module/RankDecomposition.lean | 438 ++++++ .../Module/SelfAnnihilating.lean | 135 ++ .../Module/Unimodular.lean | 181 +++ .../Module/VectorProduct.lean | 679 ++++++++++ .../Nonassociative/Alternative/Artin.lean | 507 +++++++ .../Nonassociative/Alternative/Defs.lean | 185 +++ .../Nonassociative/Alternative/Moufang.lean | 126 ++ .../Nonassociative/Alternative/Peirce.lean | 396 ++++++ .../Alternative/PowerAssociative.lean | 108 ++ .../Nonassociative/Associator.lean | 85 ++ .../Nonassociative/Division.lean | 76 ++ .../Nonassociative/Subalgebra.lean | 66 + .../QuadraticForm/BaseChangeProjective.lean | 437 ++++++ .../QuadraticForm/Cancellation.lean | 148 ++ .../QuadraticForm/FiniteField.lean | 98 ++ .../QuadraticForm/Hyperbolic.lean | 310 +++++ .../QuadraticForm/HyperbolicPair.lean | 313 +++++ .../QuadraticForm/Isotropic.lean | 277 ++++ .../QuadraticForm/NonsingularOverFields.lean | 549 ++++++++ .../QuadraticForm/OrthogonalComplement.lean | 296 ++++ .../QuadraticForm/PlaneCancellation.lean | 159 +++ .../QuadraticForm/PlaneSplitting.lean | 175 +++ .../QuadraticForm/PlaneTransitivity.lean | 524 +++++++ .../QuadraticForm/Polynomial.lean | 130 ++ .../QuadraticForm/Real.lean | 147 ++ .../QuadraticForm/Regularity.lean | 1204 +++++++++++++++++ .../QuadraticForm/Representation.lean | 232 ++++ .../QuadraticForm/WittCancellation.lean | 220 +++ .../composition-algebras-over-rings.yaml | 67 + 107 files changed, 29085 insertions(+) create mode 100644 LeanPool/CompositionAlgebrasOverRings.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Alternative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/BaseChange.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Basic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDickson.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDicksonIff.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/ComplexQuaternion.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Doubling.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Basic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Finite.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/FractionField.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Real.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SepClosed.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SurjectiveNorm.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Inseparable.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/InseparableAnisotropic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/NormClassification.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/NormEquivalence.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticEtale.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticSubalgebra.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/RankDichotomy.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/RankOneTwoFourEight.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/RankTwoSubalgebra.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Capstone.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Hyperbolic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Orientation.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/OrientedRankEight.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Peirce.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankEight.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankTwo.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Reducedness.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Split.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Splitness.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedMatrix.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedZorn.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Zorn.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Sedenion.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/BaseChange.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/BaseChangeMultiplicative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Basic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDickson.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAlternative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonConverse.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Defs.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Division.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Doubling.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Projective.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/QuadraticAlgebra.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Recognition.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/Subalgebra.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Conic/TraceDefectCounterexample.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Imports.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/ConstantRank.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Defs.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/DirectLimit.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Examples.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Jacobson.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/NonExamples.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Products.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Semilocal.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/Unimodular.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/ValueIdeal.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/LGRing/ZeroDimensional.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/AlternatingBaseChange.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/ExteriorPower.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/IdempotentDecomposition.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/IdempotentFactor.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/RankDecomposition.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/SelfAnnihilating.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/Unimodular.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Module/VectorProduct.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Defs.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Moufang.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Peirce.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/PowerAssociative.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Associator.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Division.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/Nonassociative/Subalgebra.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/BaseChangeProjective.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Cancellation.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/FiniteField.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Hyperbolic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/HyperbolicPair.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Isotropic.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/NonsingularOverFields.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/OrthogonalComplement.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneCancellation.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneSplitting.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneTransitivity.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Polynomial.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Real.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Representation.lean create mode 100644 LeanPool/CompositionAlgebrasOverRings/QuadraticForm/WittCancellation.lean create mode 100644 LeanPool/projects/composition-algebras-over-rings.yaml diff --git a/LeanPool/CompositionAlgebrasOverRings.lean b/LeanPool/CompositionAlgebrasOverRings.lean new file mode 100644 index 0000000000..54b5bc7183 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings.lean @@ -0,0 +1,281 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Alternative +public import LeanPool.CompositionAlgebrasOverRings.Composition.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Composition.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDicksonIff +public import LeanPool.CompositionAlgebrasOverRings.Composition.ComplexQuaternion +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Composition.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Composition.Examples +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Finite +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.FractionField +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Real +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.SepClosed +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.SurjectiveNorm +public import LeanPool.CompositionAlgebrasOverRings.Composition.Inseparable +public import LeanPool.CompositionAlgebrasOverRings.Composition.InseparableAnisotropic +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormClassification +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormEquivalence +public import LeanPool.CompositionAlgebrasOverRings.Composition.Octonion +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticEtale +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankOneTwoFourEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Capstone +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Classification +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Orientation +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.OrientedRankEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankTwo +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Reducedness +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Split +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Splitness +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedMatrix +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedZorn +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Zorn +public import LeanPool.CompositionAlgebrasOverRings.Composition.Sedenion +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChangeMultiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAlternative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAssociative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonConverse +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonMultiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Defs +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division +public import LeanPool.CompositionAlgebrasOverRings.Conic.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Conic.Kirmse +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.Conic.QuadraticAlgebra +public import LeanPool.CompositionAlgebrasOverRings.Conic.Recognition +public import LeanPool.CompositionAlgebrasOverRings.Conic.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.Conic.TraceDefectCounterexample +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ConstantRank +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import LeanPool.CompositionAlgebrasOverRings.LGRing.DirectLimit +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Examples +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Jacobson +public import LeanPool.CompositionAlgebrasOverRings.LGRing.NonExamples +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Products +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Semilocal +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ValueIdeal +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ZeroDimensional +public import LeanPool.CompositionAlgebrasOverRings.Module.AlternatingBaseChange +public import LeanPool.CompositionAlgebrasOverRings.Module.ExteriorPower +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentDecomposition +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentFactor +public import LeanPool.CompositionAlgebrasOverRings.Module.Invertible +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition +public import LeanPool.CompositionAlgebrasOverRings.Module.SelfAnnihilating +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.Module.VectorProduct +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Artin +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Moufang +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.PowerAssociative +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Associator +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Division +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Cancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.FiniteField +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.HyperbolicPair +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Isotropic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.NonsingularOverFields +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.OrthogonalComplement +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneCancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneSplitting +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneTransitivity +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Polynomial +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Real +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Representation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.WittCancellation + +/-! +# Composition Algebras over Commutative Rings + +Source: doi:10.1017/9781009426862 +Authors: Skip Garibaldi +Status: verified +Main declarations: `ConicAlgebra.IsComposition.rankAtStalk_classification`, `QuadraticForm.cancel` +Tags: nonassociative-algebra, composition-algebras, octonions, quadratic-forms, lg-rings +MSC: 17A75, 17D05, 11E81, 11E08, 13C10 +-/ + +@[expose] public section + +/-! +# Composition algebras over commutative rings + +This project develops the theory of **composition algebras over a commutative ring**, following +Garibaldi–Petersson–Racine, *Albert Algebras over Commutative Rings* (`GPR`), Part I: conic +algebras, Cayley–Dickson doubling, composition algebras, reduced composition algebras, and the +classification over special classes of fields. Two results needed along the way are of +independent interest and are proved in full: **Witt cancellation for quadratic forms** and +**Artin's theorem on alternative rings**. + +The proofs that are classical over fields work, almost unchanged, over **LG rings** — commutative +rings over which finitely generated projective modules behave like vector spaces — so that is the +generality used. The objects themselves are defined over an arbitrary commutative ring. + +A result-by-result record of what is proved, indexed by its number in `GPR`, `GN`, `EKM` and +`Dias`, is `RESULTS.md` in the source repository (`skipgaribaldi/CompositionAlgebras-lean`, tag +`v1.0`). Docstrings in this project cite the sections below as "overview §N" and "overview trap N". + +## Layout + +The directories form layers. A file imports mathlib, TauCeti, and directories of strictly lower +layer only, so that the general-purpose layers stay liftable: + +| Layer | Directory | Contents | +|---|---|---| +| 0 | `Module/` | commutative algebra: idempotents, rank decomposition, unimodular elements | +| 0 | `Nonassociative/` | associator, nucleus, alternative rings, Moufang, Artin's theorem | +| 1 | `LGRing/` | LG rings: examples, non-examples, constant-rank projectives are free | +| 2 | `QuadraticForm/` | base change without `2`, regularity, isotropy, Witt cancellation | +| 3 | `Conic/` | conic algebras, conjugation, Cayley–Dickson doubling | +| 4 | `Composition/` | composition algebras, the tower, ranks 1, 2, 4, 8, reduced algebras | + +## Why LG rings + +A commutative ring `R` is an **LG ring** if a polynomial over `R` represents a unit as soon as it +represents a unit over every residue field `R ⧸ 𝔪`. LG rings include all fields, all semilocal +rings, all zero-dimensional rings and the ring of all algebraic integers; they do not include `ℤ` +or `R[t]` for a domain `R`. Two facts drive everything: + +1. over an LG ring, a finitely generated projective module of constant rank is free; +2. quadratic forms over an LG ring cancel: `q₁ ⊥ q₃ ≅ q₂ ⊥ q₃ ⇒ q₁ ≅ q₂` for `q₁, q₂` + nonsingular and `q₃` regular (`GN 6.5`). + +## Results of independent interest + +* **Witt cancellation** over LG rings, with the field case as an instance, proved by the + elementary Dias–Baeza–Knebusch route through hyperbolic planes and Siegel–Eichler transvections. +* **Artin's theorem**: a ring is alternative if and only if every subring generated by two elements + is associative; with the alternating associator and the three Moufang identities. +* **LG rings** with their examples and non-examples, and freeness of constant-rank projectives. +* **The rank decomposition** of a finitely generated projective module (`GPR Exc. 9.31`). +* **Invertible modules are line bundles** (`Module.invertible_iff_isLocallyFreeRankOne`). +* **Isotropy over a finite field**: a quadratic form in at least three variables over a finite + field has a nonzero null vector, via Chevalley–Warning. + +## Conventions + +These conventions keep the development consistent; docstrings refer to them by number. + +**§0. mathlib and TauCeti are canonical.** Nothing they define is redefined here. Where a notion +must differ from mathlib's, the divergence is documented with a `⚠` paragraph saying what mathlib's +notion is, what ours is, and where they agree. + +**§2. Hypotheses are unbundled, minimal and honest.** Every result carries exactly the hypotheses +its proof consumes. Three axes stay separate: algebra structure (`[NonAssocRing A]`, +`[IsAlternative A]`), norm regularity (`IsGPRNonsingular`, `IsGPRRegular`, ...) and module +regularity (`Module.Finite`, `Module.Projective`, constant rank). Objects are defined over a +general `CommRing`; `IsLGRing k` and `[Field K]` appear only on theorems, and the field case is the +LG theorem applied to `isLGRing_of_field`. + +**§3. Import discipline.** See *Layout*: no file imports a directory of the same or a higher +layer, apart from its own. + +**§5. No `sorry`, no `native_decide`.** Every result uses only the standard axioms. + +**§6. Mandatory warnings.** Each is documented where it applies and may not be simplified away. +* (a) **Polar, never `associated`.** Norm, trace and conjugation go through the un-halved + `QuadraticMap.polar`. `QuadraticMap.associated` needs `Invertible 2` and would make every + characteristic-two example unstatable. +* (b) **Regularity words are source-specific.** mathlib's `LinearMap.BilinForm.Nondegenerate` is + injectivity into the dual, `GPR`'s "weakly regular". `GPR`'s non-degenerate, non-singular and + regular are `QuadraticForm.IsGPRNondegenerate`, `IsGPRNonsingular` and `IsGPRRegular`; `EKM`'s + ladder is `IsEKMNondegenerate`. No bare `IsNondegenerate`, `IsRegular` or `IsNonsingular`. +* (c) **`GPR` isotropy is unimodular, mathlib's is nonzero.** `GPR`'s notion is + `QuadraticMap.IsGPRIsotropic`, never `¬ QuadraticMap.Anisotropic`; they agree over fields and + over PIDs (`GPR 22.19`) but not in general. +* (d) **The Cayley–Dickson scalar is arbitrary**: `μ : k`, not `μ : kˣ`. Unit hypotheses go on + theorems; otherwise the sedenions could not be stated. +* (e) **Conjugation is an anti-homomorphism only with a module hypothesis.** Over a ring, + `conj (x y) = (conj y) (conj x)` needs the algebra projective (`GPR 16.14(b)`, `GPR 17.6`), even + when it is associative; see trap 6. + +**§8. Working with the literature.** `GPR` and `GN` are the sources of record, cited by number. +`GN` is cited by its published numbering (European Journal of Mathematics **11** (2025), article +42), not the arXiv preprint's: preprint 1.6 is published 2.6, preprint 5.5 is published 6.5, and +preprint 2.15 is published Example 3.15. The `GPR` pre-publication text uses the same numbering as +the published book. Where a result is false in greater generality, its docstring says so and cites +the counterexample. Proofs avoid disproportionate machinery: Witt cancellation follows the +elementary Dias–Baeza–Knebusch route rather than `GN`'s cohomological Cancellation Principle, and +of `GN Example 3.15` only the final paragraph is in scope. + +## Design decisions + +1. **Two named algebra notions, `ConicAlgebra` and `IsComposition`.** Everything between them is + a hypothesis. There is no `PreCompositionAlgebra`: `GPR 19.7(a)` shows that notion is not + stable under base change, with `GPR 19.4` as the counterexample. +2. **Three independent axes, never bundled** (§2). +3. **`GPR`'s regularity notions, named after their source** (§6(b)). Over a ring they are not + linearly ordered; `QuadraticForm/Regularity.lean` has the separating examples. +4. **Polar, never `associated`** (§6(a)). +5. **`μ : k` arbitrary in Cayley–Dickson** (§6(d)). +6. **Recover mathlib's objects, don't duplicate them**, asymmetrically where the mathematics is + asymmetric (trap 3). +7. **Work over `CommRing` by default** (§2). + +## Boundaries and traps + +Six places where the obvious thing is wrong. + +1. **Regularity words are source-specific** (§6(b)). For finite-dimensional forms over a field of + characteristic not two the notions agree; in characteristic two they separate already over a + field (`x²` over `𝔽₂` is non-degenerate and non-singular but not weakly regular), and over rings + further (`x²` over `𝔽₂[ε]/(ε²)` is non-singular with `ε` in its radical). +2. **Isotropy is unimodular** (§6(c)). `GPR 22.19` lists the two notions as separate conditions, + (ii) and (iii), because over a general ring they are. +3. **`QuaternionAlgebra` is a free rank-four presentation, not "the rank-four composition + algebras".** It is too wide (its norm need not be non-singular) and too narrow (it only + produces free modules). The correct statements are asymmetric: a `QuaternionAlgebra` with + non-singular norm is a rank-four composition algebra, and over an LG ring every + constant-rank-four composition algebra is a `QuaternionAlgebra`. The specific identification of + `Cay₄ ℝ (-1) (-1)` with `ℍ[ℝ]` is unaffected. +4. **The norm does not determine the algebra over a general ring.** Gille (Canad. Math. Bull. + **57** (2014), 303–309) gives non-isomorphic octonion algebras with isometric norms, so the LG + hypothesis in the norm classification cannot be dropped. +5. **Witt cancellation needs `q₃` regular**, not merely nonsingular; otherwise it is false + (Elman–Karpenko–Merkurjev, p. 49, cited at the end of `GN §6`). +6. **Alternativity does not make conjugation an anti-homomorphism over a ring.** The field proof + does not generalize: `Conic/TraceDefectCounterexample.lean` gives an associative conic algebra + over `ℤ/4` where it fails, a small variant of McCrimmon's `GPR Exc. 17.8`. `GPR` itself warns + against this in `GPR 17.4`. + +## References + +* [GPR] S. Garibaldi, H. P. Petersson, M. Racine, *Albert Algebras over Commutative Rings*, + Cambridge University Press, New Mathematical Monographs **48**, 2024. +* [GN] P. Gille, E. Neher, *Group schemes over LG-rings and applications to cancellation theorems + and Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42. +* [EKM] R. Elman, N. Karpenko, A. Merkurjev, *The Algebraic and Geometric Theory of Quadratic + Forms*, AMS Colloquium Publications **56**, 2008. +* [Dias] I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de + Campinas, 1988. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Mathematics **655**, 1978. +* R. D. Schafer, *An Introduction to Nonassociative Algebras*. +* P. Gille, *Octonion algebras over rings are not determined by their norms*, Canad. Math. Bull. + **57** (2014), 303–309. +-/ diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Alternative.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Alternative.lean new file mode 100644 index 0000000000..cc1cc01a51 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Alternative.lean @@ -0,0 +1,196 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition + +/-! +# Composition algebras are alternative, over an arbitrary commutative ring + +`Composition/Basic.lean` derives alternativity (`GPR 19.3`) from non-singularity in the two cases +where non-singularity yields a vanishing radical: over a field, and over a ring in which `2` is +invertible. This file removes both restrictions, for **every** composition algebra: no hypothesis +on `2`, none on the rank, and none on the base ring beyond commutativity. + +## Why the general case is not a descent + +`GPR 19.3` itself is *not* a statement about composition algebras. Its hypothesis is that the norm +be **non-degenerate** in the sense of `GPR 11.11` — the radical vanishes — and in that form it is +already proved in full generality here (`ConicAlgebra.IsMultiplicative.isAlternative`, in +`Conic/Kirmse.lean`). What a composition algebra supplies is **non-singularity**, which over a ring +does not imply it, and `GPR 19.6` shows the two genuinely differ: the base ring `k = 𝔽₂[t]/(t²)` is +a composition algebra over itself whose norm has `t` in its radical. So no argument can derive a +vanishing radical from the definition, and the residue-field descent once proposed for this cannot +work — `t` is nilpotent and dies in every field over that ring. + +`GPR 19.7(c)` says what is true instead: it is the **regular** composition algebras that are +alternative, via `GPR 19.3`. Regularity gives a vanishing radical for free and with no hypothesis +on `2`, since the radical is contained in the kernel of the polar form +(`QuadraticForm.IsGPRRegular.isGPRNondegenerate`). + +## Closing the gap + +That leaves only the algebras `GPR 19.11` excludes from regularity, and they are harmless. If a +composition algebra has constant rank `r`, then either its norm is regular — and alternativity +follows as above — or `r = 1`. In rank one every element is a scalar multiple of the identity +(`ConicAlgebra.eq_unitForm_smul_one_of_rankAtStalk_eq_one`), so the algebra is commutative and +associative outright, hence alternative. `𝔽₂[t]/(t²)` is exactly such an algebra: it is alternative, +just not for the reason `GPR 19.3` gives. + +The two cases together prove alternativity for every constant-rank composition algebra over a +nontrivial commutative ring. The constant-rank hypothesis then comes off by the rank decomposition +`GPR Exc. 9.31`, and the base ring need not be nontrivial: over the zero ring the index set of the +decomposition is empty and the module is a subsingleton, so the argument is vacuously fine. + +## Main results + +* `ConicAlgebra.IsComposition.isAlternative_of_isGPRRegular` : **`GPR 19.7(c)`** — a regular + composition algebra is alternative, over any commutative ring. +* `ConicAlgebra.mul_assoc_of_rankAtStalk_eq_one`, `ConicAlgebra.mul_comm_of_rankAtStalk_eq_one` : + a constant-rank-one conic algebra is associative and commutative. +* `ConicAlgebra.IsComposition.isAlternative_of_rankAtStalk` : alternativity of a composition + algebra of constant rank over a nontrivial commutative ring. +* `ConicAlgebra.IsComposition.isAlternative_general` : **alternativity of an arbitrary composition + algebra over an arbitrary commutative ring**, the constant-rank hypothesis removed by the rank + decomposition. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.3, 19.6, + 19.7(c), 19.11, Exc. 9.31. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} + +/-- **`GPR 19.7(c)`.** A composition algebra whose norm is *regular* is alternative, over an +arbitrary commutative ring and with no hypothesis on `2`. + +Regularity means the polar form is injective into the dual, and the radical is contained in its +kernel, so the radical vanishes — which is precisely the hypothesis of `GPR 19.3`. -/ +theorem IsComposition.isAlternative_of_isGPRRegular (h : C.IsComposition.{u, v, u}) + (hreg : C.norm.IsGPRRegular) : IsAlternative A := + h.isMultiplicative.isAlternative hreg.isGPRNondegenerate + +section RankOne + +/-- A conic algebra of constant rank one is **associative**: every element is a scalar multiple of +the identity, so every product is too. -/ +theorem mul_assoc_of_rankAtStalk_eq_one [Nontrivial k] (C : ConicAlgebra k A) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) (x y z : A) : + x * y * z = x * (y * z) := by + have hx := C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA x + have hy := C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA y + have hz := C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA z + rw [hx, hy, hz] + simp only [smul_mul_smul_comm, one_mul, mul_assoc] + +/-- A conic algebra of constant rank one is **commutative**, for the same reason. -/ +theorem mul_comm_of_rankAtStalk_eq_one [Nontrivial k] (C : ConicAlgebra k A) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) (x y : A) : x * y = y * x := by + have hx := C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA x + have hy := C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA y + rw [hx, hy] + simp only [smul_mul_smul_comm, one_mul, mul_comm] + +/-- A conic algebra of constant rank one is alternative, being associative. -/ +theorem isAlternative_of_rankAtStalk_eq_one [Nontrivial k] (C : ConicAlgebra k A) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) : IsAlternative A where + left_alt a b := (mul_assoc_of_rankAtStalk_eq_one C hA a a b).symm + right_alt a b := mul_assoc_of_rankAtStalk_eq_one C hA b a a + +end RankOne + +/-- **Composition algebras of constant rank are alternative over an arbitrary nontrivial +commutative ring**, with no hypothesis on `2`. + +`GPR 19.11` splits the problem in two: either the norm is regular, and `GPR 19.7(c)` applies, or +the rank is one, and the algebra is associative because every element is a scalar. The second case +is not vacuous — over `𝔽₂[t]/(t²)` the base ring is a composition algebra whose norm is not +regular (`GPR 19.6`) — which is why it has to be handled separately rather than by weakening the +regularity hypothesis. -/ +theorem IsComposition.isAlternative_of_rankAtStalk [Nontrivial k] (h : C.IsComposition.{u, v, u}) + {r : ℕ} (hrank : Module.rankAtStalk (R := k) A = fun _ ↦ r) : IsAlternative A := by + rcases h.isGPRRegular_or_rank_eq_one hrank with hreg | ⟨hr, -⟩ + · exact h.isAlternative_of_isGPRRegular hreg + · subst hr + exact isAlternative_of_rankAtStalk_eq_one C hrank + +/-! ### Removing the constant-rank hypothesis + +`GPR Exc. 9.31` splits `k` into the finitely many factors `kᵢ = k ⧸ (1 - εᵢ)` on which `A` has +constant rank `i`, and each `kᵢ ⊗ A` is again a composition algebra, of constant rank `i`. So each +factor is alternative by the theorem above. + +Transporting *back* is where an equation is easier than a structure. `IsAlternative` is two +identities, and an element of `A` vanishes as soon as it vanishes in every factor +(`Module.eq_zero_of_forall_rankIdempotent_smul_eq_zero`, +`Module.rankIdempotent_smul_eq_zero_of_one_tmul_eq_zero`); the map `x ↦ 1 ⊗ x` carries products to +products by `Algebra.TensorProduct.tmul_mul_tmul`, so it carries each alternative law to the +corresponding one. No product decomposition of the algebra has to be built. -/ + +section AllRanks + +variable (C) + +omit [Module.Finite k A] [Module.Projective k A] in +/-- The canonical map `x ↦ 1 ⊗ x` into a base change carries products to products. -/ +theorem one_tmul_mul (S : Type w) [CommRing S] [Algebra k S] (x y : A) : + (1 : S) ⊗ₜ[k] (x * y) = ((1 : S) ⊗ₜ[k] x) * ((1 : S) ⊗ₜ[k] y) := by + rw [Algebra.TensorProduct.tmul_mul_tmul, one_mul] + +/-- A base change of constant rank is alternative. + +The base may be the zero ring — the rank-`i` locus is empty for all but finitely many `i` — and +then the base change is a subsingleton and there is nothing to prove. -/ +theorem isAlternative_baseChange_of_rankAtStalk (h : C.IsComposition.{u, v, u}) + (S : Type u) [CommRing S] [Algebra k S] {i : ℕ} + (hrank : Module.rankAtStalk (R := S) (S ⊗[k] A) = fun _ ↦ i) : + IsAlternative (S ⊗[k] A) := by + rcases subsingleton_or_nontrivial S with _ | _ + · have : Subsingleton (S ⊗[k] A) := Module.subsingleton S _ + exact ⟨fun _ _ ↦ Subsingleton.elim _ _, fun _ _ ↦ Subsingleton.elim _ _⟩ + · exact (h.baseChangeOfProjective S).isAlternative_of_rankAtStalk hrank + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Two elements agreeing in every factor of the rank decomposition are equal. -/ +theorem eq_of_forall_one_tmul_eq {x y : A} + (h : ∀ i : ℕ, (1 : k ⧸ Ideal.span {1 - Module.rankIdempotent k A i}) ⊗ₜ[k] x = + (1 : k ⧸ Ideal.span {1 - Module.rankIdempotent k A i}) ⊗ₜ[k] y) : x = y := by + refine sub_eq_zero.mp (Module.eq_zero_of_forall_rankIdempotent_smul_eq_zero k A fun i ↦ ?_) + refine Module.rankIdempotent_smul_eq_zero_of_one_tmul_eq_zero k A i ?_ + rw [TensorProduct.tmul_sub, h i, sub_self] + +/-- **Every composition algebra is alternative**, over an arbitrary commutative ring, with no +hypothesis on `2` and **no constant-rank hypothesis**. + +By `GPR Exc. 9.31` it suffices to check each factor of the rank decomposition, where the rank is +constant; `ConicAlgebra.one_tmul_mul` carries each alternative law into the factor, and +`ConicAlgebra.eq_of_forall_one_tmul_eq` brings the conclusion back. No product decomposition of +the algebra itself has to be built. -/ +theorem IsComposition.isAlternative_general (h : C.IsComposition.{u, v, u}) : IsAlternative A := by + refine ⟨fun a b ↦ eq_of_forall_one_tmul_eq (k := k) (A := A) fun i ↦ ?_, + fun a b ↦ eq_of_forall_one_tmul_eq (k := k) (A := A) fun i ↦ ?_⟩ <;> + · have := isAlternative_baseChange_of_rankAtStalk C h _ + (Module.rankAtStalk_quotientTensor_rankIdempotent k A i) + simp only [one_tmul_mul] + first + | exact IsAlternative.left_alt _ _ + | exact IsAlternative.right_alt _ _ + +end AllRanks + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/BaseChange.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/BaseChange.lean new file mode 100644 index 0000000000..4ff949100e --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/BaseChange.lean @@ -0,0 +1,64 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChangeMultiplicative + +/-! +# Base change of composition algebras (`GPR 19.7`) + +A composition algebra stays one after base change along any `k → S`. This is the property that +`ConicAlgebra.IsComposition` was designed to have, and it is why the definition asks for the norm +to be **non-singular** rather than regular or merely non-degenerate: non-singularity is +base-change stable by construction, while `GPR 19.4` exhibits a conic algebra whose norm is +non-degenerate but whose base change's norm is not (which is also why there is no +`PreCompositionAlgebra` here; see `Composition/Defs.lean`). + +## Main results + +* `ConicAlgebra.IsComposition.baseChangeOfProjective` : `S ⊗[k] A` is a composition algebra + over `S`. + +## Implementation notes + +Both clauses come from elsewhere: multiplicativity from +`ConicAlgebra.IsMultiplicative.baseChangeOfProjective`, non-singularity from +`QuadraticForm.IsGPRNonsingular.baseChangeOfProjective`. Finite projectivity of `S ⊗[k] A` over +`S` is an instance. The only content here is that the norm of the base-changed conic algebra is +the base-changed norm, which is definitional +(`ConicAlgebra.baseChangeOfProjective_norm`). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.5, 19.7. +-/ + +@[expose] public section + +universe u v w w' + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] +variable {C : ConicAlgebra k A} + +/-- **A composition algebra stays a composition algebra after base change.** + +Non-singularity of the norm survives because it is a statement about every field over the base, +and a field over `S` is a field over `k`; multiplicativity survives by +`ConicAlgebra.IsMultiplicative.baseChangeOfProjective`. Nothing is assumed about `2`, about the +rank, or about `S`. -/ +theorem IsComposition.baseChangeOfProjective (h : C.IsComposition.{u, v, w'}) (S : Type w) + [CommRing S] [Algebra k S] : + (C.baseChangeOfProjective S).IsComposition.{w, max v w, w'} where + isGPRNonsingular := h.isGPRNonsingular.baseChangeOfProjective S + isMultiplicative := h.isMultiplicative.baseChangeOfProjective S + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Basic.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Basic.lean new file mode 100644 index 0000000000..8913522f63 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Basic.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Conic.Kirmse +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.NonsingularOverFields + +/-! +# Composition algebras are alternative (`GPR 19.3`) + +`GPR 19.3` says that a composition algebra is alternative, and that its norm is the unique conic +norm on it. This file proves the alternativity statement in the two cases where the hypothesis +`GPR 19.3` actually consumes — vanishing of the radical of the norm — is available from +non-singularity: **over a field**, unconditionally, and **over a ring in which `2` is +invertible**. + +The mathematical content is entirely in `Conic/Kirmse.lean`, where the Kirmse defect +`(conj x)(xy) - n(x)·y` is shown to lie in the radical of the norm with no hypothesis at all. All +that happens here is the passage from the composition-algebra hypothesis, +`QuadraticForm.IsGPRNonsingular`, to `QuadraticForm.IsGPRNondegenerate`. + +⚠ **That passage is not free over a ring.** Non-singularity does not imply that the radical +vanishes: `QuadraticForm.rankOne 1` over `𝔽₂[t]/(t²)` is non-singular but has `t` in its radical. +Over a field, non-singularity implies a vanishing radical, because it includes the trivial base +change (`QuadraticForm.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot`) — only that +direction: `x² + t y²` over `𝔽₂(t)` has zero radical but acquires a radical vector over `𝔽₂(√t)`. +Over a ring with `2` invertible, non-singular implies regular (`GN (C.8.2)`) and hence injective +polar form. The general ring case is not a descent from the residue fields (`Conic/Kirmse.lean` +explains why that fails); alternativity over an arbitrary ring is proved instead in +`Composition/Alternative.lean`. + +## Main results + +* `ConicAlgebra.IsComposition.isGPRNondegenerate` : over a field, the radical of the norm of a + composition algebra vanishes. +* `ConicAlgebra.IsComposition.isAlternative` : **`GPR 19.3` over a field**, with no hypothesis on + `2` and none on the rank — in particular it covers characteristic 2. +* `ConicAlgebra.IsComposition.isAlternative_of_invertible_two` : the same over any commutative ring + in which `2` is a unit. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.3. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European J. Math. **11** (2025), art. 42, + C.8, (C.8.2). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section CommRing + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- When `2 ∈ kˣ`, the radical of the norm of a composition algebra vanishes: non-singular implies +regular (`GN (C.8.2)`), and with `2` invertible an injective polar form is the same thing as a +vanishing radical. -/ +theorem IsComposition.isGPRNondegenerate_of_invertible_two [Invertible (2 : k)] + (h : C.IsComposition.{u, v, u}) : C.norm.IsGPRNondegenerate := + (QuadraticForm.radical_eq_bot_iff_injective_polarBilin C.norm).mpr h.isGPRRegular.injective + +/-- **`GPR 19.3` over a commutative ring in which `2` is invertible: a composition algebra is +alternative.** -/ +theorem IsComposition.isAlternative_of_invertible_two [Invertible (2 : k)] + (h : C.IsComposition.{u, v, u}) : IsAlternative A := + h.isMultiplicative.isAlternative h.isGPRNondegenerate_of_invertible_two + +end CommRing + +section Field + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] + {C : ConicAlgebra K A} + +omit [SMulCommClass K A A] [IsScalarTower K A A] in +/-- **Over a field, the radical of the norm of a composition algebra vanishes.** + +Non-singularity quantifies over *every* field extension of the base, so it applies in particular to +the base field itself, and `QuadraticForm.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot` +brings the conclusion back down along `K → K ⊗[K] A`. No hypothesis on `2`, and none on the rank: +in characteristic 2 the polar form may well have a kernel, but the *radical* — which constrains `n` +as well as `n(·,·)` — does not. -/ +theorem IsComposition.isGPRNondegenerate (h : C.IsComposition.{u, v, u}) : + C.norm.IsGPRNondegenerate := + C.norm.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot (h.isGPRNonsingular K) + +/-- **`GPR 19.3` over a field: every composition algebra is alternative.** + +No hypothesis on `2` and none on the rank. The characteristic-2 case, where the polar form of the +norm can be degenerate, is covered: Kirmse's identities need the radical to vanish, not the polar +form to be injective (`Conic/Kirmse.lean`). -/ +theorem IsComposition.isAlternative (h : C.IsComposition.{u, v, u}) : IsAlternative A := + h.isMultiplicative.isAlternative h.isGPRNondegenerate + +end Field + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDickson.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDickson.lean new file mode 100644 index 0000000000..0031e9c404 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDickson.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonMultiplicative + +/-! +# Doubling a composition algebra (`GPR 19.14`, one direction) + +If `B` is an **associative** composition algebra whose norm is **regular**, and `μ ∈ kˣ`, then +`Cay(B, μ)` is again a composition algebra. This is the engine of the tower: it produces the +quaternion algebras from the quadratic étale algebras and the octonion algebras from the quaternion +algebras, and — because octonion algebras are not associative — it stops there. + +This is the direction `⇐` of `GPR 19.14`, which is an equivalence: conversely, if `Cay(B, μ)` is +a composition algebra then `B` is a regular associative composition algebra and `μ` is a unit, and +in that case the double is regular. The converse, the regularity of the double, and the +equivalence itself (`ConicAlgebra.isComposition_cay_iff`) are in +`Composition/CayleyDicksonIff.lean`. + +Each of the three clauses of `ConicAlgebra.IsComposition` is supplied by an earlier file: + +* the module is finitely generated projective because `B × B` is (instances in + `Conic/CayleyDickson.lean`); +* the norm `n_B ⊥ ⟨-μ⟩ n_B` is non-singular by `GN (C.8.3)` + (`QuadraticForm.IsGPRRegular.prod_isGPRNonsingular`), together with the fact that rescaling by a + unit preserves non-singularity (`QuadraticForm.IsGPRNonsingular.smul_of_isUnit`); +* the norm is multiplicative by `GPR Exc. 18.18` (`ConicAlgebra.isMultiplicative_cay`), which is + where + associativity of `B` is spent. + +## Why the hypotheses are what they are + +**`μ` must be a unit** — `Cay(B, 0)` has `(0, v)` in the radical of its norm for every `v`, so +non-singularity fails at once. The construction itself still takes an arbitrary `μ` +(overview §6(d)); the unit hypothesis lives here, on the theorem. + +**The norm of `B` must be regular, not merely non-singular.** This is the asymmetry of +`GN (C.8.3)`, and it is not an artefact: over a field of characteristic 2 the rank-one form `⟨1⟩` +is non-singular but `⟨1⟩ ⊥ ⟨-1⟩ = ⟨1⟩ ⊥ ⟨1⟩` sends `(a, b)` to `(a + b) ^ 2` and so has a nonzero +radical. Concretely, `Cay(k, μ)` in characteristic 2 is the inseparable algebra `k[x]/(x² - μ)`, +which is *not* a composition algebra — which is exactly why `GPR 19.16(b)` starts the doubling +tower at a **regular rank-2** subalgebra rather than at `k`, and why `GPR 19.4` is a conic algebra +and not a composition algebra. The regularity hypothesis here is the same phenomenon seen from the +constructive side. + +**`B` must be associative**, for multiplicativity (`GPR Exc. 18.18`). Nothing is assumed about the +conjugation of `B`, and nothing about `2`. + +## Main results + +* `ConicAlgebra.IsComposition.cay` : `Cay(B, μ)` is a composition algebra. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 18.18, 19.14. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European J. Math. **11** (2025), art. 42, + (C.8.3). +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {B : Type v} [CommRing k] [Ring B] [Algebra k B] [Module.Finite k B] + [Module.Projective k B] {C : ConicAlgebra k B} + +omit [Module.Finite k B] [Module.Projective k B] in +/-- The Cayley–Dickson norm is the orthogonal sum `n_B ⊥ ⟨-μ⟩ n_B`, spelled with mathlib's +`QuadraticMap.prod`. This is `ConicAlgebra.cayNorm` unfolded across the type synonym, and is what +lets `GN (C.8.3)` be applied to it. -/ +theorem cay_norm_eq_prod (C : ConicAlgebra k B) (μ : k) : + (C.cay μ).norm = QuadraticMap.prod C.norm ((-μ) • C.norm) := rfl + +/-- **Non-singularity of the doubled norm.** For `n_B` regular and `μ` a unit, `n_B ⊥ ⟨-μ⟩ n_B` is +non-singular. + +`GN (C.8.3)` needs the *first* summand regular and the second only non-singular; `n_B` regular +gives both, the second via `GN (C.8.1)` and `QuadraticForm.IsGPRNonsingular.smul_of_isUnit`. -/ +theorem isGPRNonsingular_cay_norm (C : ConicAlgebra k B) {μ : k} (hμ : IsUnit μ) + (hreg : C.norm.IsGPRRegular) : + QuadraticForm.IsGPRNonsingular.{u, v, w} (C.cay μ).norm := + hreg.prod_isGPRNonsingular (hreg.isGPRNonsingular.smul_of_isUnit hμ.neg) + +/-- **`Cay(B, μ)` is a composition algebra**, for `B` an associative conic algebra with regular +multiplicative norm and `μ` a unit. + +Note that `B` is *not* required to be a composition algebra on the nose: what is used is that its +norm is regular (which implies non-singular, `GN (C.8.1)`) and multiplicative. Over a base in which +`2` is invertible the two hypotheses coincide with `C.IsComposition` by +`QuadraticForm.isGPRRegular_iff_isGPRNonsingular`; in characteristic 2 regularity is genuinely +stronger, and genuinely needed — see the module docstring. -/ +theorem IsComposition.cay (C : ConicAlgebra k B) {μ : k} (hμ : IsUnit μ) + (hreg : C.norm.IsGPRRegular) (hmul : C.IsMultiplicative) : + (C.cay μ).IsComposition.{u, v, w} where + isGPRNonsingular := isGPRNonsingular_cay_norm C hμ hreg + isMultiplicative := isMultiplicative_cay C μ hmul + +/-- **The doubling theorem in the form the tower uses**, when `2` is invertible: an *associative +composition algebra* doubles to a composition algebra at any unit scalar. + +Here the regularity hypothesis of `ConicAlgebra.IsComposition.cay` is discharged from +non-singularity by `GN (C.8.2)`, so the input is literally `C.IsComposition`. This is the step +`ℂ = Cay(ℝ, -1)`, `ℍ = Cay(ℂ, -1)`, `𝕆 = Cay(ℍ, -1)` — and it fails to apply once more only +because `𝕆` is not associative. -/ +theorem IsComposition.cay_of_invertible_two [Invertible (2 : k)] (C : ConicAlgebra k B) {μ : k} + (hμ : IsUnit μ) (h : C.IsComposition.{u, v, u}) : (C.cay μ).IsComposition.{u, v, w} := + IsComposition.cay C hμ h.isGPRRegular h.isMultiplicative + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDicksonIff.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDicksonIff.lean new file mode 100644 index 0000000000..c2cf18304b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/CayleyDicksonIff.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Alternative +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonConverse + +/-! +# When is a Cayley–Dickson double a composition algebra? (`GPR 19.14`) + +**`GPR 19.14`.** Let `B` be a conic `k`-algebra and `μ ∈ k`. Then `Cay(B, μ)` is a composition +algebra if and only if `B` is a regular associative composition algebra and `μ` is invertible; in +that case `Cay(B, μ)` is a regular composition algebra. + +## Relation to `Composition/CayleyDickson.lean` + +That file proves the direction `⇐` without the regularity of the double: +`ConicAlgebra.IsComposition.cay` (for `B` a `Ring`). This file supplies the rest: + +* the clause "in this case `Cay(B, μ)` is regular", `ConicAlgebra.isGPRRegular_cay_norm`: by + `GPR (18.5)` the doubled norm is `n_B ⊥ (-μ) n_B`, and an orthogonal sum of regular forms is + regular, as is a unit multiple of a regular form; +* the direction `⇒`, as five separate consequences of `(C.cay μ).IsComposition`; +* the equivalence itself, `ConicAlgebra.isComposition_cay_iff`, for `B` a `NonAssocRing`, so that + associativity of `B` is part of the statement rather than of the instances. + +## The converse + +Suppose `Cay(B, μ)` is a composition algebra. `GPR` obtains the invertibility of `μ` and the +regularity of `B` fibre by fibre, over the residue fields and the localizations of `k`. Here both +are read off from the regularity of the double, which is the only step that passes through fields. + +1. A composition algebra is alternative (`ConicAlgebra.IsComposition.isAlternative_general`, the + project's form of `GPR 19.13`), so `B` is associative by `GPR 18.15(b)` + (`ConicAlgebra.isAlternative_cay_iff_of_projective`). +2. The rank of `Cay(B, μ)` at every prime is twice that of `B`, hence never `1`. So the norm of the + double is regular by `GPR 19.11`, in the pointwise form + `ConicAlgebra.IsComposition.isGPRRegular_of_forall_rankAtStalk_ne_one`: the rank need not be + constant, since the proof of `GPR 19.11` only looks at one field at a time. +3. A regular orthogonal sum has regular summands. So `n_B` and `(-μ) n_B` are regular. +4. The polar map of `(-μ) n_B` is onto the dual, and `B` has a linear form taking the value `1` at + `1` (`GPR 16.7`, `ConicAlgebra.isUnimodular_one`). Its preimage `x` satisfies + `-μ · n_B(x, 1) = 1`, so `μ` is a unit. +5. `B` is closed under the multiplication of the double, with `(u, 0)(u', 0) = (uu', 0)` and + `n(u, 0) = n_B(u)`. So `n_B` permits composition + (`ConicAlgebra.isMultiplicative_of_isMultiplicative_cay`), and it is non-singular because it is + regular (`GN (C.8.1)`). + +⚠ The Lean statement `(C.cay μ).IsComposition` needs the module `B × B` to be finitely generated +projective, and that instance is found from `B`. So `B` is assumed finitely generated projective +throughout, where `GPR` derives this from the corresponding property of `Cay(B, μ)`, of which `B` +is a direct summand. The two hypotheses are equivalent. + +The facts about quadratic forms used in steps 3 and 4 — `QuadraticForm.isGPRRegular_prod_iff`, +`QuadraticForm.IsGPRRegular.smul_of_isUnit` and `QuadraticForm.isUnit_of_isGPRRegular_smul` — are +in `QuadraticForm/Regularity.lean`, and the pointwise form of `GPR 19.11` used in step 2 is in +`Composition/RankDichotomy.lean`. + +## Main results + +* `ConicAlgebra.isGPRRegular_cay_norm` : the norm of `Cay(B, μ)` is regular when `n_B` is and `μ` is + a unit (the last clause of `GPR 19.14`). +* `ConicAlgebra.IsComposition.mul_assoc_of_cay`, `ConicAlgebra.IsComposition.isGPRRegular_of_cay`, + `ConicAlgebra.IsComposition.isUnit_of_cay`, `ConicAlgebra.IsComposition.of_cay`, + `ConicAlgebra.IsComposition.isGPRRegular_cay_norm_of_cay` : **`GPR 19.14`, `⇒`**. +* `ConicAlgebra.isComposition_cay_iff` : **`GPR 19.14`**. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.12, 16.7, 18.5, + 18.15, 19.11, 19.13, 19.14. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European J. Math. **11** (2025), art. 42, + (C.8.1), C.8(f). +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +/-! ### `GPR 19.14` -/ + +section CayleyDickson + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [SMulCommClass k B B] [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] + {C : ConicAlgebra k B} {μ : k} + +omit [Module.Finite k B] [Module.Projective k B] in +/-- **The last clause of `GPR 19.14`: the double of a regular norm is regular.** If `n_B` is regular +and `μ` is a unit, then the norm `n_B ⊥ (-μ) n_B` of `Cay(B, μ)` (`GPR (18.5)`) is regular, being +an orthogonal sum of regular forms. Nothing is assumed about the multiplication of `B`, about the +module `B`, or about `2`. -/ +theorem isGPRRegular_cay_norm (C : ConicAlgebra k B) (hμ : IsUnit μ) + (hreg : C.norm.IsGPRRegular) : (C.cay μ).norm.IsGPRRegular := + hreg.prod (hreg.smul_of_isUnit hμ.neg) + +/-- **`GPR 19.14`, `⇒`: the double is regular.** If `Cay(B, μ)` is a composition algebra then its +norm is regular. The rank of the double is twice that of `B` at every prime +(`ConicAlgebra.rankAtStalk_cay`), hence never `1`, so `GPR 19.11` applies. -/ +theorem IsComposition.isGPRRegular_cay_norm_of_cay (h : (C.cay μ).IsComposition.{u, v, u}) : + (C.cay μ).norm.IsGPRRegular := + h.isGPRRegular_of_forall_rankAtStalk_ne_one fun p ↦ by + rw [rankAtStalk_cay] + simp only [Pi.mul_apply, Pi.ofNat_apply] + omega + +/-- **`GPR 19.14`, `⇒`: `B` is associative.** A composition algebra is alternative +(`ConicAlgebra.IsComposition.isAlternative_general`), and the double of a finitely generated +projective conic algebra is alternative exactly when the algebra is associative (`GPR 18.15(b)`). -/ +theorem IsComposition.mul_assoc_of_cay (h : (C.cay μ).IsComposition.{u, v, u}) (a b c : B) : + a * b * c = a * (b * c) := + (isAlternative_cay_iff_of_projective C μ).mp h.isAlternative_general a b c + +/-- **`GPR 19.14`, `⇒`: the norm of `B` is regular.** The norm of the double is the regular form +`n_B ⊥ (-μ) n_B` (`GPR (18.5)`), and the summands of a regular orthogonal sum are regular. -/ +theorem IsComposition.isGPRRegular_of_cay (h : (C.cay μ).IsComposition.{u, v, u}) : + C.norm.IsGPRRegular := + QuadraticForm.IsGPRRegular.of_prod_left (Q₂ := (-μ) • C.norm) h.isGPRRegular_cay_norm_of_cay + +/-- **`GPR 19.14`, `⇒`: `μ` is a unit.** The form `(-μ) n_B` is a summand of the regular norm of +the double, so it is regular, and the unit of `B` is unimodular (`GPR 16.7`); hence `-μ` is a +unit. -/ +theorem IsComposition.isUnit_of_cay (h : (C.cay μ).IsComposition.{u, v, u}) : IsUnit μ := + (IsUnit.neg_iff μ).mp <| QuadraticForm.isUnit_of_isGPRRegular_smul + (QuadraticForm.IsGPRRegular.of_prod_right (Q₁ := C.norm) h.isGPRRegular_cay_norm_of_cay) + C.isUnimodular_one + +/-- **`GPR 19.14`, `⇒`: `B` is a composition algebra.** Its norm is regular, hence non-singular +(`GN (C.8.1)`), and it permits composition because `B` sits in the double as the elements +`(u, 0)`, on which the norm and the product are those of `B`. -/ +theorem IsComposition.of_cay (h : (C.cay μ).IsComposition.{u, v, u}) : + C.IsComposition.{u, v, w} where + isGPRNonsingular := h.isGPRRegular_of_cay.isGPRNonsingular + isMultiplicative := isMultiplicative_of_isMultiplicative_cay C μ h.isMultiplicative + +/-- **`GPR 19.14`.** For a finitely generated projective conic algebra `B` and any `μ ∈ k`, the +double `Cay(B, μ)` is a composition algebra if and only if `B` is associative, `B` is a composition +algebra with regular norm, and `μ` is a unit. In that case the double is regular as well +(`ConicAlgebra.isGPRRegular_cay_norm`). + +`B` is only a `NonAssocRing` here, so associativity is part of the statement. The direction `⇐` is +`ConicAlgebra.IsComposition.cay`, applied to the `Ring` structure that associativity provides. -/ +theorem isComposition_cay_iff : + (C.cay μ).IsComposition.{u, v, u} ↔ + (∀ a b c : B, a * b * c = a * (b * c)) ∧ C.IsComposition.{u, v, u} ∧ + C.norm.IsGPRRegular ∧ IsUnit μ := by + refine ⟨fun h ↦ ⟨h.mul_assoc_of_cay, h.of_cay, h.isGPRRegular_of_cay, h.isUnit_of_cay⟩, ?_⟩ + rintro ⟨hassoc, hC, hreg, hμ⟩ + let : Ring B := { (inferInstance : NonAssocRing B) with mul_assoc := hassoc } + let : Algebra k B := Algebra.ofModule + (fun r (x y : B) ↦ by exact smul_mul_assoc r x y) + (fun r (x y : B) ↦ by exact (smul_comm r x y).symm) + exact IsComposition.cay C hμ hreg hC.isMultiplicative + +end CayleyDickson + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/ComplexQuaternion.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/ComplexQuaternion.lean new file mode 100644 index 0000000000..36812f854e --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/ComplexQuaternion.lean @@ -0,0 +1,202 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Examples +public import Mathlib.Analysis.Quaternion + +/-! +# The first two rungs are mathlib's `ℂ` and `ℍ` + +The Cayley–Dickson tower over `ℝ` at `μᵢ = -1` produces algebras of dimension `2` and `4` which +*are* the complex numbers and the quaternions. mathlib has both, so the identification is a +theorem, not a definition: this file builds the two `AlgEquiv`s and checks that they carry the +conic norm to `Complex.normSq` and `Quaternion.normSq` and the conic conjugation to `star`. + +Nothing else in the project depends on this file. It exists so that the tower is anchored to +mathlib's objects rather than merely resembling them, and so that a reader who knows +`Complex.normSq` can recognize `ConicAlgebra.norm`. + +## The dictionary + +`Cay₂ ℝ (-1)` is `ℝ × ℝ` with `(a, b)(c, d) = (ac - db, da + bc)` — the conjugation of the base +ring being the identity — which is multiplication of `a + bi`. So `(a, b) ↦ ⟨a, b⟩`. + +`Cay₄ ℝ (-1) (-1)` is `ℂ × ℂ` with `(u₁, v₁)(u₂, v₂) = (u₁u₂ - (conj v₂)v₁, v₂u₁ + v₁(conj u₂))`, +which is multiplication of `u + vj`. Writing `u = a + bi` and `v = c + di` gives `a + bi + cj + dk` +with `k = ij`, so `((a, b), (c, d)) ↦ ⟨a, b, c, d⟩`. mathlib's `Quaternion ℝ` is +`QuaternionAlgebra ℝ (-1) 0 (-1)`, whose structure constants are exactly `i² = j² = -1`. + +⚠ These are equivalences at `μ₁ = μ₂ = -1` over `ℝ` specifically. `Cay₄ k μ₁ μ₂` and +`QuaternionAlgebra k a b c` are **not** comparable in general — see overview trap 3: +`QuaternionAlgebra` takes arbitrary structure constants and always produces a free module, while +`Cay₄ k μ₁ μ₂` is a composition algebra when `2` and the `μᵢ` are units +(`ConicAlgebra.isComposition_cay₄`, which needs `Invertible (2 : k)`: in characteristic `2` the +polar form of the norm of `Cay₄ k μ₁ μ₂` is identically zero, so it is never a composition +algebra). + +## Main results + +* `ConicAlgebra.realComplexAlgEquiv` : `Cay₂ ℝ (-1) ≃ₐ[ℝ] ℂ`. +* `ConicAlgebra.realQuaternionAlgEquiv` : `Cay₄ ℝ (-1) (-1) ≃ₐ[ℝ] ℍ[ℝ]`. +* `ConicAlgebra.norm_realComplexAlgEquiv`, `ConicAlgebra.norm_realQuaternionAlgEquiv` : the + equivalences are isometries for `Complex.normSq` and `Quaternion.normSq`. +* `ConicAlgebra.conj_realComplexAlgEquiv`, `ConicAlgebra.conj_realQuaternionAlgEquiv` : they carry + `ConicAlgebra.conj` to `star`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.4, 19.18. +-/ + +@[expose] public section + +namespace ConicAlgebra + +open Quaternion + +/-! ### `Cay₂ ℝ (-1) = ℂ` -/ + +/-- **The rank-two rung is `ℂ`.** `(a, b) ↦ a + bi`. -/ +def realComplexAlgEquiv : RealComplex ≃ₐ[ℝ] ℂ where + toFun x := ⟨x.1, x.2⟩ + invFun z := ((z.re, z.im) : ℝ × ℝ) + left_inv _ := rfl + right_inv _ := rfl + map_add' _ _ := rfl + map_mul' x y := by + refine Complex.ext ?_ ?_ + · change x.1 * y.1 + (-1 : ℝ) • ((baseRing ℝ).conj y.2 * x.2) = _ + rw [Complex.mul_re, baseRing_conj_apply] + ring + · change y.2 * x.1 + x.2 * (baseRing ℝ).conj y.1 = _ + rw [Complex.mul_im, baseRing_conj_apply] + ring + commutes' r := by + refine Complex.ext ?_ ?_ <;> + simp [Algebra.algebraMap_eq_smul_one] + +@[simp] theorem realComplexAlgEquiv_apply (x : RealComplex) : + realComplexAlgEquiv x = ⟨x.1, x.2⟩ := rfl + +/-- The equivalence is an **isometry**: the conic norm of `Cay₂ ℝ (-1)` is `Complex.normSq`. -/ +theorem norm_realComplexAlgEquiv (x : RealComplex) : + (cay₂ ℝ (-1)).norm x = Complex.normSq (realComplexAlgEquiv x) := by + rw [cay_norm_apply, Complex.normSq_apply] + change (QuadraticMap.sq (R := ℝ)) x.1 - (-1 : ℝ) * (QuadraticMap.sq (R := ℝ)) x.2 = _ + simp only [QuadraticMap.sq_apply, realComplexAlgEquiv_apply] + ring + +/-- The equivalence carries the conic conjugation to complex conjugation. -/ +theorem conj_realComplexAlgEquiv (x : RealComplex) : + realComplexAlgEquiv ((cay₂ ℝ (-1)).conj x) = star (realComplexAlgEquiv x) := by + refine Complex.ext ?_ ?_ <;> + rw [realComplexAlgEquiv_apply, cay_conj_apply] <;> + simp [baseRing_conj_apply] + +/-! ### `Cay₄ ℝ (-1) (-1) = ℍ` + +⚠ Two elaboration hazards meet here, and the proofs are shaped around both. + +The first is the one documented in `Conic/CayleyDicksonAlternative.lean`: +`ConicAlgebra.cay_conj_apply` produces a pair *literal*, whose inferred type is `ℝ × ℝ` rather +than `Cay₂ ℝ μ`, and once such a literal sits inside a product the `Cay` simp lemmas no longer +unify. So the conjugation is only ever rewritten through its **components**, and +`cay_conj_apply` is removed from the default simp set with `-cay_conj_apply`. + +The second is that `ℍ[ℝ]` is a `def` wrapping `QuaternionAlgebra ℝ (-1) 0 (-1)`. A goal mixing +that spelling with `RealQuaternion` is not type-correct at `rw`'s transparency, so all quaternion +arithmetic is done in `ConicAlgebra.quaternion_mk_mul` and `ConicAlgebra.quaternion_star_mk`, +whose statements mention no `Cay`, and then used as fully instantiated rewrites. -/ + +private theorem cay₂_conj_fst (μ : ℝ) (x : Cay₂ ℝ μ) : + ((cay₂ ℝ μ).conj x).1 = x.1 := by + rw [cay_conj_apply, baseRing_conj_apply] + +private theorem cay₂_conj_snd (μ : ℝ) (x : Cay₂ ℝ μ) : + ((cay₂ ℝ μ).conj x).2 = -x.2 := by + rw [cay_conj_apply] + +private theorem cay₄_conj_fst (x : RealQuaternion) : + ((cay₄ ℝ (-1) (-1)).conj x).1 = (cay₂ ℝ (-1)).conj x.1 := by + rw [cay_conj_apply] + +private theorem cay₄_conj_snd (x : RealQuaternion) : + ((cay₄ ℝ (-1) (-1)).conj x).2 = -x.2 := by + rw [cay_conj_apply] + +private theorem quaternion_mk_mul (a₁ b₁ c₁ d₁ a₂ b₂ c₂ d₂ : ℝ) : + (⟨a₁, b₁, c₁, d₁⟩ : ℍ[ℝ]) * ⟨a₂, b₂, c₂, d₂⟩ = + ⟨a₁ * a₂ - b₁ * b₂ - c₁ * c₂ - d₁ * d₂, + a₁ * b₂ + b₁ * a₂ + c₁ * d₂ - d₁ * c₂, + a₁ * c₂ - b₁ * d₂ + c₁ * a₂ + d₁ * b₂, + a₁ * d₂ + b₁ * c₂ - c₁ * b₂ + d₁ * a₂⟩ := by + rw [QuaternionAlgebra.mk_mul_mk, QuaternionAlgebra.mk.injEq] + exact ⟨by ring, by ring, by ring, by ring⟩ + +private theorem quaternion_star_mk (a b c d : ℝ) : + star (⟨a, b, c, d⟩ : ℍ[ℝ]) = ⟨a, -b, -c, -d⟩ := by + rw [QuaternionAlgebra.star_mk, QuaternionAlgebra.mk.injEq] + exact ⟨by ring, rfl, rfl, rfl⟩ + +/-- The underlying map `((a, b), (c, d)) ↦ a + bi + cj + dk`. -/ +def toQuaternion (x : RealQuaternion) : ℍ[ℝ] := ⟨x.1.1, x.1.2, x.2.1, x.2.2⟩ + +theorem toQuaternion_apply (x : RealQuaternion) : + toQuaternion x = ⟨x.1.1, x.1.2, x.2.1, x.2.2⟩ := rfl + +theorem toQuaternion_mul (x y : RealQuaternion) : + toQuaternion (x * y) = toQuaternion x * toQuaternion y := by + change (⟨(x * y).1.1, (x * y).1.2, (x * y).2.1, (x * y).2.2⟩ : ℍ[ℝ, -1, 0, -1]) = + (⟨x.1.1, x.1.2, x.2.1, x.2.2⟩ : ℍ[ℝ, -1, 0, -1]) * ⟨y.1.1, y.1.2, y.2.1, y.2.2⟩ + rw [QuaternionAlgebra.mk_mul_mk, QuaternionAlgebra.mk.injEq] + refine ⟨?_, ?_, ?_, ?_⟩ <;> + simp [-cay_conj_apply, Cay.fst_mul, Cay.snd_mul, cay₂_conj_fst, cay₂_conj_snd] <;> + ring + +/-- **The rank-four rung is `ℍ`.** `((a, b), (c, d)) ↦ a + bi + cj + dk`. -/ +def realQuaternionAlgEquiv : RealQuaternion ≃ₐ[ℝ] ℍ[ℝ] where + toFun := toQuaternion + invFun q := (((q.re, q.imI) : ℝ × ℝ), ((q.imJ, q.imK) : ℝ × ℝ)) + left_inv _ := rfl + right_inv _ := rfl + map_add' _ _ := rfl + map_mul' := toQuaternion_mul + commutes' r := by + change (⟨(algebraMap ℝ RealQuaternion r).1.1, (algebraMap ℝ RealQuaternion r).1.2, + (algebraMap ℝ RealQuaternion r).2.1, (algebraMap ℝ RealQuaternion r).2.2⟩ : + ℍ[ℝ, -1, 0, -1]) = algebraMap ℝ ℍ[ℝ, -1, 0, -1] r + rw [QuaternionAlgebra.algebraMap_eq, QuaternionAlgebra.mk.injEq] + refine ⟨?_, ?_, ?_, ?_⟩ <;> simp [Algebra.algebraMap_eq_smul_one] + +@[simp] theorem realQuaternionAlgEquiv_apply (x : RealQuaternion) : + realQuaternionAlgEquiv x = ⟨x.1.1, x.1.2, x.2.1, x.2.2⟩ := rfl + +/-- The equivalence is an **isometry**: the conic norm of `Cay₄ ℝ (-1) (-1)` is +`Quaternion.normSq`. -/ +theorem norm_realQuaternionAlgEquiv (x : RealQuaternion) : + (cay₄ ℝ (-1) (-1)).norm x = Quaternion.normSq (realQuaternionAlgEquiv x) := by + rw [cay_norm_apply, Quaternion.normSq_def'] + change (cay₂ ℝ (-1)).norm x.1 - (-1 : ℝ) * (cay₂ ℝ (-1)).norm x.2 = _ + rw [cay_norm_apply, cay_norm_apply] + change (QuadraticMap.sq (R := ℝ)) x.1.1 - (-1 : ℝ) * (QuadraticMap.sq (R := ℝ)) x.1.2 - + (-1 : ℝ) * + ((QuadraticMap.sq (R := ℝ)) x.2.1 - + (-1 : ℝ) * (QuadraticMap.sq (R := ℝ)) x.2.2) = _ + simp only [QuadraticMap.sq_apply, realQuaternionAlgEquiv_apply] + ring + +/-- The equivalence carries the conic conjugation to quaternionic conjugation. -/ +theorem conj_realQuaternionAlgEquiv (x : RealQuaternion) : + realQuaternionAlgEquiv ((cay₄ ℝ (-1) (-1)).conj x) = star (realQuaternionAlgEquiv x) := by + change (⟨((cay₄ ℝ (-1) (-1)).conj x).1.1, ((cay₄ ℝ (-1) (-1)).conj x).1.2, + ((cay₄ ℝ (-1) (-1)).conj x).2.1, ((cay₄ ℝ (-1) (-1)).conj x).2.2⟩ : ℍ[ℝ, -1, 0, -1]) = + star (⟨x.1.1, x.1.2, x.2.1, x.2.2⟩ : ℍ[ℝ, -1, 0, -1]) + rw [QuaternionAlgebra.star_mk, QuaternionAlgebra.mk.injEq] + refine ⟨?_, ?_, ?_, ?_⟩ <;> + simp [-cay_conj_apply, cay₄_conj_fst, cay₄_conj_snd, cay₂_conj_fst, cay₂_conj_snd] + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean new file mode 100644 index 0000000000..b8fae174e8 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean @@ -0,0 +1,158 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity + +/-! +# Composition algebras (`GPR 19.5`) + +A **composition algebra** over a commutative ring `k` is a conic algebra `C` (`GPR 16.1`) which is +finitely generated projective as a `k`-module and whose norm is + +* **non-singular** in `GPR`'s sense (`QuadraticForm.IsGPRNonsingular`, `GN C.8(e)`: the radical + vanishes after base change to every field), and +* **multiplicative** (`ConicAlgebra.IsMultiplicative`, `GPR 19.1`: `n(xy) = n(x) n(y)`). + +Over a field these are exactly `k`, the quadratic étale algebras, the quaternion algebras and the +octonion algebras, of dimensions 1, 2, 4, 8. + +## Main definitions + +* `ConicAlgebra.IsComposition` : **`GPR 19.5`**. + +## Main results + +* `ConicAlgebra.isComposition_baseRing` : `k` itself, with norm the squaring map, is the rank-one + composition algebra. +* `ConicAlgebra.IsComposition.isGPRRegular` : when `2 ∈ kˣ` the norm of a composition algebra is + regular, by `GN (C.8.2)`. This is *false* without a hypothesis on `2` — see + `QuadraticForm.rankOne`, which is `k` itself in characteristic 2. + +## Implementation notes + +**Why a predicate and not a structure extending `ConicAlgebra`.** The norm of a conic algebra is +data; being a composition algebra is a *property* of that data, so `IsComposition` is `Prop`-valued +and takes `C : ConicAlgebra k A` as an argument. This keeps the three axes of overview §2 +separate: the algebra structure is in `A`'s instances, the module regularity is in the +`[Module.Finite k A] [Module.Projective k A]` instance arguments, and only the two genuinely +norm-theoretic clauses are fields of `IsComposition`. + +⚠ **Finite generation is assumed here, where `GPR` derives it.** This is a genuine, if slight, +divergence from `GPR 19.5`, and it goes in the direction of *less* generality. `GPR` assumes only +that the underlying module is projective of locally constant rank — allowing that rank to be +infinite a priori — and then *proves* the rank is finite, indeed one of `1, 2, 4, 8` (`GPR 19.18`). +We assume `[Module.Finite k A]` outright. The two definitions therefore pick out the same objects, +but only a posteriori: ours builds in a conclusion of the theory rather than deriving it. So a +`GPR` composition algebra is an `IsComposition` only by way of `GPR 19.18`, and until that theorem +is formalized here, a statement about "every composition algebra" is strictly a statement about the +finitely generated ones. + +**No separate "locally constant rank" clause**, although `GPR 19.5` states one: over a commutative +ring the rank of a finitely generated projective module is automatically locally constant on +`Spec k` (this project proves as much in `Module/RankDecomposition.lean`, +`Module.finite_range_rankAtStalk` and `Module.rankIdempotent`), so the clause would be redundant. +The *constancy* of the rank — which is what makes the rank dichotomy `1, 2, 4, 8` a statement about +a single number — is a hypothesis on theorems, not part of the definition. + +**No `PreCompositionAlgebra`.** `GPR` defines one; we deliberately do not (overview, *Design +decisions* 1): the bundle "projective + non-degenerate + multiplicative" is not stable under base +change (`GPR 19.7(a)`, with `GPR 19.4` as the counterexample), and the one theorem that motivates +the notion (`GPR 19.3`) is stated with those three as separate hypotheses instead. + +**Universes.** `QuadraticForm.IsGPRNonsingular` quantifies over all fields in a universe, so it +carries a third universe parameter beyond those of `k` and `A`; `IsComposition` inherits it, and +names it the same way `QuadraticForm.IsEKMNondegenerate` does. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.1, 19.5. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European J. Math. **11** (2025), art. 42, + C.8 (non-singularity). +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + +/-- **`GPR 19.5`: `C` is a composition algebra.** A conic algebra whose underlying module is +finitely generated projective (an instance argument, not a field) and whose norm is non-singular +in `GPR`'s sense and multiplicative. + +⚠ **Finite generation is a hypothesis here and a theorem in `GPR`**, which assumes only projective +of locally constant rank and derives finiteness of the rank from `GPR 19.18`. This definition is +correspondingly, and very slightly, less general; see the module docstring. + +⚠ **Non-singular, not regular and not non-degenerate.** `QuadraticForm.IsGPRNonsingular` is the +base-change-stable vanishing of the radical (`GN C.8(e)`), which is what makes composition algebras +stable under base change. It is strictly weaker than `QuadraticForm.IsGPRRegular` unless `2 ∈ kˣ` +(`QuadraticForm.isGPRRegular_iff_isGPRNonsingular`), and it is not mathlib's +`LinearMap.BilinForm.Nondegenerate`; see overview §6(b). -/ +structure IsComposition.{w'} (C : ConicAlgebra k A) : Prop where + /-- The norm is non-singular in `GPR`'s sense (`GN C.8(e)`): its radical vanishes after base + change to every field. -/ + isGPRNonsingular : QuadraticForm.IsGPRNonsingular.{u, v, w'} C.norm + /-- The norm permits composition: `n(xy) = n(x) n(y)` (`GPR 19.1`). -/ + isMultiplicative : C.IsMultiplicative + +namespace IsComposition + +variable {C : ConicAlgebra k A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem norm_mul (h : C.IsComposition.{u, v, w}) (x y : A) : + C.norm (x * y) = C.norm x * C.norm y := + h.isMultiplicative.norm_mul x y + +omit [SMulCommClass k A A] in +/-- **Norm-associativity** of a composition algebra (`GPR 16.5`): `n(xy, z) = n(y, (conj x)z)`. -/ +theorem polar_mul_left (h : C.IsComposition.{u, v, w}) (x y z : A) : + QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm y (C.conj x * z) := + h.isMultiplicative.polar_mul_left x y z + +omit [IsScalarTower k A A] in +/-- **Norm-associativity** of a composition algebra (`GPR 16.5`): `n(xy, z) = n(x, z(conj y))`. -/ +theorem polar_mul_right (h : C.IsComposition.{u, v, w}) (x y z : A) : + QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm x (z * C.conj y) := + h.isMultiplicative.polar_mul_right x y z + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- When `2 ∈ kˣ`, the norm of a composition algebra is **regular** (`GN (C.8.2)`), i.e. its polar +form is an isomorphism onto the dual and not merely injective. + +⚠ The hypothesis on `2` is not removable: `ConicAlgebra.baseRing k` is a composition algebra whose +norm is `QuadraticForm.rankOne 1`, and over `ℤ` that form is non-singular but not regular +(`QuadraticForm.not_isGPRRegular_rankOne_one_int`). -/ +theorem isGPRRegular [Invertible (2 : k)] (h : C.IsComposition.{u, v, u}) : + C.norm.IsGPRRegular := + h.isGPRNonsingular.isGPRRegular + +end IsComposition + +variable (k) in +/-- **The rank-one composition algebra.** `k` itself, with norm the squaring map +(`ConicAlgebra.baseRing`), is a composition algebra: the norm is `QuadraticForm.rankOne 1`, which is +non-singular over any commutative ring (`QuadraticForm.isGPRNonsingular_rankOne`), and `(xy)² = +x²y²`. + +Note that this holds with no hypothesis on `2`, even though `⟨1⟩` is *regular* only when `2` is a +unit. -/ +theorem isComposition_baseRing : (baseRing k).IsComposition.{u, u, u} where + isGPRNonsingular := by + have hsq : (baseRing k).norm = QuadraticForm.rankOne (1 : k) := by + rw [QuadraticForm.rankOne, one_smul] + rfl + rw [hsq] + exact QuadraticForm.isGPRNonsingular_rankOne isUnit_one + isMultiplicative := isMultiplicative_baseRing k + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Doubling.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Doubling.lean new file mode 100644 index 0000000000..4602ec6fbf --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Doubling.lean @@ -0,0 +1,174 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Alternative +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Examples +public import LeanPool.CompositionAlgebrasOverRings.Conic.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.OrthogonalComplement +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Representation + +/-! +# A regular subalgebra of a composition algebra splits off (`GPR 19.16(a)`) + +Let `C` be a composition algebra over an **LG ring** `k` and let `B ⊆ C` be a unital subalgebra +whose restricted norm is **regular**. If the orthogonal complement `Bᗮ` has full support — the +precise sense in which `B` is *properly* contained in `C` — then there is a `v ∈ Bᗮ` with `n(v)` +a unit, and + + `Cay(B, -n(v)) ↪ C`, `u + wj ↦ u + wv`, + +is an injective homomorphism. This is `GPR 19.16(a)`: the doubling process, run backwards. + +## The three steps + +1. **Split.** `n|_B` regular makes `B` a direct summand, `C = B ⊕ Bᗮ`, with + `n = n|_B ⊥ n|_{Bᗮ}` (`QuadraticForm/OrthogonalComplement.lean`). In particular `Bᗮ` is again + finitely generated projective, and `n|_{Bᗮ}` is non-singular by `GN (C.8.3)`. +2. **Represent.** Over an LG ring a non-singular form on a finitely generated projective module of + full support represents a unit (`GPR 11.26`, `QuadraticForm/Representation.lean`). Applied to + `n|_{Bᗮ}` this produces the element `v`. +3. **Double.** `v ⊥ B` and `n(v) ∈ kˣ` are exactly the hypotheses of `GPR 18.1` + (`Conic/Doubling.lean`), which turns `B + Bv` into a copy of `Cay(B, -n(v))`. + +## Hypotheses + +**Alternativity is derived, not assumed.** Every composition algebra is alternative over an +arbitrary commutative ring; `ConicAlgebra.IsComposition.isAlternative_general` supplies the +instance used by the doubling identities. + +**Full support of `Bᗮ`, not `B ≠ C`.** Over a ring the two are genuinely different: on a product +ring a subalgebra may fill up one factor and not the other, and then no single `v` can work. Full +support of the complement — `F ⊗ Bᗮ ≠ 0` for every field `F ∈ k`-alg — is what the representation +lemma consumes, and it is the honest hypothesis. + +**Regularity of `n|_B`, not non-singularity.** It is used twice: to split `C` at all, and, in +`ConicAlgebra.cayToAlgebra_injective`, to know that the doubled norm has vanishing radical +(`GN (C.8.3)`). Both fail for merely non-singular forms in characteristic 2. + +## Main results + +* `ConicAlgebra.hasFullSupport_polarOrthogonal_of_finrank_lt` : the rank criterion for the + full-support hypothesis. +* `ConicAlgebra.IsComposition.exists_isUnit_norm_orthogonal` : steps 1–2, the element `v`. +* `ConicAlgebra.IsComposition.exists_cayToAlgebra` : **`GPR 19.16(a)`**. +* `ConicAlgebra.IsComposition.exists_cayToAlgebra_of_field` : the same over a field, where + alternativity is automatic. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.26, 18.1, + 19.16(a). +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, (C.8.3), C.13(a). +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {B : NonAssocSubalgebra k A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- The submodule underlying a unital subalgebra, as a subset of the algebra. -/ +theorem mem_toSubmodule_iff {x : A} : + x ∈ B.toNonUnitalSubalgebra.toSubmodule ↔ x ∈ B := Iff.rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Projective k A] in +/-- **`B` is properly contained in `C` at every point.** If the rank of `B` is smaller than that +of `C` over every field in `k`-alg, the orthogonal complement has full support, which is what the +representation lemma consumes. + +This is the usable form of the hypothesis: over a ring, `B ≠ C` is *not* enough — on a product ring +a subalgebra can fill up one factor — and the rank inequality is exactly the pointwise statement +that it does not. -/ +theorem hasFullSupport_polarOrthogonal_of_finrank_lt + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) + (hlt : ∀ (F : Type u) [Field F] [Algebra k F], + Module.finrank F (F ⊗[k] B.toNonUnitalSubalgebra.toSubmodule) < + Module.finrank F (F ⊗[k] A)) : + Module.HasFullSupport k + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule) := fun F _ _ ↦ + QuadraticForm.nontrivial_baseChange_polarOrthogonal hreg F (hlt F) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 19.16(a)`, steps 1–2: the element `v`.** + +The complement of `B` is finitely generated projective with non-singular restricted norm, so over +an LG ring the representation lemma `GPR 11.26` finds a vector of unit norm in it as soon as it has +full support. -/ +theorem IsComposition.exists_isUnit_norm_orthogonal (hLG : IsLGRing k) + (h : C.IsComposition.{u, v, u}) + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) + (hsupp : Module.HasFullSupport k + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule)) : + ∃ v : A, IsUnit (C.norm v) ∧ ∀ b ∈ B, polar C.norm b v = 0 := by + have := QuadraticForm.finite_polarOrthogonal hreg + have := QuadraticForm.projective_polarOrthogonal hreg + obtain ⟨w, hw⟩ := QuadraticForm.exists_isUnit_apply_of_hasFullSupport hLG + (QuadraticForm.IsGPRNonsingular.comp_polarOrthogonal_subtype hreg h.isGPRNonsingular) hsupp + exact ⟨(w : A), hw, fun b hb ↦ w.2 b hb⟩ + +/-- **`GPR 19.16(a)`.** Over an LG ring, a unital subalgebra `B` of a composition algebra `C` whose +restricted norm is regular and whose orthogonal complement has full support is doubled inside `C`: +there is a unit `μ = -n(v)` and an injective, unital, multiplicative, isometric map +`Cay(B, μ) → C`. + +The map is `ConicAlgebra.cayToAlgebra`, `u + wj ↦ u + wv`; its image is the subalgebra `B + Bv`. -/ +theorem IsComposition.exists_cayToAlgebra (hLG : IsLGRing k) + (h : C.IsComposition.{u, v, u}) + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) + (hsupp : Module.HasFullSupport k + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule)) : + ∃ v : A, IsUnit (C.norm v) ∧ (∀ b ∈ B, polar C.norm b v = 0) ∧ + Function.Injective (cayToAlgebra C B v) ∧ + (∀ p q : Cay (C.restrict B) (-C.norm v), + cayToAlgebra C B v (p * q) = cayToAlgebra C B v p * cayToAlgebra C B v q) ∧ + (∀ p : Cay (C.restrict B) (-C.norm v), + C.norm (cayToAlgebra C B v p) = ((C.restrict B).cay (-C.norm v)).norm p) := by + let : IsAlternative A := h.isAlternative_general + obtain ⟨v, hu, hBv⟩ := h.exists_isUnit_norm_orthogonal hLG hreg hsupp + refine ⟨v, hu, hBv, ?_, ?_, ?_⟩ + · exact cayToAlgebra_injective hBv hu h.isMultiplicative hreg + · exact cayToAlgebra_mul hBv C.conjIsInvolution_of_projective hu + · exact norm_cayToAlgebra hBv h.isMultiplicative + +end ConicAlgebra + +namespace ConicAlgebra + +section Field + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] + {C : ConicAlgebra K A} {B : NonAssocSubalgebra K A} + +/-- **`GPR 19.16(a)` over a field**, where alternativity of `C` is automatic (`GPR 19.3`) and the +LG hypothesis is discharged by `isLGRing_of_field`. -/ +theorem IsComposition.exists_cayToAlgebra_of_field (h : C.IsComposition.{u, v, u}) + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) + (hsupp : Module.HasFullSupport K + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule)) : + ∃ v : A, IsUnit (C.norm v) ∧ (∀ b ∈ B, polar C.norm b v = 0) ∧ + Function.Injective (cayToAlgebra C B v) ∧ + (∀ p q : Cay (C.restrict B) (-C.norm v), + cayToAlgebra C B v (p * q) = cayToAlgebra C B v p * cayToAlgebra C B v q) ∧ + (∀ p : Cay (C.restrict B) (-C.norm v), + C.norm (cayToAlgebra C B v p) = ((C.restrict B).cay (-C.norm v)).norm p) := + h.exists_cayToAlgebra (isLGRing_of_field K) hreg hsupp + +end Field + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean new file mode 100644 index 0000000000..1aa4cade6f --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean @@ -0,0 +1,207 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Octonion +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division +public import Mathlib.Basic.Real.Basic + +/-! +# The classical tower `ℝ, ℂ, ℍ, 𝕆` + +Specializing the Cayley–Dickson tower of `Composition/Octonion.lean` to `μ₁ = μ₂ = μ₃ = -1` over +an ordered field gives the classical chain of composition algebras in which every nonzero element +is invertible, of ranks `1, 2, 4, 8` — division algebras in the sense of `GPR 8.6`, being +alternative. Over `ℝ` these are the reals, the complex numbers, the quaternions and the octonions. + +The mechanism is that a negative scalar keeps the norm **positive definite**: the norm of +`Cay(B, μ)` is `n_B(u) - μ n_B(v)`, and for `μ < 0` that is a sum of two non-negative terms which +vanishes only when both do. A positive definite form is anisotropic, and an anisotropic norm makes +every nonzero element invertible, because `x (conj x) = n(x)·1` exhibits `n(x)⁻¹ · (conj x)` as a +two-sided inverse of `x`. + +Note that the inverse is obtained here **without** alternativity or associativity: the identity +`x (conj x) = (conj x) x = n(x)·1` holds in every conic algebra, so the inverse is immediate once +`n(x)` is a unit (`ConicAlgebra.hasTwoSidedInverses_of_anisotropic`). ⚠ That is **not** yet division +in the sense of `GPR 8.6` (bijective left and right multiplication by nonzero elements): the real +sedenions are anisotropic, so have such inverses, but have zero divisors (`GPR Exc. 19.29(e)`, +`ConicAlgebra.not_isDivision_realSedenion`). Alternativity is what upgrades the inverse to division +— `(conj x)(xy) = n(x) y` — and the four algebras here are alternative +(`ConicAlgebra.isDivision_of_anisotropic`, applied in `ConicAlgebra.isDivision_realOctonion`). + +## Main results + +* `ConicAlgebra.PosDef.cay` : `μ < 0` preserves positive definiteness under doubling. +* `ConicAlgebra.posDef_cay₈`, `ConicAlgebra.exists_inv_cay₈` : the rank-8 member of the tower at + negative scalars is positive definite, hence every nonzero element is invertible. +* `ConicAlgebra.RealOctonion` : the real octonions `𝕆`, with `finrank_realOctonion` (rank 8), + `isComposition_realOctonion`, `isAlternative_realOctonion`, `exists_inv_realOctonion` and + `isDivision_realOctonion` (`𝕆` is a division algebra in the sense of `GPR 8.6`). +* `ConicAlgebra.exists_mul_ne_mul_realQuaternion`, + `ConicAlgebra.exists_mul_mul_ne_mul_mul_realOctonion` : `ℍ` is not commutative and `𝕆` is not + associative — the explicit witnesses that the tower stops. + +## Relation to mathlib's `ℂ` and `ℍ` + +`ConicAlgebra.Cay₂ ℝ (-1)` and `ConicAlgebra.Cay₄ ℝ (-1) (-1)` are identified with mathlib's +`Complex` and `Quaternion ℝ` in `Composition/ComplexQuaternion.lean` +(`ConicAlgebra.realComplexAlgEquiv`, `ConicAlgebra.realQuaternionAlgEquiv`), as isometries carrying +the conjugation to `star`. Nothing in this file depends on those identifications. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.18, 23. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +/-! ### Positive definiteness under doubling -/ + +section Ordered + +variable {k : Type u} [CommRing k] [LinearOrder k] [IsStrictOrderedRing k] + {B : Type v} [NonAssocRing B] [Module k B] [SMulCommClass k B B] [IsScalarTower k B B] + +/-- **Doubling at a negative scalar preserves positive definiteness.** The norm of `Cay(B, μ)` is +`n_B(u) - μ n_B(v)`; for `μ < 0` both terms are non-negative, and at least one is strictly +positive +unless `u = v = 0`. -/ +theorem PosDef.cay (C : ConicAlgebra k B) {μ : k} (hμ : μ < 0) (h : C.norm.PosDef) : + (C.cay μ).norm.PosDef := by + intro x hx + rw [cay_norm_apply] + rcases eq_or_ne x.1 0 with h1 | h1 + · have h2 : x.2 ≠ 0 := fun h2 ↦ hx (Cay.ext h1 h2) + have : 0 < -μ * C.norm x.2 := mul_pos (neg_pos.mpr hμ) (h _ h2) + nlinarith [h.nonneg x.1] + · nlinarith [h _ h1, h.nonneg x.2, neg_pos.mpr hμ] + +variable (k) in +/-- The norm of the base ring, `x ↦ x²`, is positive definite. -/ +theorem posDef_baseRing : (baseRing k).norm.PosDef := fun x hx ↦ by + rw [baseRing_norm_apply] + exact mul_self_pos.mpr hx + +variable (k) + +theorem posDef_cay₂ {μ₁ : k} (h₁ : μ₁ < 0) : (cay₂ k μ₁).norm.PosDef := + PosDef.cay _ h₁ (posDef_baseRing k) + +theorem posDef_cay₄ {μ₁ μ₂ : k} (h₁ : μ₁ < 0) (h₂ : μ₂ < 0) : + (cay₄ k μ₁ μ₂).norm.PosDef := + PosDef.cay _ h₂ (posDef_cay₂ k h₁) + +/-- The rank-8 member of the tower at negative scalars has **positive definite** norm — over +`ℝ`, the sum of eight squares. -/ +theorem posDef_cay₈ {μ₁ μ₂ μ₃ : k} (h₁ : μ₁ < 0) (h₂ : μ₂ < 0) + (h₃ : μ₃ < 0) : + (cay₈ k μ₁ μ₂ μ₃).norm.PosDef := + PosDef.cay _ h₃ (posDef_cay₄ k h₁ h₂) + +end Ordered + +section OrderedField + +variable (K : Type u) [Field K] [LinearOrder K] [IsStrictOrderedRing K] + +/-- In the rank-8 member of the tower at negative scalars over an ordered field, **every nonzero +element is invertible**. -/ +theorem exists_inv_cay₈ {μ₁ μ₂ μ₃ : K} (h₁ : μ₁ < 0) (h₂ : μ₂ < 0) + (h₃ : μ₃ < 0) + {x : Cay₈ K μ₁ μ₂ μ₃} (hx : x ≠ 0) : ∃ y, x * y = 1 ∧ y * x = 1 := + (cay₈ K μ₁ μ₂ μ₃).hasTwoSidedInverses_of_anisotropic (posDef_cay₈ K h₁ h₂ h₃).anisotropic hx + +end OrderedField + +/-! ### The real octonions + +⚠ `RealComplex` and `RealQuaternion` are the Cayley–Dickson doubles, not mathlib's `Complex` and +`Quaternion ℝ`. The identifying `AlgEquiv`s are `ConicAlgebra.realComplexAlgEquiv` and +`ConicAlgebra.realQuaternionAlgEquiv`, in `Composition/ComplexQuaternion.lean`. -/ + +/-- `ℂ` as a Cayley–Dickson double, `Cay(ℝ, -1)`. -/ +abbrev RealComplex : Type := Cay₂ ℝ (-1) + +/-- `ℍ` as a Cayley–Dickson double, `Cay(ℂ, -1)`. -/ +abbrev RealQuaternion : Type := Cay₄ ℝ (-1) (-1) + +/-- **The real octonions `𝕆`**, `Cay(ℍ, -1)`. mathlib has no octonions; this is the +definition of +record here. -/ +abbrev RealOctonion : Type := Cay₈ ℝ (-1) (-1) (-1) + +/-- The conic structure on `𝕆`. -/ +noncomputable abbrev realOctonion : ConicAlgebra ℝ RealOctonion := cay₈ ℝ (-1) (-1) (-1) + +theorem finrank_realComplex : Module.finrank ℝ RealComplex = 2 := finrank_cay₂ ℝ _ + +theorem finrank_realQuaternion : Module.finrank ℝ RealQuaternion = 4 := + finrank_cay₄ ℝ _ _ + +/-- **`𝕆` has dimension 8 over `ℝ`.** -/ +theorem finrank_realOctonion : Module.finrank ℝ RealOctonion = 8 := + finrank_cay₈ ℝ _ _ _ + +/-- **`𝕆` is alternative.** -/ +theorem isAlternative_realOctonion : IsAlternative RealOctonion := inferInstance + +/-- **The norm of `𝕆` is positive definite** — the sum of eight squares. -/ +theorem posDef_realOctonion : realOctonion.norm.PosDef := + posDef_cay₈ ℝ (by norm_num) (by norm_num) (by norm_num) + +/-- **Every nonzero octonion is invertible.** -/ +theorem exists_inv_realOctonion {x : RealOctonion} (hx : x ≠ 0) : + ∃ y, x * y = 1 ∧ y * x = 1 := + exists_inv_cay₈ ℝ (by norm_num) (by norm_num) (by norm_num) hx + +/-- **`𝕆` is a division algebra** in the sense of `GPR 8.6`: it is alternative with anisotropic +norm, so `GPR 13.8` applies (`ConicAlgebra.isDivision_of_anisotropic`). -/ +theorem isDivision_realOctonion : IsDivision RealOctonion := + have : Nontrivial RealOctonion := + Module.nontrivial_of_finrank_pos (R := ℝ) (by rw [finrank_realOctonion]; norm_num) + realOctonion.isDivision_of_anisotropic posDef_realOctonion.anisotropic + +/-! ### Where the tower breaks + +`ℍ` is not commutative and `𝕆` is not associative, with explicit witnesses. These are what stop +the tower: `ConicAlgebra.mul_assoc_cay` needs its input commutative, so `𝕆` gets no `Ring` +structure, and `ConicAlgebra.isMultiplicative_cay` and `ConicAlgebra.isAlternative_cay` need their +input associative, so the sedenions `Cay(𝕆, μ)` get neither a multiplicative norm nor +alternativity. -/ + +/-- The conjugation of `ℂ` moves `i`, which is what makes `ℍ` non-commutative. -/ +theorem conj_i_ne_i : (cay₂ ℝ (-1)).conj ((0, 1) : ℝ × ℝ) ≠ ((0, 1) : ℝ × ℝ) := by + have hc : (cay₂ ℝ (-1)).conj ((0, 1) : ℝ × ℝ) = + (((baseRing ℝ).conj 0, -(1 : ℝ)) : ℝ × ℝ) := + cay_conj_apply _ + intro hcon + rw [hc] at hcon + have h2 := congrArg Prod.snd hcon + norm_num at h2 + +/-- **`ℍ` is not commutative.** -/ +theorem exists_mul_ne_mul_realQuaternion : ∃ x y : RealQuaternion, x * y ≠ y * x := + exists_mul_ne_mul_cay _ _ conj_i_ne_i + +/-- **`𝕆` is not associative** — so the tower cannot be continued by the theorems that built +it, +and the sedenions are neither alternative nor multiplicative. -/ +theorem exists_mul_mul_ne_mul_mul_realOctonion : + ∃ x y z : RealOctonion, x * y * z ≠ x * (y * z) := + let ⟨_, _, h⟩ := exists_mul_ne_mul_realQuaternion + exists_mul_mul_ne_mul_mul_cay _ _ (conjIsInvolution_cay₄ ℝ (-1) (-1)) h + +/-- **`𝕆` is a composition algebra** of rank 8 over `ℝ`. -/ +theorem isComposition_realOctonion : realOctonion.IsComposition.{0, 0, 0} := + letI : Invertible (2 : ℝ) := invertibleOfNonzero (by norm_num) + isComposition_cay₈ ℝ (-1) (-1) (-1) (IsUnit.neg isUnit_one) (IsUnit.neg isUnit_one) + (IsUnit.neg isUnit_one) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Basic.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Basic.lean new file mode 100644 index 0000000000..53961bba40 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Basic.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Classification +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division + +/-! +# Composition algebras over a field: the classification mechanism (`GPR 23.12`) + +Over a field the general theory of the previous layers collapses to two statements, and every +classification result in this layer is one of them applied to a field whose quadratic forms are +understood. + +**Splitting is isotropy.** A composition algebra of dimension `2`, `4`, or `8` over a field is +split exactly when its norm has a nonzero null vector, equivalently exactly when it is not a +division algebra (`GPR 22.18`). Over a field the two isotropy notions of the literature agree +(`QuadraticMap.isGPRIsotropic_iff_not_anisotropic`), so no unimodularity bookkeeping survives. + +**The norm is a complete invariant.** Two composition algebras over a field with isometric norm +forms are isomorphic; this is Layer 9 applied with `isLGRing_of_field`. + +Together these reduce classification over a particular field to two questions about quadratic +forms over that field: which forms of dimension `2`, `4`, `8` are isotropic, and which anisotropic +ones occur as norms. + +⚠ **On "division".** Each division statement below comes in two forms: one with +`ConicAlgebra.HasTwoSidedInverses` — every nonzero element has a two-sided inverse — and one with +`IsDivision`, division in the sense of `GPR 8.6`. In general the first is weaker, but composition +algebras are alternative, so the two agree once `1 ≠ 0` (`GPR 13.8`, +`ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses`), proved in this file); the +`IsDivision` forms are derived from the others by that equivalence. + +## Main results + +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_not_anisotropic` : **`GPR 22.18`** over a field, + in dimensions. +* `ConicAlgebra.IsComposition.isSplitOfRank_of_forall_not_anisotropic` : the `u`-invariant + mechanism — if all forms of the relevant dimension over `K` are isotropic, every composition + algebra of that dimension is split. +* `ConicAlgebra.IsComposition.isSplitOfRank_or_isDivision`, + `ConicAlgebra.IsComposition.isSplitOfRank_or_hasTwoSidedInverses` : the dichotomy — over a field a + composition algebra of dimension `2`, `4`, or `8` is split or a division algebra, never both. +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_not_isDivision` : **`GPR 22.18`** over a field, with + division in the sense of `GPR 8.6`. +* `ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses` : **`GPR 13.8`** for composition + algebras over a field. +* `ConicAlgebra.mul_assoc_of_finrank_eq_two`, `ConicAlgebra.mul_comm_of_finrank_eq_two` : a + two-dimensional conic algebra over a field is an associative commutative algebra (`GPR 16.4`). +* `ConicAlgebra.IsSplitOfRank.isomorphic` : the split algebra of a given dimension is unique. +* `ConicAlgebra.IsComposition.isomorphic_of_isometryEquiv` : composition algebras over a field + with isometric norms are isomorphic (Layer 9 over a field). +* `ConicAlgebra.IsComposition.isomorphic_iff_nonempty_isometryEquiv` : the two previous results + combined — isomorphism and norm isometry are the same relation over a field. + +## Implementation notes + +The results of Layers 9 and 10 are stated with `Module.rankAtStalk`, which over a field is +`Module.finrank` (`Module.rankAtStalk_eq_of_finrank_eq`). This file performs that translation once +so that the field-specific files can speak about dimensions throughout. + +⚠ Dimension one is excluded from the splitting criterion, not overlooked: the rank-one algebra is +the base field, it is split and a division algebra at once, and its norm `x ↦ x²` is anisotropic. +`GPR 22.18` states the equivalence for dimensions greater than one for exactly this reason. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6, 13.8, 16.4, + 19.3, 19.18, 22.18, 23.12. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {K : Type u} {A : Type v} {B : Type w} [Field K] + [NonAssocRing A] [Module K A] [SMulCommClass K A A] [IsScalarTower K A A] + [Module.Finite K A] [Module.Projective K A] + [NonAssocRing B] [Module K B] [SMulCommClass K B B] [IsScalarTower K B B] + [Module.Finite K B] [Module.Projective K B] + {C : ConicAlgebra K A} {D : ConicAlgebra K B} {r : ℕ} + +/-! ### Splitting is isotropy -/ + +/-- **`GPR 22.18` over a field.** A composition algebra of dimension `2`, `4`, or `8` over a field +is split if and only if its norm has a nonzero null vector. + +This is the constant-rank equivalence over an LG ring, with `Module.rankAtStalk` traded for +`Module.finrank` and GPR's unimodular isotropy traded for mathlib's failure of anisotropy — the +two agree over a field. -/ +theorem IsComposition.isSplitOfRank_iff_not_anisotropic (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ↔ ¬ C.norm.Anisotropic := + (h.isSplitOfRank_iff_isGPRIsotropic_of_isLGRing (isLGRing_of_field K) + (Module.rankAtStalk_eq_of_finrank_eq hA) hr).trans + QuadraticMap.isGPRIsotropic_iff_not_anisotropic + +/-- **`GPR 22.18` over a field**, in the form used by every classification below: a nonzero null +vector splits a composition algebra of dimension `2`, `4`, or `8`. -/ +theorem IsComposition.isSplitOfRank_of_exists_ne_zero_norm_eq_zero + (h : C.IsComposition.{u, v, u}) (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) + {x : A} (hx : x ≠ 0) (hnx : C.norm x = 0) : C.IsSplitOfRank r := + (h.isSplitOfRank_iff_not_anisotropic hA hr).mpr fun hani ↦ hx (hani x hnx) + +/-- **The `u`-invariant mechanism.** If every quadratic form on a `K`-space of dimension `r` is +isotropic, then every composition algebra of dimension `r ∈ {2, 4, 8}` over `K` is split. + +This is how every "large enough dimension" classification in this layer is applied: over a finite +field the hypothesis holds for `r ≥ 3` (Chevalley–Warning, +`QuadraticForm.not_anisotropic_of_two_lt_finrank`), and over a local field it holds for `r ≥ 5`, +which covers the octonion case `r = 8`. -/ +theorem IsComposition.isSplitOfRank_of_forall_not_anisotropic (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) + (hiso : ∀ (V : Type v) [AddCommGroup V] [Module K V], Module.finrank K V = r → + ∀ q : QuadraticForm K V, ¬ q.Anisotropic) : C.IsSplitOfRank r := + (h.isSplitOfRank_iff_not_anisotropic hA hr).mpr (hiso A hA C.norm) + +/-- **The dichotomy of `GPR 22.18`.** Over a field a composition algebra of dimension `2`, `4`, or +`8` is either split or a division algebra. -/ +theorem IsComposition.isSplitOfRank_or_hasTwoSidedInverses (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ∨ C.HasTwoSidedInverses := by + by_cases hs : C.IsSplitOfRank r + · exact Or.inl hs + · exact Or.inr (h.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mpr + (not_not.mp ((not_congr (h.isSplitOfRank_iff_not_anisotropic hA hr)).mp hs))) + +/-- **The dichotomy of `GPR 22.18` is exclusive.** A split composition algebra of dimension `2`, +`4`, or `8` is not a division algebra. -/ +theorem IsComposition.not_hasTwoSidedInverses_of_isSplitOfRank (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) (hs : C.IsSplitOfRank r) : + ¬ C.HasTwoSidedInverses := + (h.isSplitOfRank_iff_not_hasTwoSidedInverses (Module.rankAtStalk_eq_of_finrank_eq hA) hr).mp hs + +/-! ### Division in the sense of `GPR 8.6` + +The theorems above are stated with `ConicAlgebra.HasTwoSidedInverses`. For a composition algebra +over a field that is `GPR`'s division property: composition algebras are alternative (`GPR 19.3`), +so `GPR 13.8` applies. The statements below are the same theorems with `GPR`'s `IsDivision`. -/ + +/-- **`GPR 13.8` for composition algebras over a field.** A nonzero composition algebra is a +division algebra in the sense of `GPR 8.6` exactly when every nonzero element has a two-sided +inverse, since composition algebras are alternative (`ConicAlgebra.IsComposition.isAlternative`). -/ +theorem IsComposition.isDivision_iff_hasTwoSidedInverses [Nontrivial A] + (h : C.IsComposition.{u, v, u}) : IsDivision A ↔ C.HasTwoSidedInverses := + have := h.isAlternative + C.isDivision_iff_hasTwoSidedInverses.trans (and_iff_right inferInstance) + +/-- **The dichotomy of `GPR 22.18`, with `GPR 8.6`'s division.** Over a field a composition algebra +of dimension `2`, `4`, or `8` is either split or a division algebra. -/ +theorem IsComposition.isSplitOfRank_or_isDivision (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ∨ IsDivision A := + have : Nontrivial A := Module.nontrivial_of_finrank_pos (R := K) (by omega) + (h.isSplitOfRank_or_hasTwoSidedInverses hA hr).imp_right h.isDivision_iff_hasTwoSidedInverses.mpr + +/-- **A split composition algebra of dimension `2`, `4`, or `8` is not a division algebra** in the +sense of `GPR 8.6`. -/ +theorem IsComposition.not_isDivision_of_isSplitOfRank (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) (hs : C.IsSplitOfRank r) : + ¬ IsDivision A := fun hdiv ↦ + h.not_hasTwoSidedInverses_of_isSplitOfRank hA hr hs (C.hasTwoSidedInverses_of_isDivision hdiv) + +/-- **`GPR 22.18` over a field, with `GPR 8.6`'s division**: a composition algebra of dimension +`2`, `4`, or `8` is split exactly when it is not a division algebra. -/ +theorem IsComposition.isSplitOfRank_iff_not_isDivision (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ↔ ¬ IsDivision A := + ⟨h.not_isDivision_of_isSplitOfRank hA hr, (h.isSplitOfRank_or_isDivision hA hr).resolve_right⟩ + +/-! ### Algebras of dimension two are commutative and associative -/ + +/-- **`GPR 16.4` in dimension two.** A two-dimensional conic algebra over a field is associative: +it is generated by one element (`ConicAlgebra.mul_assoc_of_isLGRing_of_rankAtStalk_eq_two`). -/ +theorem mul_assoc_of_finrank_eq_two (C : ConicAlgebra K A) (hA : Module.finrank K A = 2) : + ∀ x y z : A, x * y * z = x * (y * z) := + C.mul_assoc_of_isLGRing_of_rankAtStalk_eq_two (isLGRing_of_field K) + (Module.rankAtStalk_eq_of_finrank_eq hA) + +/-- **`GPR 16.4` in dimension two.** A two-dimensional conic algebra over a field is commutative: +it is generated by one element (`ConicAlgebra.mul_comm_of_isLGRing_of_rankAtStalk_eq_two`). -/ +theorem mul_comm_of_finrank_eq_two (C : ConicAlgebra K A) (hA : Module.finrank K A = 2) : + ∀ x y : A, x * y = y * x := + C.mul_comm_of_isLGRing_of_rankAtStalk_eq_two (isLGRing_of_field K) + (Module.rankAtStalk_eq_of_finrank_eq hA) + +/-! ### The norm is a complete invariant -/ + +omit [SMulCommClass K A A] [IsScalarTower K A A] [SMulCommClass K B B] [IsScalarTower K B B] + [Module.Finite K A] [Module.Projective K A] [Module.Finite K B] [Module.Projective K B] in +/-- **Uniqueness of the split algebra.** Two conic algebras split of the same dimension are +isomorphic, because both are isomorphic to the same standard model of `GPR 21.19`. -/ +theorem IsSplitOfRank.isomorphic (hC : C.IsSplitOfRank r) (hD : D.IsSplitOfRank r) + (hr : r = 1 ∨ r = 2 ∨ r = 4 ∨ r = 8) : C.Isomorphic D := by + rcases hr with rfl | rfl | rfl | rfl + exacts [(isSplitOfRank_one_iff.mp hC).trans (isSplitOfRank_one_iff.mp hD).symm, + (isSplitOfRank_two_iff.mp hC).trans (isSplitOfRank_two_iff.mp hD).symm, + (isSplitOfRank_four_iff.mp hC).trans (isSplitOfRank_four_iff.mp hD).symm, + (isSplitOfRank_eight_iff.mp hC).trans (isSplitOfRank_eight_iff.mp hD).symm] + +/-- **Layer 9 over a field.** Composition algebras over a field whose norm forms are isometric are +isomorphic. This is the converse direction of the norm classification, specialized by passing +`isLGRing_of_field`; no dimension hypothesis is needed because the isometry transports the +dimension. -/ +theorem IsComposition.isomorphic_of_isometryEquiv (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) (e : C.norm.IsometryEquiv D.norm) : C.Isomorphic D := + hC.exists_isometryEquiv_map_one_map_mul (isLGRing_of_field K) C D hD e + +/-- **Layer 9 over a field, both directions.** Over a field, two composition algebras are +isomorphic exactly when their norm forms are isometric. The easy direction holds over any +commutative ring; the converse is the matched-doubling argument of Layer 9. -/ +theorem IsComposition.isomorphic_iff_nonempty_isometryEquiv (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) : + C.Isomorphic D ↔ Nonempty (C.norm.IsometryEquiv D.norm) := + ⟨fun ⟨e, _, _⟩ ↦ ⟨e⟩, fun ⟨e⟩ ↦ hC.isomorphic_of_isometryEquiv hD e⟩ + +/-- A composition algebra over a field whose norm is isometric to that of a split algebra of +dimension `1`, `2`, `4`, or `8` is itself split of that dimension. -/ +theorem IsComposition.isSplitOfRank_of_isometryEquiv (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) (e : C.norm.IsometryEquiv D.norm) + (hD' : D.IsSplitOfRank r) (hr : r = 1 ∨ r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r := by + have h := hC.isomorphic_of_isometryEquiv hD e + rcases hr with rfl | rfl | rfl | rfl + exacts [h.trans (isSplitOfRank_one_iff.mp hD'), h.trans (isSplitOfRank_two_iff.mp hD'), + h.trans (isSplitOfRank_four_iff.mp hD'), h.trans (isSplitOfRank_eight_iff.mp hD')] + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Finite.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Finite.lean new file mode 100644 index 0000000000..5df9570436 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Finite.lean @@ -0,0 +1,234 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticEtale +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.FiniteField +public import Mathlib.FieldTheory.Finite.Extension + +/-! +# Composition algebras over a finite field (`GPR 23.14`) + +Over a finite field every quadratic form in at least three variables is isotropic +(`QuadraticForm.not_anisotropic_of_two_lt_finrank`, from Chevalley–Warning), so no composition +algebra of dimension four or eight can be a division algebra. By `GPR 22.18` every one of them is +split, hence isomorphic to `Mat₂(K)` or to the Zorn vector matrices `Zor(K)`. + +What survives is dimension two, where the norm is a binary form and can be anisotropic: the +quadratic field extension of `𝔽_q` is a composition division algebra. Thus there is exactly one +composition algebra in each of the dimensions `1`, `4`, `8`, and two — the split one and a +division algebra — in dimension `2`. + +⚠ **On "division".** Each division statement below comes in two forms: one with +`ConicAlgebra.HasTwoSidedInverses` — every nonzero element has a two-sided inverse — and one with +`IsDivision`, division in the sense of `GPR 8.6`. In general the first is weaker, but composition +algebras are alternative, so the two agree once `1 ≠ 0` (`GPR 13.8`, +`ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses`); the `IsDivision` forms are +derived from the others by that equivalence. + +## Main results + +* `ConicAlgebra.IsComposition.isSplitOfRank_of_finite` : **`GPR 23.14`**, every composition + algebra of dimension four or eight over a finite field is split. +* `ConicAlgebra.IsComposition.not_isDivision_of_finite`, + `ConicAlgebra.IsComposition.not_hasTwoSidedInverses_of_finite` : there are no quaternion or + octonion division algebras over a finite field. +* `ConicAlgebra.IsComposition.isomorphic_splitQuaternion_of_finite`, + `ConicAlgebra.IsComposition.isomorphic_zor_of_finite` : the two split models are the only ones. +* `ConicAlgebra.IsComposition.isomorphic_of_finite_of_ne_two` : uniqueness — over a finite field, + any two composition algebras of the same dimension other than two are isomorphic. +* `ConicAlgebra.IsComposition.isomorphic_of_finite_of_isDivision_two`, + `ConicAlgebra.IsComposition.isomorphic_of_finite_of_hasTwoSidedInverses_two` : the remaining + uniqueness statement — any two dimension-two composition division algebras are isomorphic. +* `ConicAlgebra.exists_isComposition_isDivision_not_isSplitOfRank_two`, + `ConicAlgebra.exists_isComposition_hasTwoSidedInverses_not_isSplitOfRank_two` : the matching + existence statement — a quadratic field extension is one. +* `ConicAlgebra.IsComposition.isSplitOfRank_or_isDivision_two`, + `ConicAlgebra.IsComposition.isSplitOfRank_or_hasTwoSidedInverses_two` : in dimension two the + dichotomy is genuine, and this is the only dimension in which it is. + +## Implementation notes + +For the dimension-two division case, `GPR 19.8` first shows that the multiplication is associative +and commutative. Anisotropy makes this quadratic algebra a field. Mathlib's +`FiniteField.algEquivExtension` then identifies it with the unique finite extension of degree two; +this includes characteristic two and avoids duplicating Artin–Schreier theory here. + +Existence is supplied separately by `Composition/QuadraticEtale.lean`, which puts a conic +structure on any quadratic algebra and shows it is a composition algebra exactly when the +discriminant is a unit. Over a finite field that discriminant is always a unit, so any quadratic +field extension is a dimension-two composition division algebra. Existence and uniqueness together +give the dimension-two half of `GPR 23.14` in full. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6, 13.8, 22.18, + 23.14. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {K : Type u} {A : Type v} {B : Type w} [Field K] [Finite K] + [NonAssocRing A] [Module K A] [SMulCommClass K A A] [IsScalarTower K A A] + [Module.Finite K A] [Module.Projective K A] + [NonAssocRing B] [Module K B] [SMulCommClass K B B] [IsScalarTower K B B] + [Module.Finite K B] [Module.Projective K B] + {C : ConicAlgebra K A} {D : ConicAlgebra K B} {r : ℕ} + +/-- **`GPR 23.14`.** Over a finite field every composition algebra of dimension four or eight is +split. The norm is a quadratic form in more than two variables, so Chevalley–Warning produces a +nonzero null vector, and `GPR 22.18` turns that into splitness. -/ +theorem IsComposition.isSplitOfRank_of_finite (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 4 ∨ r = 8) : C.IsSplitOfRank r := + (h.isSplitOfRank_iff_not_anisotropic hA (by tauto)).mpr + (C.norm.not_anisotropic_of_two_lt_finrank (by rcases hr with rfl | rfl <;> omega)) + +/-- **No quaternion or octonion division algebras over a finite field.** -/ +theorem IsComposition.not_hasTwoSidedInverses_of_finite (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 4 ∨ r = 8) : ¬ C.HasTwoSidedInverses := + h.not_hasTwoSidedInverses_of_isSplitOfRank hA (by tauto) (h.isSplitOfRank_of_finite hA hr) + +/-- **`GPR 23.14`: no quaternion or octonion division algebras over a finite field**, with division +in the sense of `GPR 8.6`. -/ +theorem IsComposition.not_isDivision_of_finite (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 4 ∨ r = 8) : ¬ IsDivision A := fun hdiv ↦ + h.not_hasTwoSidedInverses_of_finite hA hr (C.hasTwoSidedInverses_of_isDivision hdiv) + +/-- **Every quaternion algebra over a finite field is `Mat₂(K)`.** -/ +theorem IsComposition.isomorphic_splitQuaternion_of_finite (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = 4) : C.Isomorphic (splitQuaternion K) := + isSplitOfRank_four_iff.mp (h.isSplitOfRank_of_finite hA (Or.inl rfl)) + +/-- **Every octonion algebra over a finite field is the split one**, the algebra `Zor(K)` of Zorn +vector matrices. -/ +theorem IsComposition.isomorphic_zor_of_finite (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = 8) : C.Isomorphic (zor K) := + isSplitOfRank_eight_iff.mp (h.isSplitOfRank_of_finite hA (Or.inr rfl)) + +/-- **Uniqueness away from dimension two.** Over a finite field any two composition algebras of +the same dimension `1`, `4`, or `8` are isomorphic. + +Dimension one is the base field itself (`GPR 19.19`); dimensions four and eight are split by +`GPR 23.14`, and the split algebra of a given dimension is unique. -/ +theorem IsComposition.isomorphic_of_finite_of_ne_two (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) (hA : Module.finrank K A = r) + (hB : Module.finrank K B = r) (hr : r = 1 ∨ r = 4 ∨ r = 8) : C.Isomorphic D := by + rcases hr with rfl | hr + · exact (isSplitOfRank_one (Module.rankAtStalk_eq_of_finrank_eq hA)).isomorphic + (isSplitOfRank_one (Module.rankAtStalk_eq_of_finrank_eq hB)) (Or.inl rfl) + · exact (hC.isSplitOfRank_of_finite hA hr).isomorphic (hD.isSplitOfRank_of_finite hB hr) + (by tauto) + +/-- **The dimension-two division composition algebra over a finite field is unique.** + +By `GPR 19.8`, each algebra is associative and commutative. Its anisotropic multiplicative norm +rules out zero divisors, so module-finiteness makes it a field extension of `K`. Mathlib's +classification of finite-field extensions then supplies a `K`-algebra equivalence between the two +degree-two fields. Uniqueness of the conic norm on a finite projective algebra turns this +equivalence into an isomorphism of composition algebras. -/ +theorem IsComposition.isomorphic_of_finite_of_hasTwoSidedInverses_two + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (hA : Module.finrank K A = 2) (hB : Module.finrank K B = 2) + (hCdiv : C.HasTwoSidedInverses) (hDdiv : D.HasTwoSidedInverses) : C.Isomorphic D := by + let : CommRing A := + { (inferInstance : NonAssocRing A) with + mul_assoc := C.mul_assoc_of_finrank_eq_two hA + mul_comm := C.mul_comm_of_finrank_eq_two hA } + let : Algebra K A := Algebra.ofModule (fun r x y ↦ by exact smul_mul_assoc r x y) + (fun r x y ↦ by exact mul_smul_comm r x y) + let : Nontrivial A := Module.nontrivial_of_finrank_pos (by rw [hA]; omega) + let : NoZeroDivisors A := + (hC.isMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain).mp + (hC.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hCdiv) + let : IsDomain A := NoZeroDivisors.to_isDomain A + let : Field A := (IsField.of_isDomain_of_finite K A).toField + let : CommRing B := + { (inferInstance : NonAssocRing B) with + mul_assoc := D.mul_assoc_of_finrank_eq_two hB + mul_comm := D.mul_comm_of_finrank_eq_two hB } + let : Algebra K B := Algebra.ofModule (fun r x y ↦ by exact smul_mul_assoc r x y) + (fun r x y ↦ by exact mul_smul_comm r x y) + let : Nontrivial B := Module.nontrivial_of_finrank_pos (by rw [hB]; omega) + let : NoZeroDivisors B := + (hD.isMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain).mp + (hD.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hDdiv) + let : IsDomain B := NoZeroDivisors.to_isDomain B + let : Field B := (IsField.of_isDomain_of_finite K B).toField + let ⟨p, hp⟩ := CharP.exists K + let : Fact p.Prime := ⟨CharP.char_is_prime K p⟩ + let : CharP K p := hp + let e : A ≃ₐ[K] B := + (FiniteField.algEquivExtension K p 2 A hA).trans + (FiniteField.algEquivExtension K p 2 B hB).symm + exact ⟨isometryEquivOfAlgEquiv C D e, e.map_one, e.map_mul⟩ + +/-- **Existence of the non-split composition algebra in dimension two.** A quadratic field +extension of a finite field, with the conic structure of `GPR 19.8`, is a composition division +algebra, and in particular is not split. + +The discriminant of such an extension is a unit in every characteristic +(`ConicAlgebra.IsQuadraticAlgebra.isUnit_discriminant_of_finite`), which is what makes it a +composition algebra; being a field it has no zero divisors, so its norm is anisotropic. Together +with `isomorphic_of_finite_of_hasTwoSidedInverses_two` this completes `GPR 23.14` in dimension two: +the division algebra exists and is unique. -/ +theorem exists_isComposition_hasTwoSidedInverses_not_isSplitOfRank_two {L : Type w} [Field L] + [Algebra K L] (hL : Module.finrank K L = 2) : + ∃ (_ : Module.Finite K L) (_ : Module.Projective K L) (E : ConicAlgebra K L), + E.IsComposition.{u, w, u} ∧ E.HasTwoSidedInverses ∧ ¬ E.IsSplitOfRank 2 := by + obtain ⟨u, t, n₀, hq⟩ := exists_isQuadraticAlgebra_of_finrank_eq_two hL + have := hq.module_free + have := hq.module_finite + have : Module.Projective K L := inferInstance + have hcomp := hq.isComposition_conic hq.isUnit_discriminant_of_finite + have hani : hq.conic.norm.Anisotropic := + hcomp.isMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain.mpr inferInstance + refine ⟨inferInstance, inferInstance, hq.conic, hcomp, + hcomp.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mpr hani, ?_⟩ + rw [hcomp.isSplitOfRank_iff_not_anisotropic hL (Or.inl rfl)] + exact not_not.mpr hani + +omit [Finite K] in +/-- **Dimension two is where the dichotomy of `GPR 22.18` survives over a finite field.** A +two-dimensional composition algebra over a finite field is split or a division algebra; both occur, +the second being the quadratic field extension of the base. -/ +theorem IsComposition.isSplitOfRank_or_hasTwoSidedInverses_two (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = 2) : C.IsSplitOfRank 2 ∨ C.HasTwoSidedInverses := + h.isSplitOfRank_or_hasTwoSidedInverses hA (Or.inl rfl) + +/-! ### The same, with division in the sense of `GPR 8.6` -/ + +/-- **The dimension-two division composition algebra over a finite field is unique**, with +division in the sense of `GPR 8.6`. -/ +theorem IsComposition.isomorphic_of_finite_of_isDivision_two + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (hA : Module.finrank K A = 2) (hB : Module.finrank K B = 2) + (hCdiv : IsDivision A) (hDdiv : IsDivision B) : C.Isomorphic D := + hC.isomorphic_of_finite_of_hasTwoSidedInverses_two hD hA hB + (C.hasTwoSidedInverses_of_isDivision hCdiv) (D.hasTwoSidedInverses_of_isDivision hDdiv) + +/-- **A dimension-two division composition algebra exists over a finite field**, with division in +the sense of `GPR 8.6`: the quadratic field extension. -/ +theorem exists_isComposition_isDivision_not_isSplitOfRank_two {L : Type w} [Field L] + [Algebra K L] (hL : Module.finrank K L = 2) : + ∃ (_ : Module.Finite K L) (_ : Module.Projective K L) (E : ConicAlgebra K L), + E.IsComposition.{u, w, u} ∧ IsDivision L ∧ ¬ E.IsSplitOfRank 2 := by + obtain ⟨_, _, E, hE, hinv, hns⟩ := + exists_isComposition_hasTwoSidedInverses_not_isSplitOfRank_two (K := K) hL + exact ⟨‹_›, ‹_›, E, hE, hE.isDivision_iff_hasTwoSidedInverses.mpr hinv, hns⟩ + +omit [Finite K] in +/-- **`GPR 23.14` in dimension two, with `GPR 8.6`'s division**: a two-dimensional composition +algebra over a finite field is split or a division algebra. -/ +theorem IsComposition.isSplitOfRank_or_isDivision_two (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = 2) : C.IsSplitOfRank 2 ∨ IsDivision A := + h.isSplitOfRank_or_isDivision hA (Or.inl rfl) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/FractionField.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/FractionField.lean new file mode 100644 index 0000000000..a47f0ee0ac --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/FractionField.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower + +/-! +# Splitting over the fraction field (`GPR 22.19(i)`) + +Let `k` be a principal ideal domain with field of fractions `F`, and `C` a composition algebra of +rank `r > 1` over `k`. `GPR 22.19` lists five equivalent conditions: + +(i) `C_F` is split; (ii) the norm of `C` is isotropic in the sense of `GPR 11.17`; (iii) the norm +of `C` represents zero in the sense of `GPR Exc. 12.38`; (iv) `C` has zero divisors; (v) `C` is +split. + +Conditions (ii)–(v) are proved equivalent in `Composition/Reduced/Classification.lean`. This file +adds condition (i), following the proof of `GPR 22.19`: (i) is linked to (iii) by anisotropy. + +**Anisotropy descends from the fraction field** (`GPR Exc. 12.38(b)`, for quadratic forms). A +quadratic form on a finitely generated projective `k`-module represents zero if and only if its +extension to a localization at non-zero-divisors does. A nonzero null vector `m` stays nonzero as +`1 ⊗ m`, because projective modules have no torsion; conversely, clearing denominators turns a +nonzero null vector of the extension into `1 ⊗ m` for a nonzero null vector `m`. This is +`QuadraticForm.anisotropic_baseChangeOfProjective_iff_of_isLocalization`, which uses no algebra +structure and lives in `QuadraticForm/BaseChangeProjective.lean`. + +Over the field `F`, splitness of `C_F` is failure of anisotropy of its norm (`GPR 22.18`), so (i) +is equivalent to (iii); the remaining conditions follow from the results over a PID. + +## Main results + +* `ConicAlgebra.IsComposition.isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic` : + **`GPR 22.19`, (i) ↔ (iii)**, over any ring with a fraction field. +* `ConicAlgebra.IsComposition.isSplitOfRank_baseChangeOfProjective_iff_not_noZeroDivisors` : + **`GPR 22.19`, (i) ↔ (iv)**, over an integral domain. +* `ConicAlgebra.IsComposition.isSplitOfRank_baseChangeOfProjective_iff_isGPRIsotropic_of_pid` : + **`GPR 22.19`, (i) ↔ (ii)**, over a PID. +* `ConicAlgebra.IsComposition.isSplitOfRank_baseChangeOfProjective_iff_of_pid` : + **`GPR 22.19`, (i) ↔ (v)**, over a PID. + +## Implementation notes + +The fraction field is any field `F` with `[IsFractionRing k F]`, not only `FractionRing k`. It lives +in the universe of `k`, because the field form of `GPR 22.18` and the results over a PID are stated +for `C.IsComposition.{u, v, u}`: the non-singularity of the norm quantifies over fields in the +universe of the base. + +⚠ **Only the PID results use the PID.** The equivalences (i) ↔ (iii) and (i) ↔ (iv) hold over any +integral domain, and are stated that way. The step from (iii) to (ii) is `GPR Exc. 12.38(c)`, and +the step from (ii) to (v) uses that projective modules over a PID are free; neither generalizes to +arbitrary domains. `GPR` remarks after `22.19` that (i) ↔ (v) holds over some other classes of +domains, and that over finitely generated algebras over a field the answer depends on the number of +generators. + +⚠ **Rank one is excluded**, as in `GPR 22.19`: the rank-one algebra `k` is split, while its norm +`x ↦ x²` is anisotropic over a domain. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.17, + Exc. 12.38, 22.18, 22.19. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct nonZeroDivisors + +namespace ConicAlgebra.IsComposition + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {r : ℕ} (F : Type u) [Field F] [Algebra k F] [IsFractionRing k F] + +/-- **`GPR 22.19`, (i) ↔ (iii).** A composition algebra of constant rank `2`, `4`, or `8` is split +after extension to the fraction field if and only if its norm represents zero. + +This is the first step of the proof of `GPR 22.19`: over the field `F` it is `GPR 22.18`, and the +norm of `C_F` represents zero exactly when the norm of `C` does (`GPR Exc. 12.38(b)`). It needs +neither the PID hypothesis of `GPR 22.19` nor any hypothesis on the base beyond the existence of a +fraction field. -/ +theorem isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic + (hcomp : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : + (C.baseChangeOfProjective F).IsSplitOfRank r ↔ ¬ C.norm.Anisotropic := by + rw [(hcomp.baseChangeOfProjective F).isSplitOfRank_iff_not_anisotropic + (Module.finrank_baseChange_of_rankAtStalk_eq hA F) hr, baseChangeOfProjective_norm, + QuadraticForm.anisotropic_baseChangeOfProjective_iff_of_isFractionRing] + +/-- **`GPR 22.19`, (i) ↔ (iv).** Over an integral domain, a composition algebra of constant rank +`2`, `4`, or `8` is split after extension to the fraction field if and only if it has zero +divisors, expressed as the negation of mathlib's `NoZeroDivisors`. -/ +theorem isSplitOfRank_baseChangeOfProjective_iff_not_noZeroDivisors [IsDomain k] + (hcomp : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : + (C.baseChangeOfProjective F).IsSplitOfRank r ↔ ¬ NoZeroDivisors A := + (hcomp.isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic F hA hr).trans + (not_congr hcomp.isMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain) + +/-- **`GPR 22.19`, (i) ↔ (ii).** Over a PID, a composition algebra of constant rank `2`, `4`, or +`8` is split after extension to the fraction field if and only if its norm is isotropic in the sense +of `GPR 11.17`, i.e. has a unimodular null vector. The step from a nonzero null vector to a +unimodular one is `GPR Exc. 12.38(c)`. -/ +theorem isSplitOfRank_baseChangeOfProjective_iff_isGPRIsotropic_of_pid [IsDomain k] + [IsPrincipalIdealRing k] (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + (C.baseChangeOfProjective F).IsSplitOfRank r ↔ C.norm.IsGPRIsotropic := + (hcomp.isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic F hA hr).trans + QuadraticMap.isGPRIsotropic_iff_not_anisotropic_of_pid.symm + +/-- **`GPR 22.19`, (i) ↔ (v).** Over a PID with fraction field `F`, a composition algebra of +constant rank `2`, `4`, or `8` is split if and only if it becomes split over `F`. + +Both directions pass through condition (iii), the norm representing zero: (i) ↔ (iii) is +`isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic`, and (iii) ↔ (v) over a PID is +`isSplitOfRank_iff_not_anisotropic_of_pid`. -/ +theorem isSplitOfRank_baseChangeOfProjective_iff_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hcomp : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : + (C.baseChangeOfProjective F).IsSplitOfRank r ↔ C.IsSplitOfRank r := + (hcomp.isSplitOfRank_baseChangeOfProjective_iff_not_anisotropic F hA hr).trans + (hcomp.isSplitOfRank_iff_not_anisotropic_of_pid hA hr).symm + +end ConicAlgebra.IsComposition diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Real.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Real.lean new file mode 100644 index 0000000000..98b4a4f957 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/Real.lean @@ -0,0 +1,221 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Examples +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Real + +/-! +# Composition algebras over the reals (`GPR 23.13`) + +Over `ℝ` there is exactly one composition **division** algebra in each of the dimensions `1`, `2`, +`4`, `8` — the classical tower `ℝ, ℂ, ℍ, 𝕆` — and, besides these, only the split algebra in each of +the dimensions `2`, `4`, `8`. `GPR 23.13` notes that the same holds over any real closed field; only +`ℝ` is treated here. + +Two inputs do all the work. + +* **Sylvester's law of inertia.** A composition algebra which is not split has anisotropic norm, and + an anisotropic real quadratic form taking a positive value is a sum of squares + (`QuadraticForm.equivalent_sumSquares_of_anisotropic`). The norm takes the value `1` at the + identity element, so it is positive definite and is determined by the dimension alone. +* **Layer 9.** Over a field, composition algebras with isometric norms are isomorphic. So the + dimension already determines the division algebra. + +Existence is the Cayley–Dickson tower at `μ₁ = μ₂ = μ₃ = -1` (`Composition/Examples.lean`), which +supplies a positive definite — hence anisotropic, hence division — composition algebra in each of +the four dimensions. + +⚠ **On "division".** Each division statement below comes in two forms: one with +`ConicAlgebra.HasTwoSidedInverses` — every nonzero element has a two-sided inverse — and one with +`IsDivision`, division in the sense of `GPR 8.6`. In general the first is weaker, but composition +algebras are alternative, so the two agree once `1 ≠ 0` (`GPR 13.8`, +`ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses`); the `IsDivision` forms are +derived from the others by that equivalence. + +## Main results + +* `ConicAlgebra.IsComposition.posDef_norm_of_isDivision`, + `ConicAlgebra.IsComposition.posDef_norm_of_hasTwoSidedInverses` : a real composition division + algebra has positive definite norm. +* `ConicAlgebra.IsComposition.isomorphic_of_anisotropic` : two real composition algebras with + anisotropic norms and the same dimension are isomorphic. +* `ConicAlgebra.IsComposition.isomorphic_of_isDivision`, + `ConicAlgebra.IsComposition.isomorphic_of_hasTwoSidedInverses` : the same for division algebras. +* `ConicAlgebra.IsComposition.isomorphic_realTower_of_isDivision`, + `ConicAlgebra.IsComposition.isomorphic_realTower_of_hasTwoSidedInverses` : **`GPR 23.13`**, every + real composition division algebra is `ℝ`, `ℂ`, `ℍ`, or `𝕆`. +* `ConicAlgebra.IsComposition.isSplitOfRank_or_isomorphic_realTower` : the complete list — a real + composition algebra of dimension `2`, `4`, or `8` is either split or one of the three division + algebras of that dimension. + +## Implementation notes + +`ℂ` and `ℍ` appear as the Cayley–Dickson doubles `Cay₂ ℝ (-1)` and `Cay₄ ℝ (-1) (-1)`, not as +mathlib's `Complex` and `Quaternion ℝ`; see `Composition/Examples.lean`. The identification of +`Cay₄ ℝ (-1) (-1)` with `ℍ[ℝ]` is in `Composition/ComplexQuaternion.lean` and is not needed here. + +⚠ Positive definiteness, not mere anisotropy, is what makes the classification finite: over a +general field the anisotropic forms of a given dimension are not unique, and this is why the other +files in this layer need a separate argument for each class of field. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6, 13.8, 22.18, + 23.13. +* Sylvester, *A demonstration of the theorem that every homogeneous quadratic polynomial is + reducible by real orthogonal substitutions to the form of a sum of positive and negative + squares*, Philosophical Magazine **4** (1852), 138–142. +-/ + +@[expose] public section + +universe v w + +namespace ConicAlgebra + +variable {A : Type v} [NonAssocRing A] [Module ℝ A] [SMulCommClass ℝ A A] + [IsScalarTower ℝ A A] + [Module.Finite ℝ A] [Module.Projective ℝ A] + {B : Type w} [NonAssocRing B] [Module ℝ B] [SMulCommClass ℝ B B] [IsScalarTower ℝ B B] + [Module.Finite ℝ B] [Module.Projective ℝ B] + {C : ConicAlgebra ℝ A} {D : ConicAlgebra ℝ B} + +/-! ### Anisotropic real norms are positive definite -/ + +omit [SMulCommClass ℝ A A] [IsScalarTower ℝ A A] [Module.Finite ℝ A] [Module.Projective ℝ A] in +/-- The norm of a real conic algebra is positive at the identity element, since `n(1) = 1`. -/ +theorem norm_one_pos (C : ConicAlgebra ℝ A) : 0 < C.norm 1 := by + rw [C.norm_one] + norm_num + +omit [SMulCommClass ℝ A A] [IsScalarTower ℝ A A] [Module.Finite ℝ A] [Module.Projective ℝ A] in +/-- **An anisotropic real composition norm is positive definite.** The value at `1` is `1 > 0`, and +an anisotropic real form with a positive value is positive definite. -/ +theorem posDef_norm_of_anisotropic (C : ConicAlgebra ℝ A) (hani : C.norm.Anisotropic) : + C.norm.PosDef := + C.norm.posDef_of_anisotropic hani C.norm_one_pos + +/-- **A real composition division algebra has positive definite norm.** -/ +theorem IsComposition.posDef_norm_of_hasTwoSidedInverses (h : C.IsComposition.{0, v, 0}) + (hdiv : C.HasTwoSidedInverses) : C.norm.PosDef := + C.posDef_norm_of_anisotropic (h.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hdiv) + +/-! ### Uniqueness in each dimension -/ + +/-- **The real division composition algebra of a given dimension is unique.** Both norms are +positive definite of the same dimension, hence isometric by Sylvester's law; Layer 9 turns the +isometry into an algebra isomorphism. -/ +theorem IsComposition.isomorphic_of_anisotropic (hC : C.IsComposition.{0, v, 0}) + (hD : D.IsComposition.{0, w, 0}) (hCani : C.norm.Anisotropic) (hDani : D.norm.Anisotropic) + (hdim : Module.finrank ℝ A = Module.finrank ℝ B) : C.Isomorphic D := by + obtain ⟨e⟩ := QuadraticForm.equivalent_of_anisotropic_of_finrank_eq hCani hDani + C.norm_one_pos D.norm_one_pos hdim + exact hC.isomorphic_of_isometryEquiv hD e + +/-- **The real division composition algebra of a given dimension is unique**, stated for division +algebras. -/ +theorem IsComposition.isomorphic_of_hasTwoSidedInverses (hC : C.IsComposition.{0, v, 0}) + (hD : D.IsComposition.{0, w, 0}) (hCdiv : C.HasTwoSidedInverses) (hDdiv : D.HasTwoSidedInverses) + (hdim : Module.finrank ℝ A = Module.finrank ℝ B) : C.Isomorphic D := + hC.isomorphic_of_anisotropic hD (hC.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hCdiv) + (hD.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hDdiv) hdim + +/-! ### The classical tower realizes every dimension -/ + +section Tower + +/-- The conic structure on `ℂ = Cay(ℝ, -1)`. -/ +noncomputable abbrev realComplex : ConicAlgebra ℝ RealComplex := cay₂ ℝ (-1) + +/-- The conic structure on `ℍ = Cay(ℂ, -1)`. -/ +noncomputable abbrev realQuaternion : ConicAlgebra ℝ RealQuaternion := cay₄ ℝ (-1) (-1) + +theorem isComposition_realComplex : realComplex.IsComposition.{0, 0, 0} := + letI : Invertible (2 : ℝ) := invertibleOfNonzero (by norm_num) + isComposition_cay₂ ℝ (-1) (IsUnit.neg isUnit_one) + +theorem isComposition_realQuaternion : realQuaternion.IsComposition.{0, 0, 0} := + letI : Invertible (2 : ℝ) := invertibleOfNonzero (by norm_num) + isComposition_cay₄ ℝ (-1) (-1) (IsUnit.neg isUnit_one) (IsUnit.neg isUnit_one) + +theorem anisotropic_norm_baseRing : (baseRing ℝ).norm.Anisotropic := + (posDef_baseRing ℝ).anisotropic + +theorem anisotropic_norm_realComplex : realComplex.norm.Anisotropic := + (posDef_cay₂ ℝ (by norm_num)).anisotropic + +theorem anisotropic_norm_realQuaternion : realQuaternion.norm.Anisotropic := + (posDef_cay₄ ℝ (by norm_num) (by norm_num)).anisotropic + +theorem anisotropic_norm_realOctonion : realOctonion.norm.Anisotropic := + posDef_realOctonion.anisotropic + +end Tower + +/-- **`GPR 23.13`.** Every composition division algebra over `ℝ` is isomorphic to one of `ℝ`, `ℂ`, +`ℍ`, `𝕆`. The dimension is `1`, `2`, `4`, or `8` by `GPR 19.18`, the norm is positive definite, +and in each dimension the tower supplies a positive definite composition algebra to compare with. -/ +theorem IsComposition.isomorphic_realTower_of_hasTwoSidedInverses (h : C.IsComposition.{0, v, 0}) + (hdiv : C.HasTwoSidedInverses) : + C.Isomorphic (baseRing ℝ) ∨ C.Isomorphic realComplex ∨ C.Isomorphic realQuaternion ∨ + C.Isomorphic realOctonion := by + have hani := h.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hdiv + rcases h.finrank_eq_one_or_two_or_four_or_eight with h1 | h2 | h4 | h8 + · exact Or.inl (h.isomorphic_of_anisotropic (isComposition_baseRing ℝ) hani + anisotropic_norm_baseRing (by rw [h1, Module.finrank_self])) + · exact Or.inr (Or.inl (h.isomorphic_of_anisotropic isComposition_realComplex hani + anisotropic_norm_realComplex (by rw [h2, finrank_realComplex]))) + · exact Or.inr (Or.inr (Or.inl (h.isomorphic_of_anisotropic isComposition_realQuaternion hani + anisotropic_norm_realQuaternion (by rw [h4, finrank_realQuaternion])))) + · exact Or.inr (Or.inr (Or.inr (h.isomorphic_of_anisotropic isComposition_realOctonion hani + anisotropic_norm_realOctonion (by rw [h8, finrank_realOctonion])))) + +/-- **The complete list over `ℝ`.** A real composition algebra of dimension `2`, `4`, or `8` is +either split or the division algebra of that dimension. Together with +`ConicAlgebra.isSplitOfRank_one` in dimension one this classifies all of them. -/ +theorem IsComposition.isSplitOfRank_or_isomorphic_realTower {r : ℕ} + (h : C.IsComposition.{0, v, 0}) (hA : Module.finrank ℝ A = r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ∨ C.Isomorphic realComplex ∨ C.Isomorphic realQuaternion ∨ + C.Isomorphic realOctonion := by + rcases h.isSplitOfRank_or_hasTwoSidedInverses hA hr with hs | hdiv + · exact Or.inl hs + have hani := h.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.mp hdiv + rcases hr with rfl | rfl | rfl + · exact Or.inr (Or.inl (h.isomorphic_of_anisotropic isComposition_realComplex hani + anisotropic_norm_realComplex (by rw [hA, finrank_realComplex]))) + · exact Or.inr (Or.inr (Or.inl (h.isomorphic_of_anisotropic isComposition_realQuaternion hani + anisotropic_norm_realQuaternion (by rw [hA, finrank_realQuaternion])))) + · exact Or.inr (Or.inr (Or.inr (h.isomorphic_of_anisotropic isComposition_realOctonion hani + anisotropic_norm_realOctonion (by rw [hA, finrank_realOctonion])))) + +/-! ### The same, with division in the sense of `GPR 8.6` -/ + +/-- **A real composition division algebra has positive definite norm**, with division in the sense +of `GPR 8.6`. -/ +theorem IsComposition.posDef_norm_of_isDivision (h : C.IsComposition.{0, v, 0}) + (hdiv : IsDivision A) : C.norm.PosDef := + h.posDef_norm_of_hasTwoSidedInverses (C.hasTwoSidedInverses_of_isDivision hdiv) + +/-- **The real division composition algebra of a given dimension is unique**, with division in the +sense of `GPR 8.6`. -/ +theorem IsComposition.isomorphic_of_isDivision (hC : C.IsComposition.{0, v, 0}) + (hD : D.IsComposition.{0, w, 0}) (hCdiv : IsDivision A) (hDdiv : IsDivision B) + (hdim : Module.finrank ℝ A = Module.finrank ℝ B) : C.Isomorphic D := + hC.isomorphic_of_hasTwoSidedInverses hD (C.hasTwoSidedInverses_of_isDivision hCdiv) + (D.hasTwoSidedInverses_of_isDivision hDdiv) hdim + +/-- **`GPR 23.13`, with division in the sense of `GPR 8.6`.** Every composition division algebra +over `ℝ` is isomorphic to one of `ℝ`, `ℂ`, `ℍ`, `𝕆`. -/ +theorem IsComposition.isomorphic_realTower_of_isDivision (h : C.IsComposition.{0, v, 0}) + (hdiv : IsDivision A) : + C.Isomorphic (baseRing ℝ) ∨ C.Isomorphic realComplex ∨ C.Isomorphic realQuaternion ∨ + C.Isomorphic realOctonion := + h.isomorphic_realTower_of_hasTwoSidedInverses (C.hasTwoSidedInverses_of_isDivision hdiv) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SepClosed.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SepClosed.lean new file mode 100644 index 0000000000..f2a506236d --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SepClosed.lean @@ -0,0 +1,229 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticEtale +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Capstone +public import Mathlib.FieldTheory.IsSepClosed + +/-! +# Fields over which every quadratic étale algebra splits (`GPR 23.12`) + +Over such a field there is exactly one composition algebra in each of the dimensions `1`, `2`, `4`, +`8` — the split one — and no division algebra beyond the base field itself. + +⚠ `GPR 23.12` also treats fields in which every element is a square (of interest in +characteristic 2, e.g. perfect fields), where every quaternion and octonion algebra is split +because every quadratic étale norm is surjective. That paragraph is not formalized here. + +Two forms of the hypothesis appear here. + +* **As a hypothesis.** `ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_adjoinElement` + (`Composition/Reduced/Capstone.lean`) already proves this over an LG ring; over a field it gives + the statement above verbatim. +* **Discharged, for a separably closed field.** The condition is *separable* closure, not + algebraic closure, and the proof shows why. For `u` in a composition algebra `C` of dimension + greater than one, + + `n(a·1 + u) = a² + t(u) a + n(u)`, + + so a root of `X² + t(u) X + n(u)` produces a null vector, nonzero as soon as `u ∉ K·1`. In + characteristic other than two the discriminant `t(u)² - 4n(u)` has a square root because `X² - c` + is separable, and the usual formula applies. In characteristic two the polynomial is separable + exactly when `t(u) ≠ 0`, and such a `u` exists because the norm is regular: were the trace + identically zero, `1` would lie in the kernel of the polar form. That is the only place + regularity is used, and it is why `GPR 19.11` — the rank dichotomy — is a prerequisite. + +## Main results + +* `ConicAlgebra.IsComposition.not_anisotropic_of_isSepClosed` : over a separably closed field, the + norm of a composition algebra of dimension greater than one is isotropic. +* `ConicAlgebra.IsComposition.isSplitOfRank_of_isSepClosed` : **`GPR 23.12`**, over a separably + closed field every composition algebra of dimension `2`, `4`, or `8` is split. +* `ConicAlgebra.IsComposition.isomorphic_of_isSepClosed` : consequently there is exactly one in + each dimension. +* `ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_quadraticEtale` : **`GPR 23.12`** + with the hypothesis stated over quadratic étale algebras, as in the source. +* `ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_quadraticSubalgebra` : the same + conclusion from the hypothesis restricted to the quadratic subalgebras of the algebra at hand. + +## Implementation notes + +⚠ Separably closed is strictly weaker than algebraically closed in characteristic `p`, and the +distinction is exactly the point of `GPR 23.12`: an inseparable extension of a separably closed +field of characteristic two is a purely inseparable quadratic algebra, which is *not* étale and +*not* the norm data of a composition algebra — see `Composition/Inseparable.lean`. The proof below +therefore never needs a square root of a general element in characteristic two. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.11, 22.18, + 23.12. +-/ + +@[expose] public section + +universe u v w + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] + {B : Type w} [NonAssocRing B] [Module K B] [SMulCommClass K B B] [IsScalarTower K B B] + [Module.Finite K B] [Module.Projective K B] + {C : ConicAlgebra K A} {D : ConicAlgebra K B} {r : ℕ} + +/-! ### The quadratic polynomial attached to an element -/ + +omit [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] in +/-- The norm along the line through `1` and `u`: `n(a·1 + u) = a² + t(u) a + n(u)`. This is the +polynomial whose roots are the null vectors of `C` in the plane `K·1 + K·u`. -/ +theorem norm_smul_one_add (C : ConicAlgebra K A) (a : K) (u : A) : + C.norm (a • (1 : A) + u) = a ^ 2 + C.trace u * a + C.norm u := by + rw [C.norm_add, QuadraticMap.map_smul, C.norm_one, QuadraticMap.polar_smul_left, + ← C.trace_apply, smul_eq_mul, smul_eq_mul, mul_one] + ring + +omit [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] in +/-- **In characteristic two a regular norm has a nonzero trace somewhere.** If the trace vanished +identically, then `1` would lie in the kernel of the polar form, which regularity forbids. -/ +theorem IsComposition.exists_trace_ne_zero_of_isGPRRegular (C : ConicAlgebra K A) + (hreg : C.norm.IsGPRRegular) [Nontrivial A] : ∃ u : A, C.trace u ≠ 0 := by + by_contra hcon + have hzero : C.norm.polarBilin (1 : A) = 0 := by + ext y + simpa only [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, ← C.trace_apply] + using not_not.mp (not_exists.mp hcon y) + exact one_ne_zero ((injective_iff_map_eq_zero _).mp hreg.1 (1 : A) hzero) + +/-! ### Separably closed fields -/ + +/-- **Over a separably closed field the norm of a composition algebra of dimension greater than one +is isotropic.** See the module docstring for the two characteristics. -/ +theorem IsComposition.not_anisotropic_of_isSepClosed [IsSepClosed K] + (h : C.IsComposition.{u, v, u}) (hA : 1 < Module.finrank K A) : ¬ C.norm.Anisotropic := by + have := nontrivial_of_conicAlgebra C + intro hani + have hreg : C.norm.IsGPRRegular := + h.isGPRRegular_of_rankAtStalk_ne_one + (Module.rankAtStalk_eq_of_finrank_eq (rfl : Module.finrank K A = Module.finrank K A)) + (by omega) + rcases eq_or_ne (2 : K) 0 with h2 | h2 + · -- Characteristic two: pick `u` with `t(u) ≠ 0`; the polynomial is then separable. + obtain ⟨u, hu⟩ := IsComposition.exists_trace_ne_zero_of_isGPRRegular C hreg + obtain ⟨a, ha⟩ := IsSepClosed.exists_root_C_mul_X_pow_add_C_mul_X_add_C + (n := 2) 1 (C.trace u) (C.norm u) (by exact_mod_cast h2) le_rfl hu + have hnull : C.norm (a • (1 : A) + u) = 0 := by + rw [C.norm_smul_one_add] + linear_combination ha + have hzero := hani _ hnull + rw [add_comm] at hzero + -- `u + a·1 = 0` makes `u = (-a)·1`, whose trace is `-2a = 0` in characteristic two. + have hu' : u = (-a) • (1 : A) := by + rw [neg_smul] + exact eq_neg_of_add_eq_zero_left hzero + exact hu (by rw [hu', map_smul, C.trace_one, smul_eq_mul, h2, mul_zero]) + · -- Characteristic other than two: complete the square. + obtain ⟨u, hu⟩ : ∃ u : A, ∀ d : K, u ≠ d • (1 : A) := by + by_contra hcon + have : ∀ x : A, ∃ d : K, x = d • (1 : A) := by + intro x + by_contra hx + exact hcon ⟨x, fun d hd ↦ hx ⟨d, hd⟩⟩ + exact absurd (finrank_le_one_of_forall_exists_smul (1 : A) this) (by omega) + have : NeZero (2 : K) := ⟨h2⟩ + obtain ⟨e, he⟩ := IsSepClosed.exists_pow_nat_eq (C.trace u ^ 2 - 4 * C.norm u) 2 + set a : K := (-(C.trace u) + e) / 2 with hadef + have hnull : C.norm (a • (1 : A) + u) = 0 := by + rw [C.norm_smul_one_add, hadef] + field_simp + linear_combination he + have hzero := hani _ hnull + rw [add_comm] at hzero + exact hu (-a) (by rw [neg_smul]; exact eq_neg_of_add_eq_zero_left hzero) + +/-- **`GPR 23.12`.** Over a separably closed field every composition algebra of dimension `2`, `4`, +or `8` is split. -/ +theorem IsComposition.isSplitOfRank_of_isSepClosed [IsSepClosed K] (h : C.IsComposition.{u, v, u}) + (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r := + (h.isSplitOfRank_iff_not_anisotropic hA hr).mpr + (h.not_anisotropic_of_isSepClosed (by rcases hr with rfl | rfl | rfl <;> omega)) + +/-- **`GPR 23.12`, uniqueness.** Over a separably closed field there is exactly one composition +algebra of each dimension `1`, `2`, `4`, `8`. -/ +theorem IsComposition.isomorphic_of_isSepClosed [IsSepClosed K] (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) (hA : Module.finrank K A = r) (hB : Module.finrank K B = r) + (hr : r = 1 ∨ r = 2 ∨ r = 4 ∨ r = 8) : C.Isomorphic D := by + rcases hr with rfl | hr + · exact (isSplitOfRank_one (Module.rankAtStalk_eq_of_finrank_eq hA)).isomorphic + (isSplitOfRank_one (Module.rankAtStalk_eq_of_finrank_eq hB)) (Or.inl rfl) + · exact (hC.isSplitOfRank_of_isSepClosed hA hr).isomorphic + (hD.isSplitOfRank_of_isSepClosed hB hr) (by tauto) + +/-! ### The hypothesis in its original form -/ + +/-- **`GPR 23.12`, subalgebra form.** Over a field over which every regular rank-two composition +subalgebra `K[u]` splits, every composition algebra of dimension `2`, `4`, or `8` is split. + +This is the field case of +`ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_adjoinElement`, whose proof runs over +an arbitrary LG ring. The hypothesis is weaker than quantifying over all quadratic étale algebras, +which is why `isSplitOfRank_of_forall_isSplit_quadraticEtale` above is proved through it. -/ +theorem IsComposition.isSplitOfRank_of_forall_isSplit_quadraticSubalgebra + (h : C.IsComposition.{u, v, u}) (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) + (hsplit : ∀ (u : A) (hu : C.RegularRankTwoCompositionStructure u), + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + letI : Module.Finite K (C.adjoinElement u) := C.finite_adjoinElement u + letI : Module.Projective K (C.adjoinElement u) := hu.projective + hu.conic.IsSplitOfRank 2) : C.IsSplitOfRank r := + h.isSplitOfRank_of_forall_isSplit_adjoinElement (isLGRing_of_field K) + (Module.rankAtStalk_eq_of_finrank_eq hA) hr hsplit + +/-- **`GPR 23.12`, with the hypothesis on quadratic étale algebras themselves.** Over a field over +which *every* quadratic étale algebra splits, every composition algebra of dimension `2`, `4`, or +`8` is split. + +This is the statement `GPR 23.12` makes. It implies the subalgebra form below, because the regular +quadratic subalgebra `K[u]` produced by `GPR 19.16(b)` *is* a quadratic étale algebra: its +generator satisfies the degree-two identity, the coefficient map is bijective by regularity +(`GPR 19.8(ii) ⇔ (iii)`), and its discriminant is the unit `GPR 19.8(iii)` provides. The conic +structure carried by that subalgebra agrees with the one the presentation builds, because the norm +of a finitely generated projective conic algebra is unique (`GPR 16.7`, `GPR 19.3`) and a conic +algebra is determined by its norm. -/ +theorem IsComposition.isSplitOfRank_of_forall_isSplit_quadraticEtale + (h : C.IsComposition.{u, v, u}) (hA : Module.finrank K A = r) (hr : r = 2 ∨ r = 4 ∨ r = 8) + (hsplit : ∀ (L : Type v) [CommRing L] [Algebra K L] (w : L) (t n₀ : K) + (hq : IsQuadraticAlgebra w t n₀), IsUnit (t ^ 2 - 4 * n₀) → hq.conic.IsSplitOfRank 2) : + C.IsSplitOfRank r := by + refine h.isSplitOfRank_of_forall_isSplit_quadraticSubalgebra hA hr ?_ + intro u hu + let := C.adjoinElementCommRing u + let := C.adjoinElementAlgebra u + let : Module.Finite K (C.adjoinElement u) := C.finite_adjoinElement u + let : Module.Projective K (C.adjoinElement u) := hu.projective + have hdisc : IsUnit (C.elementDiscriminant u) := + (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mp ⟨hu⟩ + -- The subalgebra, presented as an abstract quadratic algebra on the generator `u`. + have humem : u ∈ C.adjoinElement u := ⟨(0, 1), by simp⟩ + have hq : IsQuadraticAlgebra (⟨u, humem⟩ : C.adjoinElement u) (C.trace u) (C.norm u) := by + constructor + · exact Subtype.ext (C.mul_self_eq u) + · have hmap : spanOne K (⟨u, humem⟩ : C.adjoinElement u) = + (C.quadraticSpanEquiv hdisc).toLinearMap := + LinearMap.ext fun _ ↦ Subtype.ext rfl + rw [hmap] + exact (C.quadraticSpanEquiv hdisc).bijective + -- Its discriminant is the one `GPR 19.8(iii)` supplies. + have hdisc' : IsUnit (C.trace u ^ 2 - 4 * C.norm u) := hdisc + -- The two conic structures on the subalgebra have the same norm, hence are equal. + have hnorm : hq.conic = hu.conic := ConicAlgebra.ext (norm_eq_of_projective hq.conic hu.conic) + exact hnorm ▸ hsplit (C.adjoinElement u) _ (C.trace u) (C.norm u) hq hdisc' + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SurjectiveNorm.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SurjectiveNorm.lean new file mode 100644 index 0000000000..a08fe371dd --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Fields/SurjectiveNorm.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower + +/-! +# Surjective quaternion norms split the octonions (`GPR 23.21`) + +*If every quaternion algebra over `F` has surjective norm, then every octonion algebra over `F` is +split.* + +The mechanism is the Cayley–Dickson description of an octonion algebra. By `GPR 19.17` an +eight-dimensional composition algebra over a field is `Cay(B, μ)` for a four-dimensional +composition subalgebra `B` — a quaternion algebra — and a scalar `μ = -n(v) ∈ F ˣ`. The norm of the +double is + + `n(b₁ + b₂ v) = n_B(b₁) - μ n_B(b₂)`, + +so a solution of `n_B(b) = μ` produces the nonzero null vector `b + v`. Surjectivity of `n_B` +supplies that solution, and `GPR 22.18` turns the null vector into splitness. In the language of +Pfister forms: the octonion norm is the three-fold form `⟪μ⟫ ⊗ n_B` obtained by doubling the +two-fold form `n_B`, and a form `n_B ⊥ (-μ) n_B` is isotropic as soon as `n_B` represents `μ`. + +The hypothesis is stated for the four-dimensional subalgebras the proof actually consumes, rather +than for every quaternion algebra over `F` — the same discipline as +`Composition/Reduced/Capstone.lean`. Nothing is lost: the subalgebras produced by `GPR 19.17` are +quaternion algebras in the ordinary sense. + +## Main results + +* `ConicAlgebra.IsComposition.isSplitOfRank_eight_of_forall_surjective_norm` : **`GPR 23.21`**. + +## Not formalized here + +`GPR 23.21` is applied in the literature to fields for which surjectivity of quaternion norms is +known: totally imaginary number fields and global fields with no real places (via `GPR 23.22`, the +Albert–Jacobson refinement), and `ℂ(x, y)`. Each of these inputs is a substantial theorem of number +theory or of the theory of function fields — the number-field case rests on the Hasse–Minkowski +theorem, which is out of scope here — and none of them is available in mathlib. The +mechanism above is therefore stated with surjectivity as a hypothesis, which is the part of +`GPR 23.21` that belongs to the theory of composition algebras. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.17, 22.18, + 23.21, 23.22. +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] [Module.Finite K A] [Module.Projective K A] + {C : ConicAlgebra K A} + +/-- **`GPR 23.21`.** Let `C` be an eight-dimensional composition algebra over a field `K` and +suppose that every four-dimensional composition subalgebra of `C` with regular restricted norm has +surjective norm. Then `C` is split. + +`GPR 19.17` writes `C` as `Cay(B, -n(v))` for such a subalgebra `B`; a vector of `B` whose norm is +`-n(v)` gives, together with `v`, a nonzero null vector of the norm of `C`. -/ +theorem IsComposition.isSplitOfRank_eight_of_forall_surjective_norm + (h : C.IsComposition.{u, v, u}) (hA : Module.finrank K A = 8) + (hsurj : ∀ B : NonAssocSubalgebra K A, Module.finrank K B = 4 → + QuadraticForm.IsGPRRegular (C.restrict B).norm → + Function.Surjective (C.restrict B).norm) : + C.IsSplitOfRank 8 := by + have := nontrivial_of_conicAlgebra C + have := h.isAlternative + obtain ⟨B, v, s, hs2, hsrank, -, hBreg, hbij, -, -, hnorm⟩ := + h.exists_bijective_cayToAlgebra (isLGRing_of_field K) + (Module.rankAtStalk_eq_of_finrank_eq hA) (by omega) + have hBfin : Module.finrank K B = 4 := + Module.finrank_of_rankAtStalk_eq ((rankAtStalk_toSubmodule B) ▸ hsrank) |>.trans (by omega) + obtain ⟨x, hx⟩ := hsurj B hBfin hBreg (-C.norm v) + set p : Cay (C.restrict B) (-C.norm v) := ((x, (1 : B)) : B × B) with hp + -- The Cayley–Dickson norm of `(x, 1)` is `n_B(x) + n(v)`, which vanishes by the choice of `x`. + have hpnorm : ((C.restrict B).cay (-C.norm v)).norm p = 0 := by + rw [cay_norm_apply] + change (C.restrict B).norm x - -C.norm v * (C.restrict B).norm 1 = 0 + rw [(C.restrict B).norm_one, hx] + ring + -- `(x, 1)` is nonzero because its second coordinate is the identity of `B`. + have hp0 : p ≠ 0 := by + intro hzero + have h1 : ((1 : B) : A) = ((0 : B) : A) := + congrArg (fun z : B ↦ (z : A)) (congrArg Prod.snd hzero) + simp only [OneMemClass.coe_one, ZeroMemClass.coe_zero] at h1 + exact one_ne_zero h1 + refine h.isSplitOfRank_of_exists_ne_zero_norm_eq_zero hA (Or.inr (Or.inr rfl)) + (x := cayToAlgebra C B v p) ?_ ((hnorm p).trans hpnorm) + intro hzero + exact hp0 (hbij.1 (hzero.trans (map_zero (cayToAlgebra C B v)).symm)) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Inseparable.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Inseparable.lean new file mode 100644 index 0000000000..d1cce3a6f4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Inseparable.lean @@ -0,0 +1,273 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import Mathlib.Algebra.DualNumber +public import Mathlib.Algebra.Field.ZMod + +/-! +# Anisotropic conic algebras with vanishing polar form (`GPR 19.4`) + +In characteristic two a commutative algebra all of whose squares are scalars — a purely +inseparable extension of exponent at most one, in the field case — is a conic algebra whose norm +is the squaring map. Its polar form vanishes **identically**, so it is not a composition algebra as +soon as it has dimension greater than one, even though the norm may well be anisotropic. + +This is the example that certifies two design decisions at once. + +* **The polar form is never halved.** `ConicAlgebra.trace` is `n(1, x)`, not `n(1, x) / 2`, and the + degree-two identity is stated with it. A conic definition needing `2 ∈ kˣ` could not even state + this example, let alone prove it is a conic algebra. +* **Anisotropic is not the same as non-singular.** Over a field of characteristic other than two, a + form with identically zero polar form is `2 q(x) = q(x, x) = 0`, hence zero, hence isotropic in + dimension at least one. Only in characteristic two can a form be anisotropic and have vanishing + polar form at the same time, and that is exactly the configuration here. + +## The construction + +Let `F` have characteristic two and let `A` be a commutative `F`-algebra carrying a function +`n : A → F` with `x² = n(x) · 1` for every `x`. Then `n` is a quadratic form with zero polar form — +`(x + y)² = x² + y²` because the cross terms are `2xy = 0` — and it is a conic norm: the trace +`n(1, x)` vanishes, so the degree-two identity `x² = t(x) · x − n(x) · 1` reduces to +`x² = −n(x) · 1`, which is the hypothesis since `−1 = 1`. + +Nothing here is an existence statement about purely inseparable extensions; `n` is taken as data, +which is what the field case supplies (`n(x) = x²`, landing in `F` because `A² ⊆ F`). + +## Why it is not a composition algebra + +Not because of the multiplication — `A` is commutative and associative — but because of the norm. +The polar form is zero, so for `A` of dimension at least one the map `A → A*` it induces kills +everything and cannot be injective; the norm is therefore not regular, and `GPR 19.11` allows a +non-regular composition norm only in dimension one. + +## The witness + +`ConicAlgebra.dualNumberInseparable` exhibits the configuration over `𝔽₂` with the dual numbers +`𝔽₂[ε]`, `ε² = 0`: dimension two, zero polar form, not a composition algebra. + +⚠ The dual numbers are **not** anisotropic — `n(ε) = 0` — so they witness the vanishing polar form +and the failure of composition, but not the sharpness claim about anisotropy. An anisotropic +witness must be a genuine purely inseparable field extension, so it needs an imperfect base such as +`𝔽₂(t)` with `A = 𝔽₂(t)(√t)`. That witness is constructed in +`Composition/InseparableAnisotropic.lean` (`ConicAlgebra.anisotropic_insepSqrtConic`, +`ConicAlgebra.not_isComposition_insepSqrtConic`), by applying the general theorems below. + +## Main results + +* `ConicAlgebra.inseparableNorm`, `ConicAlgebra.inseparable` : the quadratic form and the conic + structure. +* `ConicAlgebra.polar_inseparableNorm`, `ConicAlgebra.trace_inseparable` : the polar form and the + trace vanish identically. +* `ConicAlgebra.anisotropic_inseparable_iff` : the norm is anisotropic exactly when `A` has no + nonzero square-zero element. +* `ConicAlgebra.not_isComposition_inseparable` : **`GPR 19.4`** — not a composition algebra in + dimension greater than one. +* `ConicAlgebra.dualNumberInseparable`, `ConicAlgebra.not_isComposition_dualNumberInseparable`, + `ConicAlgebra.not_anisotropic_dualNumberInseparable` : the concrete witness over `𝔽₂` and what + it does and does not show. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.4, 19.11. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section Inseparable + +variable {F : Type u} {A : Type v} [Field F] [CommRing A] [Nontrivial A] [Algebra F A] + (hchar : (2 : F) = 0) (n : A → F) (hn : ∀ x : A, x * x = n x • (1 : A)) + +/-- Scalars are determined by their action on `1`: `c • 1 = algebraMap c`, and a ring +homomorphism out of a field into a nonzero ring is injective. -/ +private theorem smul_one_inj {c d : F} (h : c • (1 : A) = d • (1 : A)) : c = d := by + simp only [Algebra.smul_def, mul_one] at h + exact (algebraMap F A).injective h + +include hn + +theorem inseparable_one : n 1 = 1 := + smul_one_inj (A := A) (by rw [← hn 1, mul_one, one_smul]) + +theorem inseparable_smul (a : F) (x : A) : n (a • x) = a * a * n x := + smul_one_inj (A := A) (by rw [← hn (a • x), smul_mul_smul_comm, hn x, smul_smul]) + +include hchar + +/-- **Additivity of the squaring map in characteristic two**: the cross terms of `(x + y)²` are +`2xy = 0`. This is what makes the polar form vanish. -/ +private theorem inseparable_add (x y : A) : n (x + y) = n x + n y := by + have hcross : x * y + y * x = 0 := by + rw [mul_comm y x, ← two_smul F (x * y), hchar, zero_smul] + refine smul_one_inj (A := A) ?_ + rw [← hn (x + y), add_smul, ← hn x, ← hn y, mul_add, add_mul, add_mul] + linear_combination (norm := module) hcross + +/-- The squaring map as a quadratic form. Its companion bilinear form is **zero**: in +characteristic two the cross terms of `(x + y)²` are `2xy`. -/ +def inseparableNorm : QuadraticForm F A where + toFun := n + toFun_smul := inseparable_smul n hn + exists_companion' := ⟨0, fun x y ↦ by simp [inseparable_add hchar n hn x y]⟩ + +@[simp] theorem inseparableNorm_apply (x : A) : inseparableNorm hchar n hn x = n x := rfl + +/-- **The polar form vanishes identically.** This is the whole point of the example. -/ +@[simp] theorem polar_inseparableNorm (x y : A) : + QuadraticMap.polar (inseparableNorm hchar n hn) x y = 0 := by + rw [QuadraticMap.polar, inseparableNorm_apply, inseparableNorm_apply, inseparableNorm_apply, + inseparable_add hchar n hn] + ring + +/-- **`GPR 19.4`: the squaring map is a conic norm.** No hypothesis beyond commutativity, +characteristic two, and `x² ∈ F · 1`. -/ +def inseparable : ConicAlgebra F A where + norm := inseparableNorm hchar n hn + norm_one := inseparable_one n hn + mul_self x := by + rw [polar_inseparableNorm, zero_smul, zero_sub, hn x, inseparableNorm_apply, ← neg_smul] + congr 1 + rw [eq_neg_iff_add_eq_zero, ← two_mul, hchar, zero_mul] + +@[simp] theorem inseparable_norm_apply (x : A) : (inseparable hchar n hn).norm x = n x := rfl + +/-- The trace of the example vanishes identically, being a value of the polar form. -/ +@[simp] theorem trace_inseparable (x : A) : (inseparable hchar n hn).trace x = 0 := by + rw [trace_apply] + exact polar_inseparableNorm hchar n hn 1 x + +/-- The conjugation is the **identity**, not merely an involution: `conj x = t(x) · 1 − x = −x = x`. +-/ +@[simp] theorem conj_inseparable (x : A) : (inseparable hchar n hn).conj x = x := by + rw [conj_apply, trace_inseparable, zero_smul, zero_sub, neg_eq_iff_add_eq_zero, ← two_smul F x, + hchar, zero_smul] + +/-- **Anisotropy is exactly the absence of square-zero elements.** For `A` a field extension the +right-hand side is automatic, which is the case `GPR 19.4` is about. -/ +theorem anisotropic_inseparable_iff : + (inseparable hchar n hn).norm.Anisotropic ↔ ∀ x : A, x * x = 0 → x = 0 := by + constructor + · intro hani x hx + refine hani x ?_ + rw [inseparable_norm_apply] + refine smul_one_inj (A := A) ?_ + rw [← hn x, hx, zero_smul] + · intro h x hx + refine h x ?_ + rw [hn x, inseparable_norm_apply] at * + rw [hx, zero_smul] + +/-- **`GPR 19.4`.** In dimension greater than one this is a conic algebra that is **not** a +composition algebra: its polar form vanishes, so its norm is not regular, and `GPR 19.11` permits +a non-regular composition norm only in dimension one. -/ +theorem not_isComposition_inseparable [Module.Finite F A] [Module.Projective F A] + (hdim : 1 < Module.finrank F A) : ¬ (inseparable hchar n hn).IsComposition.{u, v, u} := by + intro h + have hnotreg : ¬ (inseparable hchar n hn).norm.IsGPRRegular := by + intro hreg + have hone : QuadraticMap.polarBilin (inseparable hchar n hn).norm 1 = 0 := by + ext y + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] + exact polar_inseparableNorm hchar n hn 1 y + exact one_ne_zero ((injective_iff_map_eq_zero _).mp hreg.1 1 hone) + rcases h.isGPRRegular_or_finrank_eq_one with hreg | ⟨hd, -⟩ + · exact hnotreg hreg + · omega + +end Inseparable + +/-! ### A witness over `𝔽₂` + +The dual numbers `𝔽₂[ε]`, `ε² = 0`, satisfy the hypotheses in dimension two: `(a + bε)² = a²` +because the cross term is `2ab = 0`. They show the configuration is not empty. + +⚠ They are **not** anisotropic (`ConicAlgebra.not_anisotropic_dualNumberInseparable`), so they +witness the vanishing polar form and the failure of composition but not the sharpness claim about +anisotropy; that needs a genuine purely inseparable field extension, hence an imperfect base, and +is supplied by `Composition/InseparableAnisotropic.lean`. -/ + +section DualNumber + +/-- The dual numbers over `𝔽₂` are nonzero. -/ +instance : Nontrivial (DualNumber (ZMod 2)) := + ⟨⟨0, 1, fun h ↦ zero_ne_one (congrArg TrivSqZeroExt.fst h)⟩⟩ + +/-- `𝔽₂[ε] ≃ 𝔽₂ ⊕ 𝔽₂` as a module. This is what computes the dimension. -/ +noncomputable def dualNumberProdEquiv : + DualNumber (ZMod 2) ≃ₗ[ZMod 2] (ZMod 2 × ZMod 2) where + toFun x := (x.fst, x.snd) + invFun p := TrivSqZeroExt.inl p.1 + TrivSqZeroExt.inr p.2 + map_add' _ _ := rfl + map_smul' _ _ := rfl + left_inv x := by ext <;> simp + right_inv p := by ext <;> simp + +noncomputable instance : Module.Finite (ZMod 2) (DualNumber (ZMod 2)) := + Module.Finite.equiv dualNumberProdEquiv.symm + +/-- The dual numbers have dimension two. -/ +theorem finrank_dualNumber : Module.finrank (ZMod 2) (DualNumber (ZMod 2)) = 2 := by + rw [dualNumberProdEquiv.finrank_eq, Module.finrank_prod, Module.finrank_self] + +/-- **Every square in `𝔽₂[ε]` is a scalar**: `(a + bε)² = a²`, the cross term `2ab` vanishing. -/ +theorem sq_dualNumber (x : DualNumber (ZMod 2)) : + x * x = algebraMap (ZMod 2) (DualNumber (ZMod 2)) (TrivSqZeroExt.fst x ^ 2) := by + ext + · simp [TrivSqZeroExt.algebraMap_eq_inl, TrivSqZeroExt.fst_mul, sq] + · simp [TrivSqZeroExt.algebraMap_eq_inl, TrivSqZeroExt.snd_mul] + ring_nf + rw [show (2 : ZMod 2) = 0 from rfl, mul_zero] + +/-- `𝔽₂` has characteristic two. -/ +theorem dualNumber_char : (2 : ZMod 2) = 0 := by decide + +/-- `ConicAlgebra.sq_dualNumber` in the `c • 1` form the construction consumes. -/ +theorem dualNumber_sq (x : DualNumber (ZMod 2)) : + x * x = (TrivSqZeroExt.fst x ^ 2) • (1 : DualNumber (ZMod 2)) := by + rw [sq_dualNumber x, Algebra.algebraMap_eq_smul_one] + +/-- **The witness for `GPR 19.4`**: the dual numbers over `𝔽₂`, a two-dimensional conic algebra +whose norm is the squaring map `a + bε ↦ a²` and whose polar form vanishes identically. -/ +noncomputable def dualNumberInseparable : ConicAlgebra (ZMod 2) (DualNumber (ZMod 2)) := + inseparable dualNumber_char (fun x : DualNumber (ZMod 2) ↦ TrivSqZeroExt.fst x ^ 2) + dualNumber_sq + +/-- The polar form of the witness vanishes identically — the configuration `GPR 19.4` is about, +in a concrete two-dimensional case. -/ +theorem polar_dualNumberInseparable (x y : DualNumber (ZMod 2)) : + QuadraticMap.polar dualNumberInseparable.norm x y = 0 := + polar_inseparableNorm dualNumber_char _ dualNumber_sq x y + +/-- **`GPR 19.4` in the concrete case.** The dual numbers over `𝔽₂` are a conic algebra that is +not a composition algebra. -/ +theorem not_isComposition_dualNumberInseparable : + ¬ dualNumberInseparable.IsComposition.{0, 0, 0} := + not_isComposition_inseparable dualNumber_char _ dualNumber_sq + (by rw [finrank_dualNumber]; norm_num) + +/-- ⚠ The witness is **not** anisotropic: `ε² = 0` with `ε ≠ 0`. Anisotropy in the presence of a +vanishing polar form — the sharp form of `GPR 19.4` — needs a purely inseparable field extension, +which requires an imperfect base field. That witness is `𝔽₂(t)(√t)`, in +`Composition/InseparableAnisotropic.lean` (`ConicAlgebra.anisotropic_insepSqrtConic`). -/ +theorem not_anisotropic_dualNumberInseparable : + ¬ dualNumberInseparable.norm.Anisotropic := by + intro hani + have h := (anisotropic_inseparable_iff dualNumber_char _ dualNumber_sq).mp hani + have hzero : (TrivSqZeroExt.inr 1 : DualNumber (ZMod 2)) * + (TrivSqZeroExt.inr 1 : DualNumber (ZMod 2)) = 0 := by + ext <;> simp + have := h _ hzero + exact one_ne_zero (congrArg TrivSqZeroExt.snd this) + +end DualNumber + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/InseparableAnisotropic.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/InseparableAnisotropic.lean new file mode 100644 index 0000000000..64c886acdb --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/InseparableAnisotropic.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Inseparable +public import Mathlib.FieldTheory.KummerPolynomial +public import Mathlib.FieldTheory.RatFunc.Degree + +/-! +# An anisotropic witness for `GPR 19.4` + +`Composition/Inseparable.lean` proves `GPR 19.4` in general — a commutative algebra over a field of +characteristic two all of whose squares are scalars is a conic algebra with identically vanishing +polar form, and is not a composition algebra once its dimension exceeds one — and exhibits the dual +numbers `𝔽₂[ε]` as a witness. The dual numbers are **not** anisotropic (`ε² = 0`), so they do not +witness the sharpness claim the example exists to make: that anisotropy and non-singularity part +company in characteristic two. + +This file supplies an anisotropic witness. It must be a purely inseparable field extension of +exponent one, so the base field must be imperfect; the smallest is `𝔽₂(t)`, and the extension is +`𝔽₂(t)(√t)`. + +## The construction + +`X² - t` is irreducible over `𝔽₂(t)` because `t` is not a square there — the `intDegree` of a +square is even, and `intDegree t = 1`. So `AdjoinRoot (X² - C t)` is a field, of dimension two over +`𝔽₂(t)`. + +Every square in it is a scalar. This is not a coordinate computation: the set of elements whose +square is a scalar is closed under addition (in characteristic two the cross terms of `(x + y)²` +are `2xy = 0`), under multiplication (by commutativity), contains the image of the base field, and +contains the root; since the root generates, it is everything (`Algebra.adjoin_induction`). + +Anisotropy is then free, and this is the point of using a field rather than a ring: by +`ConicAlgebra.anisotropic_inseparable_iff` the norm is anisotropic exactly when the algebra has no +nonzero square-zero element, which in a field is `mul_self_eq_zero`. + +## Main results + +* `RatFunc.sq_ne_X` : `t` is not a square in `K(t)`, for any field `K`. +* `ConicAlgebra.insepSqrt` : the field `𝔽₂(t)(√t)`. +* `ConicAlgebra.insepSqrtConic` : its conic structure, with the squaring map as norm. +* `ConicAlgebra.anisotropic_insepSqrtConic` : **its norm is anisotropic**. +* `ConicAlgebra.polar_insepSqrtConic` : its polar form vanishes identically. +* `ConicAlgebra.not_isComposition_insepSqrtConic` : it is not a composition algebra. + +Together these separate anisotropy from non-singularity, which is what `GPR 19.4` is for. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.4, 19.11. +-/ + +@[expose] public section + +open Polynomial + +namespace RatFunc + +/-- **`t` is not a square in `K(t)`.** The `intDegree` of a nonzero square is even, while +`intDegree t = 1`. This is what makes `K(t)` imperfect in characteristic two. -/ +theorem sq_ne_X {K : Type*} [Field K] (b : RatFunc K) : b * b ≠ RatFunc.X := by + intro h + have hb : b ≠ 0 := by + rintro rfl + exact RatFunc.X_ne_zero (by simpa using h.symm) + have hdeg : b.intDegree + b.intDegree = 1 := by + rw [← RatFunc.intDegree_mul hb hb, h, RatFunc.intDegree_X] + omega + +end RatFunc + +namespace ConicAlgebra + +/-- The imperfect base field `𝔽₂(t)`. -/ +abbrev InsepBase : Type := RatFunc (ZMod 2) + +/-- The polynomial `X² - t` over `𝔽₂(t)`. -/ +noncomputable abbrev insepPoly : InsepBase[X] := X ^ 2 - C RatFunc.X + +theorem irreducible_insepPoly : Irreducible insepPoly := + X_pow_sub_C_irreducible_of_prime Nat.prime_two fun b ↦ by + rw [pow_two]; exact RatFunc.sq_ne_X b + +noncomputable instance : Fact (Irreducible insepPoly) := ⟨irreducible_insepPoly⟩ + +/-- The purely inseparable quadratic extension `𝔽₂(t)(√t)`. -/ +abbrev insepSqrt : Type := AdjoinRoot insepPoly + +theorem insepPoly_ne_zero : insepPoly ≠ 0 := irreducible_insepPoly.ne_zero + +/-- `𝔽₂(t)(√t)` has dimension two over `𝔽₂(t)`. -/ +theorem finrank_insepSqrt : Module.finrank InsepBase insepSqrt = 2 := by + rw [(AdjoinRoot.powerBasis insepPoly_ne_zero).finrank, + AdjoinRoot.powerBasis_dim insepPoly_ne_zero] + exact natDegree_X_pow_sub_C + +noncomputable instance : Module.Finite InsepBase insepSqrt := + (AdjoinRoot.powerBasis insepPoly_ne_zero).finite + +/-- `𝔽₂(t)` has characteristic two. -/ +theorem insepBase_two_eq_zero : (2 : InsepBase) = 0 := by + have h : ((2 : ℕ) : InsepBase) = 0 := CharP.cast_eq_zero InsepBase 2 + simpa using h + +/-- **Every square in `𝔽₂(t)(√t)` is a scalar.** + +The set of such elements is a subalgebra — closed under addition because in characteristic two the +cross terms of `(x + y)²` are `2xy`, and under multiplication by commutativity — and it contains +the root, whose square is `t`. Since the root generates, it is everything. -/ +theorem exists_mul_self_eq_algebraMap (x : insepSqrt) : + ∃ c : InsepBase, x * x = algebraMap InsepBase insepSqrt c := by + have hx : x ∈ Algebra.adjoin InsepBase ({AdjoinRoot.root insepPoly} : Set insepSqrt) := by + rw [AdjoinRoot.adjoinRoot_eq_top]; trivial + induction hx using Algebra.adjoin_induction with + | mem y hy => + rw [Set.mem_singleton_iff] at hy + subst hy + refine ⟨RatFunc.X, ?_⟩ + rw [← pow_two, AdjoinRoot.algebraMap_eq] + exact root_X_pow_sub_C_pow 2 RatFunc.X + | algebraMap r => exact ⟨r * r, by rw [map_mul]⟩ + | add y z _ _ ihy ihz => + obtain ⟨c, hc⟩ := ihy + obtain ⟨d, hd⟩ := ihz + refine ⟨c + d, ?_⟩ + have hcross : y * z + z * y = 0 := by + rw [mul_comm z y, ← two_mul, ← map_ofNat (algebraMap InsepBase insepSqrt) 2, + insepBase_two_eq_zero] + simp + rw [map_add, ← hc, ← hd, mul_add, add_mul, add_mul] + linear_combination hcross + | mul y z _ _ ihy ihz => + obtain ⟨c, hc⟩ := ihy + obtain ⟨d, hd⟩ := ihz + exact ⟨c * d, by rw [map_mul, ← hc, ← hd]; ring⟩ + +/-- The norm: the squaring map, read as a function to the base field. -/ +noncomputable def insepSqrtNorm (x : insepSqrt) : InsepBase := + (exists_mul_self_eq_algebraMap x).choose + +theorem insepSqrtNorm_spec (x : insepSqrt) : x * x = insepSqrtNorm x • (1 : insepSqrt) := by + rw [Algebra.smul_def, mul_one] + exact (exists_mul_self_eq_algebraMap x).choose_spec + +/-- **`GPR 19.4` with an anisotropic witness**: the conic structure on `𝔽₂(t)(√t)` whose norm is +the squaring map. -/ +noncomputable def insepSqrtConic : ConicAlgebra InsepBase insepSqrt := + inseparable insepBase_two_eq_zero insepSqrtNorm insepSqrtNorm_spec + +/-- The polar form vanishes identically. -/ +@[simp] theorem polar_insepSqrtConic (x y : insepSqrt) : + QuadraticMap.polar insepSqrtConic.norm x y = 0 := + polar_inseparableNorm insepBase_two_eq_zero insepSqrtNorm insepSqrtNorm_spec x y + +/-- The trace vanishes identically and the conjugation is the identity. -/ +@[simp] theorem trace_insepSqrtConic (x : insepSqrt) : insepSqrtConic.trace x = 0 := + trace_inseparable insepBase_two_eq_zero insepSqrtNorm insepSqrtNorm_spec x + +@[simp] theorem conj_insepSqrtConic (x : insepSqrt) : insepSqrtConic.conj x = x := + conj_inseparable insepBase_two_eq_zero insepSqrtNorm insepSqrtNorm_spec x + +/-- **The norm is anisotropic.** This is what the dual numbers could not witness: in a field the +only square-zero element is zero, so `ConicAlgebra.anisotropic_inseparable_iff` applies. -/ +theorem anisotropic_insepSqrtConic : insepSqrtConic.norm.Anisotropic := by + rw [insepSqrtConic, anisotropic_inseparable_iff] + exact fun x hx ↦ mul_self_eq_zero.mp hx + +/-- **`GPR 19.4`.** An anisotropic conic algebra whose polar form vanishes identically, hence +which is not a composition algebra. Anisotropy and non-singularity therefore genuinely part +company in characteristic two. -/ +theorem not_isComposition_insepSqrtConic : ¬ insepSqrtConic.IsComposition.{0, 0, 0} := + not_isComposition_inseparable insepBase_two_eq_zero insepSqrtNorm insepSqrtNorm_spec + (by rw [finrank_insepSqrt]; norm_num) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/NormClassification.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/NormClassification.lean new file mode 100644 index 0000000000..e828d5b150 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/NormClassification.lean @@ -0,0 +1,1125 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankOneTwoFourEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.OrthogonalComplement +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.WittCancellation + +/-! +# Algebra isomorphisms and norm isometries + +The first direction of the classification of composition algebras by their norm forms says that +an algebra isomorphism is an isometry. The key input is that a conic norm on a finitely generated +projective algebra is intrinsic: two conic structures on the same algebra have the same norm. +This is the easy half of `GPR 23.4(a)`. + +For the converse direction, the first step normalizes an arbitrary norm **similarity** to a unital +norm isometry (`GPR 23.3`). If its multiplier is `μ` and the image of `1` is `x`, left +multiplication by `conj x / μ` has the inverse multiplier and sends `x` to `1`. Such a normalized +map preserves the whole conic calculus — trace, conjugation and squares — which is `GPR 23.2`. + +Over a nontrivial LG ring, the converse is completed without a constant-rank hypothesis; that +completion is the **norm equivalence theorem** `GPR 23.5`. The rank idempotents reduce it to the +constant-rank cases. In rank one, +`unitForm` canonically identifies the algebra with the base ring, even when its polar form is +nonregular in characteristic two. In ranks two, four, and eight, the proof starts from the +corresponding regular quadratic subalgebras of `GPR 19.16(b)`, uses Witt cancellation (`GN 6.5`) +to match successive doubling vectors, and iterates to regular full-rank subalgebras, which are the +ambient algebras. + +## Main results + +* `ConicAlgebra.norm_eq_of_projective` : two conic norms on the same finite projective algebra + coincide. +* `ConicAlgebra.isometryEquivOfLinearEquiv` : **`GPR 23.4(a)`**, a unital multiplicative linear + equivalence of conic algebras is an isometry of their norms. +* `ConicAlgebra.trace_map_of_linearEquiv`, `ConicAlgebra.conj_map_of_linearEquiv` : such an + equivalence also preserves trace and conjugation. +* `ConicAlgebra.IsMultiplicative.exists_isometryEquiv_map_one_of_similarity` : full + **`GPR 23.3`**, normalizing a norm similarity to a unital norm isometry. +* `ConicAlgebra.IsMultiplicative.exists_isometryEquiv_map_one` : its isometry special case. +* `ConicAlgebra.trace_map_of_isometryEquiv_map_one`, `.conj_map_of_isometryEquiv_map_one`, + `.map_mul_self_of_isometryEquiv_map_one` : **`GPR 23.2`**, a unital norm isometry preserves the + conic calculus and squaring. +* `ConicAlgebra.adjoinElementLinearEquivOfMapOne` : a unital norm isometry restricts to an algebra + isomorphism `k[u] ≅ k[e u]` (expressed as a multiplicative unital linear equivalence). +* `ConicAlgebra.isRegularRankTwoComposition_map_of_isometryEquiv_map_one` : the regular quadratic + starting subalgebra transfers across a unital norm isometry. +* `ConicAlgebra.cayAdjoinElementIsometryEquivOfMapOne` : the matched quadratic subalgebras can be + doubled with a common Cayley–Dickson scalar, preserving the norm and multiplication. +* `ConicAlgebra.exists_doubledSubalgebras_isometryEquiv_of_isGPRRegular` : one internal matched + doubling step carries equivalent regular subalgebras to equivalent doubled image subalgebras. +* `ConicAlgebra.IsComposition.exists_next_doubledSubalgebras_isometryEquiv` : unit representation, + complement cancellation and internal doubling combined into one complete induction step. +* `ConicAlgebra.IsComposition.exists_next_isGPRRegular_rankAtStalk_two_mul` : the self-feeding + version of that step, recording regularity and doubled rank for both new image subalgebras. +* `ConicAlgebra.exists_isometryEquiv_polarOrthogonal` : cancellation for arbitrary corresponding + regular subalgebras. +* `ConicAlgebra.IsComposition.exists_isometryEquiv_map_one_map_mul` : **`GPR 23.5`**, the norm + equivalence theorem over a nontrivial LG ring, with no constant-rank hypothesis. +* `ConicAlgebra.exists_isometryEquiv_polarOrthogonal_adjoinElement` : Witt cancellation identifies + the orthogonal complements of the corresponding quadratic subalgebras. +* `ConicAlgebra.exists_polarOrthogonal_adjoinElement_eq_norm` : corresponding complement vectors + give the same Cayley–Dickson parameter. +* `ConicAlgebra.isometryEquivOf_fullRank_subalgebras` : a matched equivalence of regular full-rank + subalgebras assembles to an ambient equivalence. +* `ConicAlgebra.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq_one` : the exceptional + rank-one converse, proved directly through `unitForm`. +* `ConicAlgebra.IsComposition.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk` : the + constant-rank-at-least-two step. +* `ConicAlgebra.IsComposition.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq` : the + constant-rank theorem used on each idempotent factor. + +## Implementation notes + +Mathlib's `AlgEquiv` applies only to associative semirings, while composition algebras need not be +associative. Accordingly the second theorem accepts a `LinearEquiv` together with the two laws +that make it an isomorphism of unital non-associative algebras. This avoids introducing a local +competitor to the `NonUnitalAlgEquiv` that mathlib itself records as a future TODO. + +The uniqueness argument is elementary. Subtracting the two degree-two identities gives + +`(t_C(x) - t_D(x)) x = (n_C(x) - n_D(x)) 1`. + +Applying a functional taking `1` to `1` shows that the trace difference annihilates its own +traceless argument. The projective self-annihilation lemma then makes the traces equal, and the +same displayed identity makes the norms equal. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.7, 19.3, + 19.16(b), 19.18, 23.2, 23.3, 23.4(a), 23.5. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, 6.5. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + +section Equiv + +variable {B : Type w} [NonAssocRing B] [Module k B] [SMulCommClass k B B] + [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] + +/-- **The engine of `GPR 23.4(a)`.** A unital linear equivalence between finitely generated +projective conic algebras that preserves squares, `e (x * x) = e x * e x`, is an isometry of their +norm forms: pulling the norm of `B` back along `e` gives a second conic norm on `A`, and the conic +norm of a finitely generated projective algebra is unique (`ConicAlgebra.norm_eq_of_projective`, +`GPR 16.16`). Isomorphisms (`isometryEquivOfLinearEquiv`) and anti-isomorphisms +(`isometryEquivOfLinearEquivOfMapMulRev`) both preserve squares. -/ +noncomputable def isometryEquivOfLinearEquivOfMapMulSelf (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) + (map_mul_self : ∀ x, e (x * x) = e x * e x) : C.norm.IsometryEquiv D.norm := by + let E : ConicAlgebra k A := + { norm := D.norm.comp e.toLinearMap + norm_one := by simp [QuadraticMap.comp_apply, map_one, D.norm_one] + mul_self := fun x ↦ e.injective (by + simp only [map_mul_self, D.mul_self_eq, map_smul, map_sub, map_one, + QuadraticMap.comp_apply] + rw [QuadraticMap.polar] + simp only [map_add, QuadraticMap.comp_apply] + change D.trace (e x) • e x - D.norm (e x) • 1 = + (D.norm (e 1 + e x) - D.norm (e 1) - D.norm (e x)) • e x - + D.norm (e x) • 1 + rw [map_one] + rfl) } + exact + { toLinearEquiv := e + map_app' := fun x ↦ by + change E.norm x = C.norm x + rw [norm_eq_of_projective C E] } + +/-- **`GPR 23.4(a)`, isomorphisms.** A unital multiplicative linear equivalence between conic +algebras is an isometry of their norm forms. In particular, every isomorphism of composition +algebras preserves the norm; the converse, in rank two, is `Composition/NormEquivalence.lean`. + +⚠ Mathlib's `AlgEquiv` requires associative multiplication, so the non-associative algebra +isomorphism is deliberately expressed as a `LinearEquiv` plus `map_one` and `map_mul`. -/ +noncomputable def isometryEquivOfLinearEquiv (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) (map_mul : ∀ x y, e (x * y) = e x * e y) : + C.norm.IsometryEquiv D.norm := + isometryEquivOfLinearEquivOfMapMulSelf C D e map_one fun x ↦ map_mul x x + +/-- **`GPR 23.4(a)`, anti-isomorphisms.** A unital linear equivalence reversing multiplication, +`e (x * y) = e y * e x`, between conic algebras is an isometry of their norm forms. For example +the conjugation of a quaternion algebra is one. -/ +noncomputable def isometryEquivOfLinearEquivOfMapMulRev (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) + (map_mul_rev : ∀ x y, e (x * y) = e y * e x) : C.norm.IsometryEquiv D.norm := + isometryEquivOfLinearEquivOfMapMulSelf C D e map_one fun x ↦ map_mul_rev x x + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] in +/-- A unital multiplicative linear equivalence preserves the conic norm. -/ +theorem norm_map_of_linearEquiv (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) (map_mul : ∀ x y, e (x * y) = e x * e y) + (x : A) : D.norm (e x) = C.norm x := + (isometryEquivOfLinearEquiv C D e map_one map_mul).map_app x + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] in +/-- A unital linear equivalence reversing multiplication preserves the conic norm +(`GPR 23.4(a)` for anti-isomorphisms). -/ +theorem norm_map_of_linearEquiv_of_map_mul_rev (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) (map_mul_rev : ∀ x y, e (x * y) = e y * e x) + (x : A) : D.norm (e x) = C.norm x := + (isometryEquivOfLinearEquivOfMapMulRev C D e map_one map_mul_rev).map_app x + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] in +/-- A unital multiplicative linear equivalence preserves the trace derived from the conic norm. -/ +theorem trace_map_of_linearEquiv (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) (map_mul : ∀ x y, e (x * y) = e x * e y) + (x : A) : D.trace (e x) = C.trace x := by + rw [trace_apply, trace_apply, QuadraticMap.polar] + rw [show (1 : B) = e (1 : A) from map_one.symm] + rw [← map_add, norm_map_of_linearEquiv C D e map_one map_mul, + norm_map_of_linearEquiv C D e map_one map_mul, + norm_map_of_linearEquiv C D e map_one map_mul] + rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] in +/-- A unital multiplicative linear equivalence preserves the standard conjugation. -/ +theorem conj_map_of_linearEquiv (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : A ≃ₗ[k] B) (map_one : e (1 : A) = 1) (map_mul : ∀ x y, e (x * y) = e x * e y) + (x : A) : D.conj (e x) = e (C.conj x) := by + rw [conj_apply, conj_apply, trace_map_of_linearEquiv C D e map_one map_mul, map_sub, map_smul, + map_one] + +section Associative + +variable {A' : Type v} {B' : Type w} [Ring A'] [Ring B'] [Algebra k A'] [Algebra k B'] + [Module.Finite k A'] [Module.Projective k A'] [Module.Finite k B'] [Module.Projective k B'] + +/-- For associative conic algebras, the easy direction is available through mathlib's standard +`AlgEquiv` API. -/ +noncomputable def isometryEquivOfAlgEquiv (C : ConicAlgebra k A') (D : ConicAlgebra k B') + (e : A' ≃ₐ[k] B') : C.norm.IsometryEquiv D.norm := + isometryEquivOfLinearEquiv C D e.toLinearEquiv e.map_one e.map_mul + +end Associative + +end Equiv + +section Normalize + +variable {B : Type w} [NonAssocRing B] [Module k B] [SMulCommClass k B B] + [IsScalarTower k B B] {D : ConicAlgebra k B} + +/-- Left multiplication by `conj x` is a linear equivalence when `n(x) = 1`; its inverse is left +multiplication by `x`. -/ +def leftMulConjLinearEquiv [IsAlternative B] (x : B) (hx : D.norm x = 1) : B ≃ₗ[k] B where + toFun z := D.conj x * z + invFun z := x * z + map_add' y z := mul_add _ _ _ + map_smul' c z := mul_smul_comm _ _ _ + left_inv z := by + change x * (D.conj x * z) = z + rw [mul_conj_mul_of_isAlternative, hx, one_smul] + right_inv z := by + change D.conj x * (x * z) = z + rw [conj_mul_mul_of_isAlternative, hx, one_smul] + +/-- Left multiplication by `conj x`, followed by division by `n(x)`, is a linear equivalence when +`n(x)` is a unit. Its inverse is left multiplication by `x`. -/ +def leftMulConjUnitLinearEquiv [IsAlternative B] (x : B) (μ : kˣ) + (hx : D.norm x = (μ : k)) : B ≃ₗ[k] B where + toFun z := (↑μ⁻¹ : k) • (D.conj x * z) + invFun z := x * z + map_add' y z := by rw [mul_add, smul_add] + map_smul' c z := by simp only [mul_smul_comm, RingHom.id_apply, smul_smul, mul_comm] + left_inv z := by + change x * ((↑μ⁻¹ : k) • (D.conj x * z)) = z + rw [mul_smul_comm, mul_conj_mul_of_isAlternative, hx, smul_smul, Units.inv_mul, one_smul] + right_inv z := by + change (↑μ⁻¹ : k) • (D.conj x * (x * z)) = z + rw [conj_mul_mul_of_isAlternative, hx, smul_smul, Units.inv_mul, one_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- For a norm-one element `x` in an alternative multiplicative conic algebra, left multiplication +by `conj x` is a self-isometry of the norm and carries `x` to `1`. -/ +noncomputable def IsMultiplicative.leftMulConjIsometryEquiv [IsAlternative B] + (h : D.IsMultiplicative) (x : B) (hx : D.norm x = 1) : D.norm.IsometryEquiv D.norm where + toLinearEquiv := D.leftMulConjLinearEquiv x hx + map_app' z := by + change D.norm (D.conj x * z) = D.norm z + rw [h.norm_mul, norm_conj, hx, one_mul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +@[simp] theorem IsMultiplicative.leftMulConjIsometryEquiv_apply_self [IsAlternative B] + (h : D.IsMultiplicative) (x : B) (hx : D.norm x = 1) : + h.leftMulConjIsometryEquiv x hx x = 1 := by + change D.conj x * x = 1 + rw [D.conj_mul_self, hx, one_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- **`GPR 23.3`, for norm similarities.** A similarity from the norm of `C` to the norm of an +alternative multiplicative conic algebra `D` can be normalized to a unital norm isometry. + +Here a similarity is given by a linear equivalence `e` and its unit multiplier `μ`, with +`n_D(e x) = μ n_C(x)`. Postcomposition by `μ⁻¹ L_{conj (e 1)}` removes the multiplier and sends +`1` to `1`. -/ +theorem IsMultiplicative.exists_isometryEquiv_map_one_of_similarity + [IsAlternative B] (h : D.IsMultiplicative) (C : ConicAlgebra k A) (e : A ≃ₗ[k] B) + (μ : kˣ) (he : ∀ x, D.norm (e x) = (μ : k) * C.norm x) : + ∃ e' : C.norm.IsometryEquiv D.norm, e' (1 : A) = 1 := by + have hx : D.norm (e (1 : A)) = (μ : k) := by rw [he, C.norm_one, mul_one] + let f := e.trans (D.leftMulConjUnitLinearEquiv (e 1) μ hx) + refine ⟨{ toLinearEquiv := f, map_app' := fun z ↦ ?_ }, ?_⟩ + · change D.norm ((↑μ⁻¹ : k) • (D.conj (e 1) * e z)) = C.norm z + rw [QuadraticMap.map_smul, h.norm_mul, norm_conj, hx, he] + simp only [smul_eq_mul] + ring_nf + rw [← Units.val_pow_eq_pow_val, ← Units.val_pow_eq_pow_val, ← Units.val_mul] + simp + · change f (1 : A) = 1 + change (↑μ⁻¹ : k) • (D.conj (e 1) * e 1) = 1 + rw [D.conj_mul_self, hx, smul_smul, Units.inv_mul, one_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + [SMulCommClass k B B] [IsScalarTower k B B] in +/-- **`GPR 23.2`.** A unital norm isometry preserves the trace derived from the polar form. -/ +theorem trace_map_of_isometryEquiv_map_one (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) (x : A) : + D.trace (e x) = C.trace x := by + rw [trace_apply, trace_apply, QuadraticMap.polar, QuadraticMap.polar] + rw [show (1 : B) = e (1 : A) from h1.symm, ← map_add, e.map_app, e.map_app, e.map_app] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + [SMulCommClass k B B] [IsScalarTower k B B] in +/-- **`GPR 23.2`.** A unital norm isometry commutes with standard conjugation. -/ +theorem conj_map_of_isometryEquiv_map_one (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) (x : A) : + D.conj (e x) = e (C.conj x) := by + rw [conj_apply, conj_apply, trace_map_of_isometryEquiv_map_one C D e h1, map_sub, map_smul, + h1] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + [SMulCommClass k B B] [IsScalarTower k B B] in +/-- **`GPR 23.2`.** A unital norm isometry preserves squares. This is the multiplication that is +already forced by the degree-two identity before the Cayley–Dickson induction recovers mixed +products. -/ +theorem map_mul_self_of_isometryEquiv_map_one (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) (x : A) : + e (x * x) = e x * e x := by + calc + e (x * x) = e (C.trace x • x - C.norm x • (1 : A)) := by rw [C.mul_self_eq] + _ = C.trace x • e x - C.norm x • e (1 : A) := by rw [map_sub, map_smul, map_smul] + _ = D.trace (e x) • e x - D.norm (e x) • (1 : B) := by + rw [trace_map_of_isometryEquiv_map_one C D e h1, e.map_app, h1] + _ = e x * e x := (D.mul_self_eq (e x)).symm + +/-- A unital linear equivalence restricts to a linear equivalence +`k[u] ≃ₗ[k] k[e u]` between the quadratic subalgebras generated by corresponding elements. + +No discriminant or rank hypothesis is needed: both subalgebras are, by definition, the spans of +`1` and the indicated element. -/ +noncomputable def adjoinElementLinearEquivOfMapOne (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : A ≃ₗ[k] B) (h1 : e (1 : A) = 1) (u : A) : + C.adjoinElement u ≃ₗ[k] D.adjoinElement (e u) where + toFun x := ⟨e x, by + obtain ⟨a, b, hx⟩ := (C.mem_adjoinElement_iff u x).mp x.2 + apply (D.mem_adjoinElement_iff (e u) (e x)).mpr + refine ⟨a, b, ?_⟩ + rw [← h1, ← map_smul, ← map_smul, ← map_add, hx]⟩ + invFun y := ⟨e.symm y, by + obtain ⟨a, b, hy⟩ := (D.mem_adjoinElement_iff (e u) y).mp y.2 + apply (C.mem_adjoinElement_iff u (e.symm y)).mpr + refine ⟨a, b, ?_⟩ + rw [← hy, map_add, map_smul, map_smul, + show e.symm (1 : B) = (1 : A) by rw [← h1, e.symm_apply_apply], e.symm_apply_apply]⟩ + map_add' x y := Subtype.ext (map_add e (x : A) (y : A)) + map_smul' c x := Subtype.ext (map_smul e c (x : A)) + left_inv x := Subtype.ext (e.symm_apply_apply (x : A)) + right_inv x := Subtype.ext (e.apply_symm_apply (x : B)) + +omit [Module.Finite k A] [Module.Projective k A] in +@[simp] theorem coe_adjoinElementLinearEquivOfMapOne_apply (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : A ≃ₗ[k] B) (h1 : e (1 : A) = 1) (u : A) + (x : C.adjoinElement u) : + (adjoinElementLinearEquivOfMapOne C D e h1 u x : B) = e (x : A) := rfl + +omit [Module.Finite k A] [Module.Projective k A] in +/-- **The quadratic base case for Layer 9.** A unital norm isometry restricts to a unital +multiplicative linear equivalence `k[u] ≅ k[e u]`. + +Multiplication in these monogenic conic algebras is the coefficient formula of `GPR 19.8`; its +only structure constants are `t(u)` and `n(u)`, both preserved by a unital norm isometry. -/ +theorem adjoinElementLinearEquivOfIsometryEquiv_map_mul + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) (x y : C.adjoinElement u) : + adjoinElementLinearEquivOfMapOne C D e.toLinearEquiv h1 u (x * y) = + adjoinElementLinearEquivOfMapOne C D e.toLinearEquiv h1 u x * + adjoinElementLinearEquivOfMapOne C D e.toLinearEquiv h1 u y := by + apply Subtype.ext + change e ((x : A) * (y : A)) = e (x : A) * e (y : A) + obtain ⟨a, b, hx⟩ := (C.mem_adjoinElement_iff u x).mp x.2 + obtain ⟨c, d, hy⟩ := (C.mem_adjoinElement_iff u y).mp y.2 + rw [← hx, ← hy] + simp only [map_add, map_smul, h1] + change e (spanOne k u (a, b) * spanOne k u (c, d)) = + spanOne k (e u) (a, b) * spanOne k (e u) (c, d) + rw [C.spanOne_mul, D.spanOne_mul] + simp only [spanOne_apply, map_add, map_smul, h1] + rw [trace_map_of_isometryEquiv_map_one C D e h1, e.map_app] + +omit [Module.Finite k A] [Module.Projective k A] in +@[simp] theorem adjoinElementLinearEquivOfMapOne_apply_one + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : A ≃ₗ[k] B) + (h1 : e (1 : A) = 1) (u : A) : + adjoinElementLinearEquivOfMapOne C D e h1 u 1 = 1 := + Subtype.ext h1 + +omit [Module.Finite k A] [Module.Projective k A] in +/-- The quadratic base equivalence of Layer 9, including its norm-isometry structure. -/ +noncomputable def adjoinElementIsometryEquivOfMapOne + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) : + (C.restrict (C.adjoinElement u)).norm.IsometryEquiv + (D.restrict (D.adjoinElement (e u))).norm where + toLinearEquiv := adjoinElementLinearEquivOfMapOne C D e.toLinearEquiv h1 u + map_app' x := e.map_app (x : A) + +omit [Module.Finite k A] [Module.Projective k A] in +/-- **The first Cayley–Dickson step in Layer 9.** The corresponding quadratic subalgebras +`k[u]` and `k[e u]` can be doubled by any common scalar `μ`; the componentwise equivalence is a +unital, multiplicative norm isometry. + +The complement isometry obtained from Witt cancellation supplies such a common scalar by carrying +a chosen doubling vector to one with the same norm. -/ +noncomputable def cayAdjoinElementIsometryEquivOfMapOne + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) (μ : k) : + ((C.restrict (C.adjoinElement u)).cay μ).norm.IsometryEquiv + ((D.restrict (D.adjoinElement (e u))).cay μ).norm := + cayIsometryEquiv (D.restrict (D.adjoinElement (e u))) + (adjoinElementIsometryEquivOfMapOne C D e h1 u) + +omit [Module.Finite k A] [Module.Projective k A] in +/-- The matched equivalence between the first doubles preserves the identity. -/ +theorem cayAdjoinElementIsometryEquivOfMapOne_map_one + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) (μ : k) : + cayAdjoinElementIsometryEquivOfMapOne C D e h1 u μ 1 = 1 := + cayIsometryEquiv_map_one (C := C.restrict (C.adjoinElement u)) (μ := μ) + (D.restrict (D.adjoinElement (e u))) + (adjoinElementIsometryEquivOfMapOne C D e h1 u) + (adjoinElementLinearEquivOfMapOne_apply_one C D e.toLinearEquiv h1 u) + +omit [Module.Finite k A] [Module.Projective k A] in +/-- The matched equivalence between the first doubles preserves multiplication. -/ +theorem cayAdjoinElementIsometryEquivOfMapOne_map_mul + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) (μ : k) + (x y : Cay (C.restrict (C.adjoinElement u)) μ) : + cayAdjoinElementIsometryEquivOfMapOne C D e h1 u μ (x * y) = + cayAdjoinElementIsometryEquivOfMapOne C D e h1 u μ x * + cayAdjoinElementIsometryEquivOfMapOne C D e h1 u μ y := + cayIsometryEquiv_map_mul (C := C.restrict (C.adjoinElement u)) (μ := μ) + (D.restrict (D.adjoinElement (e u))) + (adjoinElementIsometryEquivOfMapOne C D e h1 u) + (adjoinElementLinearEquivOfMapOne_apply_one C D e.toLinearEquiv h1 u) + (adjoinElementLinearEquivOfIsometryEquiv_map_mul C D e h1 u) x y + +section MatchedDouble + +variable [Module.Finite k B] [Module.Projective k B] [IsAlternative A] [IsAlternative B] + +/-- **One internal matched-doubling step for Layer 9.** Suppose `S ⊆ A` and `T ⊆ B` are +already related by a unital multiplicative norm isometry. If `v ⊥ S` and `v' ⊥ T` have the +same norm, then the internal doubles `S + Sv` and `T + Tv'` are again related by such an +isometry, provided the two internal doubling maps are injective. + +The resulting subalgebras are the images of `cayToAlgebra`. The equivalence is obtained by moving +back to the external double, applying `cayIsometryEquiv` componentwise, and moving into the other +image. -/ +theorem exists_doubledSubalgebras_isometryEquiv_and_equiv_cay (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (hCmul : C.IsMultiplicative) (hDmul : D.IsMultiplicative) + (e : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (h1 : e (1 : S) = 1) (hmul : ∀ x y, e (x * y) = e x * e y) {v : A} {v' : B} + (hSv : ∀ s ∈ S, QuadraticMap.polar C.norm s v = 0) + (hTv' : ∀ t ∈ T, QuadraticMap.polar D.norm t v' = 0) + (hv : IsUnit (C.norm v)) (hnorm : D.norm v' = C.norm v) + (hinjC : Function.Injective (cayToAlgebra C S v)) + (hinjD : Function.Injective (cayToAlgebra D T v')) : + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (iC : Cay (C.restrict S) (-C.norm v) ≃ₗ[k] S') + (iD : Cay (D.restrict T) (-D.norm v') ≃ₗ[k] T') + (f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + (∀ p, ((iC p : S') : A) = cayToAlgebra C S v p) ∧ + (∀ p, ((iD p : T') : B) = cayToAlgebra D T v' p) ∧ + f 1 = 1 ∧ ∀ x y, f (x * y) = f x * f y := by + have hv' : IsUnit (D.norm v') := hnorm.symm ▸ hv + obtain ⟨S', iC, hiC⟩ := exists_subalgebra_equiv_cay hSv hv hinjC + obtain ⟨T', iD, hiD⟩ := exists_subalgebra_equiv_cay hTv' hv' hinjD + let esame := cayIsometryEquiv (C := C.restrict S) (μ := -C.norm v) (D.restrict T) e + let eparam := cayIsometryEquivOfEq (D.restrict T) (congrArg Neg.neg hnorm.symm) + let ecay := esame.trans eparam + let fLinear : S' ≃ₗ[k] T' := iC.symm.trans (ecay.toLinearEquiv.trans iD) + have hiC_one : iC 1 = 1 := by + apply Subtype.ext + change (iC 1 : A) = 1 + rw [hiC, cayToAlgebra_one] + have hiD_one : iD 1 = 1 := by + apply Subtype.ext + change (iD 1 : B) = 1 + rw [hiD, cayToAlgebra_one] + have hiC_mul (x y : Cay (C.restrict S) (-C.norm v)) : iC (x * y) = iC x * iC y := by + apply Subtype.ext + change (iC (x * y) : A) = (iC x : A) * (iC y : A) + rw [hiC, hiC, hiC, cayToAlgebra_mul hSv C.conjIsInvolution_of_projective hv] + have hiD_mul (x y : Cay (D.restrict T) (-D.norm v')) : iD (x * y) = iD x * iD y := by + apply Subtype.ext + change (iD (x * y) : B) = (iD x : B) * (iD y : B) + rw [hiD, hiD, hiD, + cayToAlgebra_mul hTv' D.conjIsInvolution_of_projective hv'] + have hiC_symm_one : iC.symm 1 = 1 := by + rw [← hiC_one, iC.symm_apply_apply] + have hiC_symm_mul (x y : S') : iC.symm (x * y) = iC.symm x * iC.symm y := by + apply iC.injective + rw [iC.apply_symm_apply, hiC_mul, iC.apply_symm_apply, iC.apply_symm_apply] + let f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm := + { toLinearEquiv := fLinear + map_app' := fun x ↦ by + change D.norm (iD (ecay (iC.symm x)) : B) = C.norm (x : A) + rw [hiD, norm_cayToAlgebra hTv' hDmul, ecay.map_app, + ← norm_cayToAlgebra hSv hCmul, ← hiC, iC.apply_symm_apply] } + refine ⟨S', T', iC, iD, f, hiC, hiD, ?_, ?_⟩ + · change iD (ecay (iC.symm 1)) = 1 + rw [hiC_symm_one, show ecay 1 = 1 by + change eparam (esame 1) = 1 + rw [cayIsometryEquiv_map_one _ e h1, cayIsometryEquivOfEq_map_one], hiD_one] + · intro x y + change iD (ecay (iC.symm (x * y))) = + iD (ecay (iC.symm x)) * iD (ecay (iC.symm y)) + rw [hiC_symm_mul, show ∀ p q, ecay (p * q) = ecay p * ecay q by + intro p q + change eparam (esame (p * q)) = eparam (esame p) * eparam (esame q) + rw [cayIsometryEquiv_map_mul _ e h1 hmul, cayIsometryEquivOfEq_map_mul], hiD_mul] + +/-- The internal matched-doubling step, with the external-to-image equivalences hidden. -/ +theorem exists_doubledSubalgebras_isometryEquiv (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (hCmul : C.IsMultiplicative) (hDmul : D.IsMultiplicative) + (e : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (h1 : e (1 : S) = 1) (hmul : ∀ x y, e (x * y) = e x * e y) {v : A} {v' : B} + (hSv : ∀ s ∈ S, QuadraticMap.polar C.norm s v = 0) + (hTv' : ∀ t ∈ T, QuadraticMap.polar D.norm t v' = 0) + (hv : IsUnit (C.norm v)) (hnorm : D.norm v' = C.norm v) + (hinjC : Function.Injective (cayToAlgebra C S v)) + (hinjD : Function.Injective (cayToAlgebra D T v')) : + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + f 1 = 1 ∧ ∀ x y, f (x * y) = f x * f y := by + obtain ⟨S', T', _, _, f, _, _, h1, hmul⟩ := + exists_doubledSubalgebras_isometryEquiv_and_equiv_cay C D S T hCmul hDmul e h1 hmul + hSv hTv' hv hnorm hinjC hinjD + exact ⟨S', T', f, h1, hmul⟩ + +/-- The regular-base form of `exists_doubledSubalgebras_isometryEquiv`. Regularity makes both +internal doubling maps injective, so it is the form used by the Layer 9 induction. -/ +theorem exists_doubledSubalgebras_isometryEquiv_of_isGPRRegular + (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (hCmul : C.IsMultiplicative) (hDmul : D.IsMultiplicative) + (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) + (e : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (h1 : e (1 : S) = 1) (hmul : ∀ x y, e (x * y) = e x * e y) {v : A} {v' : B} + (hSv : ∀ s ∈ S, QuadraticMap.polar C.norm s v = 0) + (hTv' : ∀ t ∈ T, QuadraticMap.polar D.norm t v' = 0) + (hv : IsUnit (C.norm v)) (hnorm : D.norm v' = C.norm v) : + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + f 1 = 1 ∧ ∀ x y, f (x * y) = f x * f y := by + have hv' : IsUnit (D.norm v') := hnorm.symm ▸ hv + exact exists_doubledSubalgebras_isometryEquiv C D S T hCmul hDmul e h1 hmul hSv hTv' hv + hnorm (cayToAlgebra_injective hSv hv hCmul hSreg) + (cayToAlgebra_injective hTv' hv' hDmul hTreg) + +end MatchedDouble + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The canonical linear equivalence from a rank-one conic algebra to its base ring. -/ +noncomputable def unitFormLinearEquivOfRankAtStalkEqOne (C : ConicAlgebra k A) + [Nontrivial k] (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) : A ≃ₗ[k] k where + toLinearMap := C.unitForm + invFun a := a • (1 : A) + left_inv x := (eq_unitForm_smul_one_of_rankAtStalk_eq_one C hA x).symm + right_inv a := by simp + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem unitFormLinearEquivOfRankAtStalkEqOne_apply_one + (C : ConicAlgebra k A) [Nontrivial k] + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) : + unitFormLinearEquivOfRankAtStalkEqOne C hA (1 : A) = 1 := + C.unitForm_one + +omit [SMulCommClass k A A] [SMulCommClass k B B] in +/-- Every unital linear equivalence between constant-rank-one conic algebras is multiplicative. -/ +theorem linearEquiv_map_mul_of_rankAtStalk_eq_one [Nontrivial k] (C : ConicAlgebra k A) + (e : A ≃ₗ[k] B) (he1 : e (1 : A) = 1) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) (x y : A) : + e (x * y) = e x * e y := by + have hprod (a b : k) : (a • (1 : A)) * (b • 1) = (a * b) • (1 : A) := by + rw [smul_mul_assoc, one_mul, smul_smul] + have hprodB (a b : k) : (a • (1 : B)) * (b • 1) = (a * b) • (1 : B) := by + rw [smul_mul_assoc, one_mul, smul_smul] + rw [eq_unitForm_smul_one_of_rankAtStalk_eq_one C hA x, + eq_unitForm_smul_one_of_rankAtStalk_eq_one C hA y, hprod, map_smul, he1, map_smul, + map_smul, he1, hprodB] + +omit [SMulCommClass k A A] [SMulCommClass k B B] in +/-- **The rank-one case of the converse direction in Layer 9.** Any two constant-rank-one conic +algebras over a nontrivial base are unital multiplicatively norm-isometric. Both are canonically +identified with the base ring by `unitForm`; this avoids imposing regularity on the polar form, +which can fail in characteristic two. -/ +theorem exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq_one + [Module.Finite k B] [Module.Projective k B] [Nontrivial k] + (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) + (hB : Module.rankAtStalk (R := k) B = fun _ ↦ 1) : + ∃ e : C.norm.IsometryEquiv D.norm, + e (1 : A) = 1 ∧ ∀ x y, e (x * y) = e x * e y := by + let eA := unitFormLinearEquivOfRankAtStalkEqOne C hA + let eB := unitFormLinearEquivOfRankAtStalkEqOne D hB + let g : A ≃ₗ[k] B := eA.trans eB.symm + have hg1 : g (1 : A) = 1 := by + apply eB.injective + simp [g, eA, eB] + have hgmul : ∀ x y, g (x * y) = g x * g y := + linearEquiv_map_mul_of_rankAtStalk_eq_one C g hg1 hA + exact ⟨isometryEquivOfLinearEquiv C D g hg1 hgmul, hg1, hgmul⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- **Full-rank assembly for Layer 9.** A unital multiplicative norm isometry between regular +subalgebras of the same full rank extends to the ambient algebras, because each inclusion is then +a linear equivalence. + +The full-rank assertion is converted to surjectivity by +`ConicAlgebra.mem_of_isGPRRegular_of_rankAtStalk_eq`; no choice of complements remains at this +stage. -/ +theorem isometryEquivOf_fullRank_subalgebras [Module.Finite k B] [Module.Projective k B] + (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (f : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (hf1 : f (1 : S) = 1) (hfmul : ∀ x y, f (x * y) = f x * f y) + (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B = fun _ ↦ r) + (hS : Module.rankAtStalk (R := k) S.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) + (hT : Module.rankAtStalk (R := k) T.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) : + ∃ e : C.norm.IsometryEquiv D.norm, + e (1 : A) = 1 ∧ ∀ x y, e (x * y) = e x * e y := by + let incS : S →ₗ[k] A := S.toNonUnitalSubalgebra.toSubmodule.subtype + let incT : T →ₗ[k] B := T.toNonUnitalSubalgebra.toSubmodule.subtype + have hincS : Function.Bijective incS := + ⟨Subtype.val_injective, fun x ↦ + ⟨⟨x, mem_of_isGPRRegular_of_rankAtStalk_eq hSreg hA hS x⟩, rfl⟩⟩ + have hincT : Function.Bijective incT := + ⟨Subtype.val_injective, fun x ↦ + ⟨⟨x, mem_of_isGPRRegular_of_rankAtStalk_eq hTreg hB hT x⟩, rfl⟩⟩ + let eS : S ≃ₗ[k] A := LinearEquiv.ofBijective incS hincS + let eT : T ≃ₗ[k] B := LinearEquiv.ofBijective incT hincT + have eS_one : eS (1 : S) = 1 := rfl + have eT_one : eT (1 : T) = 1 := rfl + have eS_symm_one : eS.symm (1 : A) = 1 := by + rw [← eS_one, eS.symm_apply_apply] + have eS_symm_mul (x y : A) : eS.symm (x * y) = eS.symm x * eS.symm y := by + apply eS.injective + rw [eS.apply_symm_apply] + change x * y = (eS (eS.symm x) : A) * eS (eS.symm y) + rw [eS.apply_symm_apply, eS.apply_symm_apply] + let eLinear : A ≃ₗ[k] B := eS.symm.trans (f.toLinearEquiv.trans eT) + let e : C.norm.IsometryEquiv D.norm := + { toLinearEquiv := eLinear + map_app' := fun x ↦ + calc + D.norm (f (eS.symm x) : B) = (D.restrict T).norm (f (eS.symm x)) := rfl + _ = (C.restrict S).norm (eS.symm x) := f.map_app _ + _ = C.norm (eS (eS.symm x)) := rfl + _ = C.norm x := by rw [eS.apply_symm_apply] } + refine ⟨e, ?_, ?_⟩ + · change eT (f (eS.symm 1)) = 1 + rw [eS_symm_one, hf1, eT_one] + · intro x y + change eT (f (eS.symm (x * y))) = + eT (f (eS.symm x)) * eT (f (eS.symm y)) + rw [eS_symm_mul, hfmul] + rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] + [Module.Projective k A] [SMulCommClass k B B] [IsScalarTower k B B] in +/-- A unital norm isometry preserves the element discriminant `t(u) ^ 2 - 4 * n(u)`. -/ +theorem elementDiscriminant_map_of_isometryEquiv_map_one + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) (u : A) : + D.elementDiscriminant (e u) = C.elementDiscriminant u := by + rw [elementDiscriminant, elementDiscriminant, + trace_map_of_isometryEquiv_map_one C D e h1, e.map_app] + +omit [Module.Finite k A] [Module.Projective k A] in +/-- A unital norm isometry carries the regular rank-two composition subalgebra generated by `u` +to the one generated by `e u`. This is the base rung that the Layer 9 doubling induction uses. -/ +theorem isRegularRankTwoComposition_map_of_isometryEquiv_map_one + (C : ConicAlgebra k A) (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) {u : A} (hu : C.IsRegularRankTwoComposition u) : + D.IsRegularRankTwoComposition (e u) := by + rw [D.isRegularRankTwoComposition_iff_isUnit_discriminant, + elementDiscriminant_map_of_isometryEquiv_map_one C D e h1] + exact (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mp hu + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- **The general Witt-cancellation step for Layer 9.** If an ambient norm isometry identifies +the regular restricted norm forms on `S ⊆ A` and `T ⊆ B`, then their orthogonal complements +are isometric over an LG ring. + +This is the form needed after every matched doubling rung. The target ambient norm is assumed +non-singular in the GPR sense through `hD`; no composition hypothesis on `C` is used. -/ +theorem exists_isometryEquiv_polarOrthogonal [Module.Finite k B] [Module.Projective k B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hD : D.IsComposition.{u, w, u}) (S : NonAssocSubalgebra k A) + (T : NonAssocSubalgebra k B) (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) + (eST : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (e : C.norm.IsometryEquiv D.norm) : + Nonempty + ((C.norm.comp + (C.norm.polarOrthogonal S.toNonUnitalSubalgebra.toSubmodule).subtype).IsometryEquiv + (D.norm.comp + (D.norm.polarOrthogonal T.toNonUnitalSubalgebra.toSubmodule).subtype)) := by + let NS := S.toNonUnitalSubalgebra.toSubmodule + let NT := T.toNonUnitalSubalgebra.toSubmodule + let qPS := C.norm.comp (C.norm.polarOrthogonal NS).subtype + let qPT := D.norm.comp (D.norm.polarOrthogonal NT).subtype + let : Module.Finite k NS := QuadraticForm.finite_of_comp_isGPRRegular hSreg + let : Module.Projective k NS := QuadraticForm.projective_of_comp_isGPRRegular hSreg + let : Module.Finite k (D.norm.polarOrthogonal NT) := + QuadraticForm.finite_polarOrthogonal hTreg + let : Module.Projective k (D.norm.polarOrthogonal NT) := + QuadraticForm.projective_polarOrthogonal hTreg + have hPT : QuadraticForm.IsGPRNonsingular.{u, w, u} qPT := + hD.isGPRNonsingular.comp_polarOrthogonal_subtype hTreg + let total : (qPS.prod (C.norm.comp NS.subtype)).IsometryEquiv + (qPT.prod (C.norm.comp NS.subtype)) := + (QuadraticMap.IsometryEquiv.prodComm _ _).trans + ((QuadraticForm.orthogonalDecompositionIsometryEquiv hSreg).trans + (e.trans ((QuadraticForm.orthogonalDecompositionIsometryEquiv hTreg).symm.trans + ((QuadraticMap.IsometryEquiv.prod eST.symm + (QuadraticMap.IsometryEquiv.refl qPT)).trans + (QuadraticMap.IsometryEquiv.prodComm _ _))))) + exact QuadraticForm.cancel hLG hPT hSreg ⟨total⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- **Selecting matched doubling vectors at an arbitrary Layer 9 rung.** If the complement of +`S` has full support, it represents a unit over the LG ring. The general cancellation isometry +then carries that vector to the complement of `T`, preserving its norm exactly. -/ +theorem IsComposition.exists_matched_isUnit_norm_orthogonal [Module.Finite k B] + [Module.Projective k B] (hLG : IsLGRing k) (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (hC : C.IsComposition.{u, v, u}) + (hD : D.IsComposition.{u, w, u}) (S : NonAssocSubalgebra k A) + (T : NonAssocSubalgebra k B) (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) + (eST : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (e : C.norm.IsometryEquiv D.norm) + (hsupp : Module.HasFullSupport k + (C.norm.polarOrthogonal S.toNonUnitalSubalgebra.toSubmodule)) : + ∃ v : A, ∃ v' : B, IsUnit (C.norm v) ∧ + (∀ s ∈ S, QuadraticMap.polar C.norm s v = 0) ∧ + (∀ t ∈ T, QuadraticMap.polar D.norm t v' = 0) ∧ D.norm v' = C.norm v := by + obtain ⟨v, hv, hSv⟩ := hC.exists_isUnit_norm_orthogonal hLG hSreg hsupp + obtain ⟨g⟩ := exists_isometryEquiv_polarOrthogonal hLG C D hD S T hSreg hTreg eST e + let vS : C.norm.polarOrthogonal S.toNonUnitalSubalgebra.toSubmodule := + ⟨v, fun s hs ↦ hSv s hs⟩ + refine ⟨v, (g vS : B), hv, hSv, ?_, g.map_app vS⟩ + exact fun t ht ↦ (g vS).2 t ht + +/-- **One complete induction step for Layer 9.** Matched regular subalgebras with a proper source +complement can be enlarged simultaneously: unit representation and Witt cancellation choose +matched orthogonal vectors, and internal Cayley–Dickson doubling produces new image subalgebras +related by a unital multiplicative norm isometry. -/ +theorem IsComposition.exists_next_doubledSubalgebras_isometryEquiv [Module.Finite k B] + [Module.Projective k B] [IsAlternative A] [IsAlternative B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) + (eST : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (h1 : eST (1 : S) = 1) (hmul : ∀ x y, eST (x * y) = eST x * eST y) + (e : C.norm.IsometryEquiv D.norm) + (hsupp : Module.HasFullSupport k + (C.norm.polarOrthogonal S.toNonUnitalSubalgebra.toSubmodule)) : + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + f 1 = 1 ∧ ∀ x y, f (x * y) = f x * f y := by + obtain ⟨v, v', hv, hSv, hTv', hnorm⟩ := + hC.exists_matched_isUnit_norm_orthogonal hLG C D hD S T hSreg hTreg eST e hsupp + exact exists_doubledSubalgebras_isometryEquiv_of_isGPRRegular C D S T + hC.isMultiplicative hD.isMultiplicative hSreg hTreg eST h1 hmul hSv hTv' hv hnorm + +/-- **The self-feeding Layer 9 induction step.** If the matched input subalgebras both have +constant rank `s`, the enlarged subalgebras have regular restricted norms and constant rank `2s`, +in addition to carrying the new unital multiplicative norm isometry. Thus the output satisfies the +hypotheses needed for the next doubling rung. -/ +theorem IsComposition.exists_next_isGPRRegular_rankAtStalk_two_mul + [Module.Finite k B] [Module.Projective k B] [IsAlternative A] [IsAlternative B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm) + (hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm) + (eST : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm) + (h1 : eST (1 : S) = 1) (hmul : ∀ x y, eST (x * y) = eST x * eST y) + (e : C.norm.IsometryEquiv D.norm) {s : ℕ} + (hSrank : Module.rankAtStalk (R := k) S.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ s) + (hTrank : Module.rankAtStalk (R := k) T.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ s) + (hsupp : Module.HasFullSupport k + (C.norm.polarOrthogonal S.toNonUnitalSubalgebra.toSubmodule)) : + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (f : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + f 1 = 1 ∧ (∀ x y, f (x * y) = f x * f y) ∧ + QuadraticForm.IsGPRRegular (C.restrict S').norm ∧ + QuadraticForm.IsGPRRegular (D.restrict T').norm ∧ + (Module.rankAtStalk (R := k) S'.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ 2 * s) ∧ + (Module.rankAtStalk (R := k) T'.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ 2 * s) := by + obtain ⟨v, v', hv, hSv, hTv', hnorm⟩ := + hC.exists_matched_isUnit_norm_orthogonal hLG C D hD S T hSreg hTreg eST e hsupp + have hv' : IsUnit (D.norm v') := hnorm.symm ▸ hv + obtain ⟨S', T', iC, iD, f, hiC, hiD, hf1, hfmul⟩ := + exists_doubledSubalgebras_isometryEquiv_and_equiv_cay C D S T hC.isMultiplicative + hD.isMultiplicative eST h1 hmul hSv hTv' hv hnorm + (cayToAlgebra_injective hSv hv hC.isMultiplicative hSreg) + (cayToAlgebra_injective hTv' hv' hD.isMultiplicative hTreg) + obtain ⟨hS'reg, hS'rank⟩ := isGPRRegular_restrict_and_rankAtStalk_of_equiv_cay + hC hSreg hSv hv S' iC hiC hSrank + obtain ⟨hT'reg, hT'rank⟩ := isGPRRegular_restrict_and_rankAtStalk_of_equiv_cay + hD hTreg hTv' hv' T' iD hiD hTrank + exact ⟨S', T', f, hf1, hfmul, hS'reg, hT'reg, hS'rank, hT'rank⟩ + +/-- The fuel-based finite iteration behind the converse direction of Layer 9. -/ +private theorem IsComposition.exists_fullRank_subalgebras_isometryEquiv_aux + [Nontrivial k] [Module.Finite k B] [Module.Projective k B] + [IsAlternative A] [IsAlternative B] (hLG : IsLGRing k) + (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B = fun _ ↦ r) + (e : C.norm.IsometryEquiv D.norm) : + ∀ (n s : ℕ) (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B), + QuadraticForm.IsGPRRegular (C.restrict S).norm → + QuadraticForm.IsGPRRegular (D.restrict T).norm → + ∀ f : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm, + f (1 : S) = 1 → (∀ x y, f (x * y) = f x * f y) → + Module.rankAtStalk (R := k) S.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) → + Module.rankAtStalk (R := k) T.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) → + 0 < s → s ≤ r → r - s ≤ n → + ∃ (S' : NonAssocSubalgebra k A) (T' : NonAssocSubalgebra k B) + (f' : (C.restrict S').norm.IsometryEquiv (D.restrict T').norm), + f' 1 = 1 ∧ (∀ x y, f' (x * y) = f' x * f' y) ∧ + QuadraticForm.IsGPRRegular (C.restrict S').norm ∧ + QuadraticForm.IsGPRRegular (D.restrict T').norm ∧ + (Module.rankAtStalk (R := k) S'.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) ∧ + (Module.rankAtStalk (R := k) T'.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) := by + intro n + induction n with + | zero => + intro s S T hSreg hTreg f hf1 hfmul hSrank hTrank hs0 hsr hfuel + have hsr' : s = r := by omega + subst r + exact ⟨S, T, f, hf1, hfmul, hSreg, hTreg, hSrank, hTrank⟩ + | succ n ih => + intro s S T hSreg hTreg f hf1 hfmul hSrank hTrank hs0 hsr hfuel + by_cases hfull : s = r + · subst r + exact ⟨S, T, f, hf1, hfmul, hSreg, hTreg, hSrank, hTrank⟩ + · have hlt : s < r := lt_of_le_of_ne hsr hfull + have hsupp := hasFullSupport_polarOrthogonal_of_rankAtStalk_lt + (C := C) hSreg hA hSrank hlt + obtain ⟨S', T', f', hf1', hfmul', hS'reg, hT'reg, hS'rank, hT'rank⟩ := + hC.exists_next_isGPRRegular_rankAtStalk_two_mul hLG C D hD S T hSreg hTreg + f hf1 hfmul e hSrank hTrank hsupp + have hle : 2 * s ≤ r := by + have hle' := rankAtStalk_le_of_isGPRRegular hS'reg + (Classical.arbitrary (PrimeSpectrum k)) + rwa [hS'rank, hA] at hle' + exact ih (2 * s) S' T' hS'reg hT'reg f' hf1' hfmul' hS'rank hT'rank + (by omega) hle (by omega) + +/-- **Finite matched doubling from rank two to full rank.** Starting from corresponding regular +quadratic subalgebras, the self-feeding step is iterated until both image subalgebras have the full +ambient rank. -/ +theorem IsComposition.exists_fullRank_subalgebras_isometryEquiv + [Nontrivial k] [Module.Finite k B] [Module.Projective k B] + [IsAlternative A] [IsAlternative B] (hLG : IsLGRing k) + (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (e : C.norm.IsometryEquiv D.norm) (he1 : e (1 : A) = 1) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B = fun _ ↦ r) (hr : 2 ≤ r) : + ∃ (S : NonAssocSubalgebra k A) (T : NonAssocSubalgebra k B) + (f : (C.restrict S).norm.IsometryEquiv (D.restrict T).norm), + f 1 = 1 ∧ (∀ x y, f (x * y) = f x * f y) ∧ + QuadraticForm.IsGPRRegular (C.restrict S).norm ∧ + QuadraticForm.IsGPRRegular (D.restrict T).norm ∧ + (Module.rankAtStalk (R := k) S.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) ∧ + (Module.rankAtStalk (R := k) T.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) := by + obtain ⟨u, hu⟩ := hC.exists_isRegularRankTwoComposition_of_rankAtStalk hLG fun p ↦ by + rw [hA] + exact hr + have huD : D.IsRegularRankTwoComposition (e u) := + isRegularRankTwoComposition_map_of_isometryEquiv_map_one C D e he1 hu + let S := C.adjoinElement u + let T := D.adjoinElement (e u) + have hdisc : IsUnit (C.elementDiscriminant u) := + (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mp hu + have hdiscD : IsUnit (D.elementDiscriminant (e u)) := + (D.isRegularRankTwoComposition_iff_isUnit_discriminant (e u)).mp huD + have hSreg : QuadraticForm.IsGPRRegular (C.restrict S).norm := + C.normAdjoinElement_isGPRRegular hdisc + have hTreg : QuadraticForm.IsGPRRegular (D.restrict T).norm := + D.normAdjoinElement_isGPRRegular hdiscD + let f := adjoinElementIsometryEquivOfMapOne C D e he1 u + have hf1 : f (1 : S) = 1 := + adjoinElementLinearEquivOfMapOne_apply_one C D e.toLinearEquiv he1 u + have hfmul : ∀ x y, f (x * y) = f x * f y := + adjoinElementLinearEquivOfIsometryEquiv_map_mul C D e he1 u + have hSrank := C.rankAtStalk_adjoinElement hdisc + have hTrank := D.rankAtStalk_adjoinElement hdiscD + exact hC.exists_fullRank_subalgebras_isometryEquiv_aux hLG C D hD hA hB e + (r - 2) 2 S T hSreg hTreg f hf1 hfmul hSrank hTrank (by omega) hr (by omega) + +/-- **`GPR 23.5`, the norm equivalence theorem, in constant rank at least two.** Over a nontrivial +LG ring, composition algebras of the same constant rank `r ≥ 2` with isometric norm forms are +isomorphic as unital non-associative algebras. The isomorphism is expressed, as elsewhere in this +file, by a linear equivalence together with its unital and multiplicative laws. + +The proof normalizes the norm isometry at `1`, matches the regular quadratic starting +subalgebras, iterates the matched Cayley–Dickson enlargement to full rank, and finally identifies +the full-rank image subalgebras with the ambient algebras. -/ +theorem IsComposition.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk + [Nontrivial k] [Module.Finite k B] [Module.Projective k B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (e : C.norm.IsometryEquiv D.norm) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : 2 ≤ r) : + ∃ e' : C.norm.IsometryEquiv D.norm, + e' (1 : A) = 1 ∧ ∀ x y, e' (x * y) = e' x * e' y := by + have hB : Module.rankAtStalk (R := k) B = fun _ ↦ r := + (Module.rankAtStalk_eq_of_equiv e.toLinearEquiv).symm.trans hA + have hCreg : C.norm.IsGPRRegular := + hC.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + have hDreg : D.norm.IsGPRRegular := + hD.isGPRRegular_of_rankAtStalk_ne_one hB (by omega) + have hCnd : C.norm.IsGPRNondegenerate := + Submodule.eq_bot_iff _ |>.mpr fun _ hx ↦ + (injective_iff_map_eq_zero _).mp hCreg.1 _ hx.2 + have hDnd : D.norm.IsGPRNondegenerate := + Submodule.eq_bot_iff _ |>.mpr fun _ hx ↦ + (injective_iff_map_eq_zero _).mp hDreg.1 _ hx.2 + let : IsAlternative A := hC.isMultiplicative.isAlternative hCnd + let : IsAlternative B := hD.isMultiplicative.isAlternative hDnd + have hx : D.norm (e (1 : A)) = 1 := by rw [e.map_app, C.norm_one] + let e1 := e.trans (hD.isMultiplicative.leftMulConjIsometryEquiv (e 1) hx) + have he1 : e1 (1 : A) = 1 := + hD.isMultiplicative.leftMulConjIsometryEquiv_apply_self (e 1) hx + obtain ⟨S, T, f, hf1, hfmul, hSreg, hTreg, hSrank, hTrank⟩ := + hC.exists_fullRank_subalgebras_isometryEquiv hLG C D hD e1 he1 hA hB hr + exact isometryEquivOf_fullRank_subalgebras C D S T f hf1 hfmul hSreg hTreg + hA hB hSrank hTrank + +/-- **`GPR 23.5`, the norm equivalence theorem.** Over a nontrivial LG ring, composition algebras +of the same constant rank with isometric norm forms are isomorphic as unital +non-associative algebras. + +By `GPR 19.18`, the common rank is `1`, `2`, `4`, or `8`. Rank one is handled directly through the +canonical `unitForm` coordinate, while the other three cases use the regular matched-doubling +argument based on `GPR 19.16(b)` and Witt cancellation (`GN 6.5`). -/ +theorem IsComposition.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq + [Nontrivial k] [Module.Finite k B] [Module.Projective k B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (e : C.norm.IsometryEquiv D.norm) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) : + ∃ e' : C.norm.IsometryEquiv D.norm, + e' (1 : A) = 1 ∧ ∀ x y, e' (x * y) = e' x * e' y := by + have hB : Module.rankAtStalk (R := k) B = fun _ ↦ r := + (Module.rankAtStalk_eq_of_equiv e.toLinearEquiv).symm.trans hA + rcases hC.rankAtStalk_eq_one_or_two_or_four_or_eight hA with h1 | h2 | h4 | h8 + · subst r + exact exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq_one C D hA hB + · subst r + exact hC.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk hLG C D hD e hA (by omega) + · subst r + exact hC.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk hLG C D hD e hA (by omega) + · subst r + exact hC.exists_isometryEquiv_map_one_map_mul_of_rankAtStalk hLG C D hD e hA (by omega) + +/-- **`GPR 23.5`, without a constant-rank hypothesis.** Over a nontrivial LG ring, composition +algebras with isometric norm forms are isomorphic as unital non-associative algebras. + +The rank idempotents decompose both modules into the same constant-rank factors: a norm isometry +is in particular a linear equivalence, so the two rank functions agree. The constant-rank norm +equivalence theorem is applied on every idempotent factor, and the resulting isomorphisms are +glued through the module decomposition of `GPR Exc. 9.31`. -/ +theorem IsComposition.exists_isometryEquiv_map_one_map_mul + [Module.Finite k B] [Module.Projective k B] + (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hC : C.IsComposition.{u, v, u}) (hD : D.IsComposition.{u, w, u}) + (e : C.norm.IsometryEquiv D.norm) : + ∃ e' : C.norm.IsometryEquiv D.norm, + e' (1 : A) = 1 ∧ ∀ x y, e' (x * y) = e' x * e' y := by + classical + let I := Module.rankFinset k A + let ε : I → k := fun i ↦ Module.rankIdempotent k A i + let hε : CompleteOrthogonalIdempotents ε := + Module.completeOrthogonalIdempotents_rankIdempotent_rankFinset k A + have hrankB : Module.rankAtStalk (R := k) B = Module.rankAtStalk (R := k) A := + (Module.rankAtStalk_eq_of_equiv e.toLinearEquiv).symm + have hrankA (i : I) : + Module.rankAtStalk (R := (k ⧸ Ideal.span {1 - ε i})) + (TensorProduct k (k ⧸ Ideal.span {1 - ε i}) A) = fun _ ↦ (i : ℕ) := + Module.rankAtStalk_quotientTensor_rankIdempotent k A i + have hrankB' (i : I) : + Module.rankAtStalk (R := (k ⧸ Ideal.span {1 - ε i})) + (TensorProduct k (k ⧸ Ideal.span {1 - ε i}) B) = fun _ ↦ (i : ℕ) := by + funext p + rw [Module.rankAtStalk_baseChange, hrankB, ← Module.rankAtStalk_baseChange] + exact congrFun (hrankA i) p + have hlocal (i : I) : + ∃ f : (C.baseChangeOfProjective (k ⧸ Ideal.span {1 - ε i})).norm.IsometryEquiv + (D.baseChangeOfProjective (k ⧸ Ideal.span {1 - ε i})).norm, + f (1 : TensorProduct k (k ⧸ Ideal.span {1 - ε i}) A) = 1 ∧ + ∀ x y, f (x * y) = f x * f y := by + let S := k ⧸ Ideal.span {1 - ε i} + rcases subsingleton_or_nontrivial S with hS | hS + · let := hS + let : Subsingleton (TensorProduct k S A) := Module.subsingleton S _ + let : Subsingleton (TensorProduct k S B) := Module.subsingleton S _ + exact ⟨⟨LinearEquiv.ofSubsingleton _ _, fun _ ↦ Subsingleton.elim _ _⟩, + Subsingleton.elim _ _, fun _ _ ↦ Subsingleton.elim _ _⟩ + · let := hS + have hLGi : IsLGRing S := + hLG.quotient_span_one_sub_of_isIdempotentElem + (Module.isIdempotentElem_rankIdempotent k A i) + have hei := QuadraticMap.IsometryEquiv.baseChangeOfProjective (A := S) C.norm D.norm e + exact (hC.baseChangeOfProjective S).exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq + hLGi + (C.baseChangeOfProjective S) (D.baseChangeOfProjective S) + (hD.baseChangeOfProjective S) hei (hrankA i) + choose f hf1 hfmul using hlocal + let EA := hε.linearEquivPiQuotientTensor A ε + let EB := hε.linearEquivPiQuotientTensor B ε + let fp : (∀ i, TensorProduct k (k ⧸ Ideal.span {1 - ε i}) A) ≃ₗ[k] + ∀ i, TensorProduct k (k ⧸ Ideal.span {1 - ε i}) B := + LinearEquiv.piCongrRight fun i ↦ f i |>.toLinearEquiv.restrictScalars k + let g : A ≃ₗ[k] B := EA.trans (fp.trans EB.symm) + have hcomponent (x : A) (i : I) : EB (g x) i = f i (EA x i) := by + simp [g, fp] + have hg1 : g (1 : A) = 1 := + EB.injective <| funext fun i ↦ by + rw [hcomponent] + exact hf1 i + have hgmul : ∀ x y, g (x * y) = g x * g y := by + intro x y + apply EB.injective + funext i + rw [hcomponent] + change f i (1 ⊗ₜ[k] (x * y)) = 1 ⊗ₜ[k] (g x * g y) + rw [one_tmul_mul, hfmul, one_tmul_mul] + have hx := hcomponent x i + have hy := hcomponent y i + simp only [EA, EB, + CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor_apply] at hx hy + exact congrArg₂ (· * ·) hx.symm hy.symm + refine ⟨{ toLinearEquiv := g, map_app' := fun x ↦ ?_ }, hg1, hgmul⟩ + apply hε.bijective_pi.1 + funext i + have hi := (f i).map_app (EA x i) + rw [← hcomponent] at hi + simpa [EA, EB, QuadraticForm.baseChangeOfProjective_tmul, Algebra.smul_def] using hi + +/-- **The Witt-cancellation step in `GPR 23.5`.** Let a unital norm isometry carry `u` to `e u`, and +suppose `k[u]` is a regular rank-two composition subalgebra. Then the orthogonal complements of +`k[u]` and `k[e u]` are isometric over an LG ring. + +The ambient forms split as the regular quadratic summand plus its orthogonal complement. The +quadratic summands are isometric by `adjoinElementLinearEquivOfMapOne`; cancelling that common +regular summand with `GN 6.5` gives the result. -/ +theorem exists_isometryEquiv_polarOrthogonal_adjoinElement [Module.Finite k B] + [Module.Projective k B] (hLG : IsLGRing k) (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hD : D.IsComposition.{u, w, u}) (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : A) = 1) {u : A} (hu : C.IsRegularRankTwoComposition u) : + Nonempty + ((C.norm.comp + (C.norm.polarOrthogonal + (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule).subtype).IsometryEquiv + (D.norm.comp + (D.norm.polarOrthogonal + (D.adjoinElement (e u)).toNonUnitalSubalgebra.toSubmodule).subtype)) := by + let NC := (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule + let ND := (D.adjoinElement (e u)).toNonUnitalSubalgebra.toSubmodule + have hdisc : IsUnit (C.elementDiscriminant u) := + (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mp hu + have hdiscD : IsUnit (D.elementDiscriminant (e u)) := + elementDiscriminant_map_of_isometryEquiv_map_one C D e h1 u ▸ hdisc + have hregC : QuadraticForm.IsGPRRegular (C.norm.comp NC.subtype) := + C.normAdjoinElement_isGPRRegular hdisc + have hregD : QuadraticForm.IsGPRRegular (D.norm.comp ND.subtype) := + D.normAdjoinElement_isGPRRegular hdiscD + exact exists_isometryEquiv_polarOrthogonal hLG C D hD (C.adjoinElement u) + (D.adjoinElement (e u)) hregC hregD (adjoinElementIsometryEquivOfMapOne C D e h1 u) e + +/-- **Matching the first doubling parameter in Layer 9.** Under the hypotheses of the complement +cancellation step, every vector in the complement of `k[u]` has a corresponding vector in the +complement of `k[e u]` with exactly the same norm. In particular, unit-norm doubling vectors give +the same Cayley–Dickson scalar on both sides. -/ +theorem exists_polarOrthogonal_adjoinElement_eq_norm [Module.Finite k B] + [Module.Projective k B] (hLG : IsLGRing k) (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (hD : D.IsComposition.{u, w, u}) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) {u : A} + (hu : C.IsRegularRankTwoComposition u) + (v : C.norm.polarOrthogonal + (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule) : + ∃ v' : D.norm.polarOrthogonal + (D.adjoinElement (e u)).toNonUnitalSubalgebra.toSubmodule, + D.norm (v' : B) = C.norm (v : A) := by + obtain ⟨g⟩ := exists_isometryEquiv_polarOrthogonal_adjoinElement hLG C D hD e h1 hu + exact ⟨g v, g.map_app v⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- **`GPR 23.3`, unital normalization of a norm isometry.** If `D` is alternative and +multiplicative, every isometry `n_C ≅ n_D` can be postcomposed with a self-isometry of `n_D` so +that it sends `1` to `1`. This is the first step of the norm equivalence theorem `GPR 23.5`. -/ +theorem IsMultiplicative.exists_isometryEquiv_map_one [IsAlternative B] + (h : D.IsMultiplicative) (C : ConicAlgebra k A) (e : C.norm.IsometryEquiv D.norm) : + ∃ e' : C.norm.IsometryEquiv D.norm, e' (1 : A) = 1 := by + have hx : D.norm (e (1 : A)) = 1 := by rw [e.map_app, C.norm_one] + refine ⟨e.trans (h.leftMulConjIsometryEquiv (e 1) hx), ?_⟩ + exact h.leftMulConjIsometryEquiv_apply_self (e 1) hx + +end Normalize + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/NormEquivalence.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/NormEquivalence.lean new file mode 100644 index 0000000000..445fb3091d --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/NormEquivalence.lean @@ -0,0 +1,244 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormClassification +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Splitness +public import LeanPool.CompositionAlgebrasOverRings.Conic.QuadraticAlgebra + +/-! +# Automorphisms are the unital norm equivalences (`GPR 23.4`) + +A **unital norm equivalence** of conic algebras is a linear equivalence carrying `1` to `1` and the +norm to the norm (`GPR 23.1`); `Composition/NormClassification.lean` produces them from arbitrary +norm isometries (`GPR 23.3`) and shows they preserve trace, conjugation and squares (`GPR 23.2`). + +`GPR 23.4` compares them with algebra isomorphisms in the two directions that are true. + +**(a) Every isomorphism or anti-isomorphism is a unital norm equivalence, in every rank.** The +norm of a finitely generated projective conic algebra is intrinsic (`GPR 16.16`), so a unital +linear equivalence preserving squares has no choice but to preserve it. This is +`ConicAlgebra.norm_map_of_linearEquiv` for isomorphisms and +`ConicAlgebra.norm_map_of_linearEquiv_of_map_mul_rev` for anti-isomorphisms, recorded here for a +self-map as `ConicAlgebra.norm_map_of_automorphism`. + +**(b) For quadratic algebras the converse holds.** A **quadratic algebra** is a unital algebra that +is finitely generated projective of constant rank two (`GPR 16.4`). The proof is `GPR`'s, and it +holds over an **arbitrary** commutative ring, with no LG, nontriviality, regularity, composition or +characteristic hypothesis. Multiplication in a conic algebra generated by `1` and one element `u` +has only the two structure constants `t(u)` and `n(u)` (`GPR 19.8`), and a unital norm equivalence +preserves both (`GPR 23.2`), so out of such an algebra it is automatically multiplicative. A +quadratic algebra need not be generated by one element, but multiplicativity is an equation, so it +may be checked after base change to the localization `k_𝔪` at every maximal ideal +(`ConicAlgebra.eq_of_forall_localization_maximal`), and a unital norm equivalence base changes to +one (`QuadraticMap.IsometryEquiv.baseChangeOfProjective`). Over `k_𝔪`, as over any LG ring, the +unit is unimodular (`GPR 16.7`) with a free complement of rank one (`GPR 11.24`), whose generator +`u` gives `k_𝔪 ⊗ A = k_𝔪[u]` +(`ConicAlgebra.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two`). + +⚠ **(b) is false in higher rank**, which is why `GPR 23.4` is stated as it is. The standard +conjugation of a quaternion algebra is a unital norm equivalence — `ConicAlgebra.norm_conj` and +`ConicAlgebra.conj_one` — but it is an anti-automorphism, and a quaternion algebra is not +commutative (`ConicAlgebra.exists_mul_ne_mul_realQuaternion`). What rank two supplies is a property +of the algebra, not of the map. + +## How the statement matches `GPR 23.4(b)` + +`GPR 16.4` makes a quadratic algebra conic by Cayley–Hamilton, with `n(x) = det(L_x)` and +`t(x) = tr(L_x)`. The statements here instead take **arbitrary** conic structures `C` on `A` and +`D` on `B`. This loses nothing: a finitely generated projective algebra carries at most one conic +norm (`ConicAlgebra.norm_eq_of_projective`, `GPR 16.16`), so whatever conic structure is supplied, +its norm is the norm of `GPR 16.4`, and "`e` is a unital norm equivalence" means exactly what it +means in `GPR`. Only `A` is assumed finitely generated projective of constant rank two; for `B` this +follows from the linear equivalence, so `B` is only assumed to be conic. Neither algebra is assumed +associative or commutative; `GPR 16.4` shows both, but they are not needed here. + +The existence half of `GPR 16.4` — every unital algebra that is finitely generated projective of +rank two admits a conic norm — is `ConicAlgebra.nonempty_of_rankAtStalk_eq_two` +(`Conic/QuadraticAlgebra.lean`). With it, `ConicAlgebra.map_mul_of_norm_map_of_rankAtStalk_eq_two` +states `GPR 23.4(b)` for quadratic algebras exactly as `GPR` does, with no conic structure +supplied. + +## Main results + +* `ConicAlgebra.norm_map_of_automorphism` : **`GPR 23.4(a)`**. +* `ConicAlgebra.map_mul_of_isometryEquiv_map_one_of_forall_mem_adjoinElement` : the engine of + **`GPR 23.4(b)`** — a unital norm equivalence out of a monogenic conic algebra is multiplicative, + over any commutative ring and with no regularity hypothesis. +* `ConicAlgebra.map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two` : **`GPR 23.4(b)`**. +* `ConicAlgebra.isomorphic_of_isometryEquiv_map_one_of_rankAtStalk_eq_two` : the same, as + `ConicAlgebra.Isomorphic`. +* `ConicAlgebra.map_mul_iff_norm_map_of_rankAtStalk_eq_two` : **`GPR 23.4`** for quadratic + algebras, both directions: a unital linear equivalence is multiplicative if and only if it + preserves the norm. +* `ConicAlgebra.map_mul_of_norm_map_of_rankAtStalk_eq_two` : **`GPR 23.4(b)`** for quadratic + algebras with their norms from `GPR 16.4`, no conic structure supplied. +* `ConicAlgebra.map_mul_of_isometryEquiv_map_one_of_finrank_eq_two`, + `ConicAlgebra.map_mul_iff_norm_map_of_finrank_eq_two` : the field case, in dimension two. + +## Implementation notes + +Since mathlib's `AlgEquiv` requires associative multiplication, an automorphism is expressed +throughout as a `LinearEquiv` together with `map_one` and `map_mul`, exactly as in +`Composition/NormClassification.lean` and `Composition/Reduced/Splitness.lean`. No new predicate is +introduced. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.24, 16.4, 16.7, + 16.16, 19.3, 19.8, 23.1--23.4. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {B : Type w} [NonAssocRing B] [Module k B] [SMulCommClass k B B] [IsScalarTower k B B] + +/-! ### `GPR 23.4(a)`: isomorphisms are unital norm equivalences -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 23.4(a)`.** Every automorphism of a finitely generated projective conic algebra is a +unital norm equivalence: it preserves the norm, and hence the trace and the conjugation. + +This is the self-map case of `ConicAlgebra.norm_map_of_linearEquiv`, and it holds in every rank +and over every commutative ring, because the conic norm on such an algebra is intrinsic +(`GPR 16.7`, `GPR 19.3`). -/ +theorem norm_map_of_automorphism (C : ConicAlgebra k A) (e : A ≃ₗ[k] A) + (map_one : e (1 : A) = 1) (map_mul : ∀ x y, e (x * y) = e x * e y) (x : A) : + C.norm (e x) = C.norm x := + norm_map_of_linearEquiv C C e map_one map_mul x + +/-! ### `GPR 23.4(b)`: in the monogenic case, unital norm equivalences are multiplicative -/ + +omit [Module.Finite k A] [Module.Projective k A] in +/-- **The engine of `GPR 23.4(b)`.** If every element of `A` lies in the quadratic subalgebra +`k[u]`, then every unital norm isometry out of `C` is multiplicative. + +Multiplication in `k[u]` is the coefficient formula of `GPR 19.8`, whose only structure constants +are `t(u)` and `n(u)`; a unital norm isometry preserves the norm by hypothesis and the trace by +`GPR 23.2`, so it transports the formula. No regularity, projectivity, rank or characteristic +hypothesis is used. -/ +theorem map_mul_of_isometryEquiv_map_one_of_forall_mem_adjoinElement (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) {u : A} + (hu : ∀ x : A, x ∈ C.adjoinElement u) (x y : A) : e (x * y) = e x * e y := by + have h := adjoinElementLinearEquivOfIsometryEquiv_map_mul C D e h1 u ⟨x, hu x⟩ ⟨y, hu y⟩ + exact congrArg (fun z : D.adjoinElement (e u) ↦ (z : B)) h + +omit [Module.Finite k A] [Module.Projective k A] in +/-- **`GPR 23.4(b)`, as an isomorphism of conic algebras.** A unital norm isometry out of a +monogenic conic algebra is an isomorphism in the sense of `ConicAlgebra.Isomorphic`. -/ +theorem isomorphic_of_isometryEquiv_map_one_of_forall_mem_adjoinElement (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) {u : A} + (hu : ∀ x : A, x ∈ C.adjoinElement u) : C.Isomorphic D := + ⟨e, h1, map_mul_of_isometryEquiv_map_one_of_forall_mem_adjoinElement C D e h1 hu⟩ + +/-! ### `GPR 23.4(b)` for quadratic algebras -/ + +/-- **`GPR 23.4(b)`.** A unital norm equivalence from a quadratic algebra onto a conic algebra is +multiplicative, over an arbitrary commutative ring. + +Here `A` is finitely generated projective of constant rank two, i.e. quadratic in the sense of +`GPR 16.4`; the target `B` need only be conic, since finite generation, projectivity and rank pass +to it along `e`. The conic structures are arbitrary, which is no loss: on a finitely generated +projective algebra the conic norm is unique (`ConicAlgebra.norm_eq_of_projective`), so it is the +norm `det(L_x)` of `GPR 16.4`. + +Following `GPR`, the equation is checked at each localization `k_𝔪`, where `k_𝔪 ⊗ A = k_𝔪[u]` +(`ConicAlgebra.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two`) and +multiplication in `k_𝔪[u]` is determined by `t(u)` and `n(u)` (`GPR 19.8`), both preserved by a +unital norm equivalence (`GPR 23.2`). -/ +theorem map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) (x y : A) : e (x * y) = e x * e y := by + have : Module.Finite k B := Module.Finite.equiv e.toLinearEquiv + have : Module.Projective k B := Module.Projective.of_equiv' e.toLinearEquiv + refine eq_of_forall_localization_maximal (k := k) _ _ fun P _ ↦ ?_ + let S := Localization.AtPrime P + have hSrank := Module.rankAtStalk_baseChange_of_eq S hA + obtain ⟨u, hu⟩ := (C.baseChangeOfProjective S) + |>.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two + (isLGRing_of_isLocalRing S) hSrank + let eS := QuadraticMap.IsometryEquiv.baseChangeOfProjective (A := S) C.norm D.norm e + have h1S : eS (1 : S ⊗[k] A) = 1 := congrArg ((1 : S) ⊗ₜ[k] ·) h1 + have h := map_mul_of_isometryEquiv_map_one_of_forall_mem_adjoinElement + (C.baseChangeOfProjective S) (D.baseChangeOfProjective S) eS h1S hu (1 ⊗ₜ x) (1 ⊗ₜ y) + rw [← one_tmul_mul] at h + exact h.trans (one_tmul_mul S (e x) (e y)).symm + +/-- **`GPR 23.4(b)`, as an isomorphism.** A unital norm equivalence from a quadratic algebra onto a +conic algebra is an isomorphism of conic algebras, over an arbitrary commutative ring. -/ +theorem isomorphic_of_isometryEquiv_map_one_of_rankAtStalk_eq_two (C : ConicAlgebra k A) + (D : ConicAlgebra k B) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) + (e : C.norm.IsometryEquiv D.norm) (h1 : e (1 : A) = 1) : C.Isomorphic D := + ⟨e, h1, map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two C D hA e h1⟩ + +/-- **`GPR 23.4` for quadratic algebras, both directions.** Let `A` be finitely generated +projective of constant rank two and `e : A ≃ₗ[k] B` a linear equivalence with `e 1 = 1`. Then `e` +is multiplicative if and only if it carries the norm of `C` to the norm of `D`. + +Forwards is `GPR 23.4(a)` (`ConicAlgebra.norm_map_of_linearEquiv`) and holds in every rank; +backwards is `GPR 23.4(b)`, where rank two is used. -/ +theorem map_mul_iff_norm_map_of_rankAtStalk_eq_two (C : ConicAlgebra k A) (D : ConicAlgebra k B) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (e : A ≃ₗ[k] B) (h1 : e (1 : A) = 1) : + (∀ x y, e (x * y) = e x * e y) ↔ ∀ x, D.norm (e x) = C.norm x := + ⟨fun hmul x ↦ norm_map_of_linearEquiv C D e h1 hmul x, fun hnorm ↦ + map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two C D hA + { toLinearEquiv := e, map_app' := hnorm } h1⟩ + +/-- **`GPR 23.4(b)` for quadratic algebras as `GPR 16.4` defines them**: unital algebras that are +finitely generated projective of constant rank two, each with its conic norm — which exists by +`GPR 16.4` (`ConicAlgebra.ofRankTwo`) and is unique by `GPR 16.16` +(`ConicAlgebra.eq_ofRankTwo`). A unital norm equivalence between them is an algebra isomorphism; +no conic structure needs to be supplied. -/ +theorem map_mul_of_norm_map_of_rankAtStalk_eq_two [Module.Finite k B] [Module.Projective k B] + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) + (hB : Module.rankAtStalk (R := k) B = fun _ ↦ 2) (e : A ≃ₗ[k] B) (h1 : e (1 : A) = 1) + (hnorm : ∀ x, (ofRankTwo hB).norm (e x) = (ofRankTwo hA).norm x) (x y : A) : + e (x * y) = e x * e y := + map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two (ofRankTwo hA) (ofRankTwo hB) hA + { toLinearEquiv := e, map_app' := hnorm } h1 x y + +/-! ### The field case -/ + +section Field + +variable {K : Type u} {X : Type v} {Y : Type w} [Field K] + [NonAssocRing X] [Module K X] [SMulCommClass K X X] [IsScalarTower K X X] + [Module.Finite K X] [Module.Projective K X] + [NonAssocRing Y] [Module K Y] [SMulCommClass K Y Y] [IsScalarTower K Y Y] + +/-- **`GPR 23.4(b)` over a field.** A unital norm isometry out of a two-dimensional conic algebra +over a field is multiplicative. -/ +theorem map_mul_of_isometryEquiv_map_one_of_finrank_eq_two (E : ConicAlgebra K X) + (F : ConicAlgebra K Y) (hX : Module.finrank K X = 2) (e : E.norm.IsometryEquiv F.norm) + (h1 : e (1 : X) = 1) (x y : X) : e (x * y) = e x * e y := + map_mul_of_isometryEquiv_map_one_of_rankAtStalk_eq_two E F + (Module.rankAtStalk_eq_of_finrank_eq hX) e h1 x y + +/-- **`GPR 23.4(b)` over a field, as an isomorphism.** -/ +theorem isomorphic_of_isometryEquiv_map_one_of_finrank_eq_two (E : ConicAlgebra K X) + (F : ConicAlgebra K Y) (hX : Module.finrank K X = 2) (e : E.norm.IsometryEquiv F.norm) + (h1 : e (1 : X) = 1) : E.Isomorphic F := + ⟨e, h1, map_mul_of_isometryEquiv_map_one_of_finrank_eq_two E F hX e h1⟩ + +/-- **`GPR 23.4` over a field, both directions.** A unital linear equivalence out of a +two-dimensional conic algebra over a field is multiplicative if and only if it preserves the norm. +-/ +theorem map_mul_iff_norm_map_of_finrank_eq_two (E : ConicAlgebra K X) (F : ConicAlgebra K Y) + (hX : Module.finrank K X = 2) (e : X ≃ₗ[K] Y) (h1 : e (1 : X) = 1) : + (∀ x y, e (x * y) = e x * e y) ↔ ∀ x, F.norm (e x) = E.norm x := + map_mul_iff_norm_map_of_rankAtStalk_eq_two E F (Module.rankAtStalk_eq_of_finrank_eq hX) e h1 + +end Field + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean new file mode 100644 index 0000000000..50b9b64708 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean @@ -0,0 +1,235 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAlternative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAssociative + +/-! +# The Cayley–Dickson tower: rank 2, 4 and 8 (`GPR 19.18`) + +Iterating the Cayley–Dickson process three times from the base ring produces, for scalars +`μ₁, μ₂, μ₃ ∈ k`, conic algebras of ranks `2`, `4` and `8`: + + `Cay₂ k μ₁ = Cay(k, μ₁)`, + `Cay₄ k μ₁ μ₂ = Cay(Cay₂, μ₂)` — a quaternion algebra, + `Cay₈ k μ₁ μ₂ μ₃ = Cay(Cay₄, μ₃)` — an **octonion algebra**, which mathlib does + not have. + +Everything is over an arbitrary commutative ring `k`, with arbitrary scalars; the hypotheses +`2 ∈ kˣ` and `μᵢ ∈ kˣ` appear only on the theorem that the tower consists of *composition* +algebras. + +## Why the tower stops at 8 + +Each rung is built by a theorem whose hypothesis is a property of the rung below. +`ConicAlgebra.mul_comm_cay` needs its input's conjugation to be the identity, which holds for the +base ring; `ConicAlgebra.mul_assoc_cay` needs its input commutative; and +`ConicAlgebra.isMultiplicative_cay` (`GPR Exc. 18.18`) and `ConicAlgebra.isAlternative_cay` +(`GPR 18.14(c)`) need it associative. So each property may be lost one rung after the property +that implies it, and the fourth double — the **sedenions** — is in general neither alternative +nor +multiplicative. That is the mechanism behind the rank dichotomy `1, 2, 4, 8` of `GPR 19.18`. + +What is proved *positively* here is that `Cay₂` is commutative, `Cay₄` is associative, and +`Cay₈` +is alternative with multiplicative norm — each over an arbitrary base. + +⚠ The *negative* half is genuinely characteristic-dependent and is therefore **not** stated in +this file. Over a base in which `2 = 0` the conjugation of `Cay₂` is again the identity, so +`ConicAlgebra.mul_comm_cay` applies once more and the tower stays commutative — the ranks still +double, but the algebras do not become non-commutative and then non-associative in the classical +way. The explicit witnesses that `ℍ` is not commutative and `𝕆` is not associative are proved +over +`ℝ` in `Composition/Examples.lean`, from the general +`ConicAlgebra.exists_mul_ne_mul_cay` and `ConicAlgebra.exists_mul_mul_ne_mul_mul_cay`. + +Once such a witness is in hand for a rung, `ConicAlgebra.not_isAlternative_cay_of_mul_mul_ne` — +the converse half of `GPR 18.14(c)` — turns it into the failure of alternativity one rung up, with +no hypothesis on the scalar. That is the route to the sedenions of `GPR 19.23`. + +## Main definitions + +* `ConicAlgebra.Cay₂`, `ConicAlgebra.Cay₄`, `ConicAlgebra.Cay₈` : the underlying modules. +* `ConicAlgebra.cay₂`, `ConicAlgebra.cay₄`, `ConicAlgebra.cay₈` : their conic structures. +* `ConicAlgebra.Octonion`, `ConicAlgebra.octonion` : notation for the rank-8 case. + +## Main results + +* `ConicAlgebra.isMultiplicative_cay₈` : the octonion norm permits composition. +* `ConicAlgebra.isAlternative_cay₈` : octonion algebras are alternative (directly, from + `GPR 18.14(c)`, without going through `GPR 19.3`). +* `ConicAlgebra.isComposition_cay₈` : for `2 ∈ kˣ` and `μᵢ` units, the octonion algebra is a + composition algebra; likewise `isComposition_cay₂` and `isComposition_cay₄`. +* `ConicAlgebra.finrank_cay₂`, `.finrank_cay₄`, `.finrank_cay₈` : the ranks are `2`, `4`, `8`. + +## Implementation notes + +The `Ring`, `CommRing` and `Algebra` structures on the rungs are declared as **genuine instances** +here, unlike the `def`s they come from in `Conic/CayleyDicksonAssociative.lean`: at each rung the +side conditions are discharged by theorems (`ConicAlgebra.baseRing_conj_apply` at the bottom, +`ConicAlgebra.ConjIsInvolution.cay` above it) rather than assumed, so there is nothing for instance +search to guess. This is what makes the tower usable without `letI` at every step. + +⚠ `Cay₄` is **not** mathlib's `QuaternionAlgebra`, and the two are incomparable in general — +see +overview trap 3. `QuaternionAlgebra` takes arbitrary structure constants and always produces a +*free* module; `Cay₄` produces a composition algebra exactly under the hypotheses below. Relating +them is the job of a later file. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.14, Exc. 18.18, + 19.18. +-/ + +@[expose] public section + +universe u + +namespace ConicAlgebra + +variable (k : Type u) [CommRing k] (μ₁ μ₂ μ₃ : k) + +/-! ### Rank 2 -/ + +/-- The **rank-2** Cayley–Dickson algebra `Cay(k, μ₁)`, as a `k`-module. -/ +abbrev Cay₂ : Type u := Cay (baseRing k) μ₁ + +/-- The conic structure on `Cay₂`, i.e. `GPR 18.4` applied to the base ring. -/ +noncomputable abbrev cay₂ : ConicAlgebra k (Cay₂ k μ₁) := (baseRing k).cay μ₁ + +/-- `Cay₂` is **commutative**: the conjugation of the base ring is the identity +(`ConicAlgebra.baseRing_conj_apply`), which is exactly the hypothesis of +`ConicAlgebra.mul_comm_cay`. This is the last commutative rung. -/ +noncomputable instance : CommRing (Cay₂ k μ₁) := + Cay.commRing (baseRing k) μ₁ (baseRing_conj_apply k) + +noncomputable instance : Algebra k (Cay₂ k μ₁) := + Cay.algebra (baseRing k) μ₁ (conjIsInvolution_of_conj_eq_id _ (baseRing_conj_apply k)) + +theorem conjIsInvolution_cay₂ : (cay₂ k μ₁).ConjIsInvolution := + ConjIsInvolution.cay (conjIsInvolution_of_conj_eq_id _ (baseRing_conj_apply k)) + +/-- The rank-2 norm is multiplicative: `GPR Exc. 18.18` applied to the base ring, which is +associative +with multiplicative norm. -/ +theorem isMultiplicative_cay₂ : (cay₂ k μ₁).IsMultiplicative := + isMultiplicative_cay (baseRing k) μ₁ (isMultiplicative_baseRing k) + +/-! ### Rank 4 -/ + +/-- The **rank-4** Cayley–Dickson algebra `Cay(Cay(k, μ₁), μ₂)` — a quaternion algebra. + +⚠ Not mathlib's `QuaternionAlgebra`; see the module docstring. -/ +abbrev Cay₄ : Type u := Cay (cay₂ k μ₁) μ₂ + +/-- The conic structure on `Cay₄`. -/ +noncomputable abbrev cay₄ : ConicAlgebra k (Cay₄ k μ₁ μ₂) := (cay₂ k μ₁).cay μ₂ + +/-- `Cay₄` is **associative**, by `GPR 18.14(b)` applied to the commutative `Cay₂`. It is the +last +associative rung, which is why the tower produces composition algebras only up to rank 8. -/ +noncomputable instance : Ring (Cay₄ k μ₁ μ₂) := + Cay.ring (cay₂ k μ₁) μ₂ (conjIsInvolution_cay₂ k μ₁) + +noncomputable instance : Algebra k (Cay₄ k μ₁ μ₂) := + Cay.algebra (cay₂ k μ₁) μ₂ (conjIsInvolution_cay₂ k μ₁) + +theorem conjIsInvolution_cay₄ : (cay₄ k μ₁ μ₂).ConjIsInvolution := + ConjIsInvolution.cay (conjIsInvolution_cay₂ k μ₁) + +theorem isMultiplicative_cay₄ : (cay₄ k μ₁ μ₂).IsMultiplicative := + isMultiplicative_cay (cay₂ k μ₁) μ₂ (isMultiplicative_cay₂ k μ₁) + +/-! ### Rank 8: octonion algebras -/ + +/-- The **rank-8** Cayley–Dickson algebra `Cay(Cay(Cay(k, μ₁), μ₂), μ₃)`: an +**octonion algebra**. +mathlib has no octonions, so this is the definition of record here. -/ +abbrev Cay₈ : Type u := Cay (cay₄ k μ₁ μ₂) μ₃ + +/-- The conic structure on `Cay₈`. -/ +noncomputable abbrev cay₈ : ConicAlgebra k (Cay₈ k μ₁ μ₂ μ₃) := + (cay₄ k μ₁ μ₂).cay μ₃ + +/-- The underlying module of an octonion algebra, under its usual name. -/ +abbrev Octonion : Type u := Cay₈ k μ₁ μ₂ μ₃ + +/-- An octonion algebra, under its usual name. -/ +noncomputable abbrev octonion : ConicAlgebra k (Octonion k μ₁ μ₂ μ₃) := + cay₈ k μ₁ μ₂ μ₃ + +theorem conjIsInvolution_cay₈ : (cay₈ k μ₁ μ₂ μ₃).ConjIsInvolution := + ConjIsInvolution.cay (conjIsInvolution_cay₄ k μ₁ μ₂) + +/-- **Octonion algebras are alternative** — `GPR 18.14(c)` applied to the associative `Cay₄`. + +This is a *direct* proof, independent of `GPR 19.3`: it needs no regularity of the norm, no +hypothesis on `2`, and no hypothesis on the `μᵢ`, whereas the general +`ConicAlgebra.IsComposition.isAlternative` needs the norm's radical to vanish. -/ +instance isAlternative_cay₈ : IsAlternative (Cay₈ k μ₁ μ₂ μ₃) := + isAlternative_cay (cay₄ k μ₁ μ₂) μ₃ (conjIsInvolution_cay₄ k μ₁ μ₂) + +/-- **The octonion norm permits composition**, `n(xy) = n(x)n(y)` — `GPR Exc. 18.18` applied to the +associative `Cay₄`. Again no hypothesis on `2` or on the `μᵢ`. + +This is the last rung for which it holds: `Cay₈` is not associative, so `GPR Exc. 18.18` does not +apply +to it, and the sedenions `Cay(Cay₈, μ₄)` are not multiplicative. -/ +theorem isMultiplicative_cay₈ : (cay₈ k μ₁ μ₂ μ₃).IsMultiplicative := + isMultiplicative_cay (cay₄ k μ₁ μ₂) μ₃ (isMultiplicative_cay₄ k μ₁ μ₂) + +/-! ### The ranks are `2`, `4`, `8` + +`ConicAlgebra.Cay.finrank_cay` doubles the rank at each step, starting from `finrank k k = 1`. +These need `k` nontrivial (otherwise `finrank` is `0` throughout) but nothing else — no unit +scalars, no hypothesis on `2`, and no composition. -/ + +section Rank + +variable [Nontrivial k] + +@[simp] theorem finrank_cay₂ : Module.finrank k (Cay₂ k μ₁) = 2 := by + rw [Cay.finrank_cay, Module.finrank_self] + +@[simp] theorem finrank_cay₄ : Module.finrank k (Cay₄ k μ₁ μ₂) = 4 := by + rw [Cay.finrank_cay, finrank_cay₂] + +/-- **An octonion algebra has rank 8.** -/ +@[simp] theorem finrank_cay₈ : Module.finrank k (Cay₈ k μ₁ μ₂ μ₃) = 8 := by + rw [Cay.finrank_cay, finrank_cay₄] + +end Rank + +/-! ### The tower consists of composition algebras + +Here, and only here, the scalars must be units and `2` must be invertible. The hypothesis on `2` +is what turns non-singularity of each norm into the *regularity* that +`ConicAlgebra.IsComposition.cay` consumes; without it the very first rung already fails, since +`Cay(k, μ)` in characteristic 2 is inseparable and not a composition algebra. -/ + +section Composition + +variable [Invertible (2 : k)] + +theorem isComposition_cay₂ (h₁ : IsUnit μ₁) : (cay₂ k μ₁).IsComposition.{u, u, u} := + IsComposition.cay_of_invertible_two _ h₁ (isComposition_baseRing k) + +theorem isComposition_cay₄ (h₁ : IsUnit μ₁) (h₂ : IsUnit μ₂) : + (cay₄ k μ₁ μ₂).IsComposition.{u, u, u} := + IsComposition.cay_of_invertible_two _ h₂ (isComposition_cay₂ k μ₁ h₁) + +/-- **An octonion algebra with unit scalars, over a base in which `2` is invertible, is a +composition algebra.** -/ +theorem isComposition_cay₈ (h₁ : IsUnit μ₁) (h₂ : IsUnit μ₂) (h₃ : IsUnit μ₃) : + (cay₈ k μ₁ μ₂ μ₃).IsComposition.{u, u, u} := + IsComposition.cay_of_invertible_two _ h₃ (isComposition_cay₄ k μ₁ μ₂ h₁ h₂) + +end Composition + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticEtale.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticEtale.lean new file mode 100644 index 0000000000..876fcd94da --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticEtale.lean @@ -0,0 +1,444 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra +public import Mathlib.Algebra.QuadraticAlgebra.Basic +public import Mathlib.Algebra.QuadraticAlgebra.Discriminant + +/-! +# A quadratic algebra is a conic algebra, and is composition exactly when étale (`GPR 19.8`) + +Everything in `Composition/QuadraticSubalgebra.lean` builds the quadratic algebra `k[u]` *inside* +an ambient conic algebra, so its norm and trace are inherited rather than constructed. This file +supplies the missing standalone direction: given a commutative `k`-algebra `L` whose underlying +module is free on `1` and a single element `u`, with + + `u² = t·u − n₀·1`, + +there is a conic structure on `L` with `t(u) = t` and `n(u) = n₀`, its norm is multiplicative, and +it is a composition algebra exactly when the discriminant `t² − 4n₀` is a unit — that is, exactly +when `L` is quadratic **étale**. + +Without this, the only rank-two composition algebra available as an object in its own right is the +split one `k × k` (`Composition/Reduced/Split.lean`), and `Cay(k, μ)`, which needs `2 ∈ kˣ` and +only reaches the presentations with `t = 0`. + +## Main definitions + +* `ConicAlgebra.quadraticCoeffNorm t n₀` : the form `(a, b) ↦ a² + t·ab + n₀·b²` on `k²`. +* `ConicAlgebra.IsQuadraticAlgebra u t n₀` : the data above — `u² = t·u − n₀·1`, and `(a, b) ↦ + a·1 + b·u` a bijection. +* `ConicAlgebra.IsQuadraticAlgebra.conic` : the resulting conic algebra. +* `ConicAlgebra.IsQuadraticAlgebra.quadraticAlgebraEquiv` : `QuadraticAlgebra k (-n₀) t ≃ₐ[k] L`, + `ω ↦ u` — the presentation identifies `L` with mathlib's model quadratic algebra. + +## Main results + +* `ConicAlgebra.IsQuadraticAlgebra.isMultiplicative_conic` : the norm permits composition + (`GPR 19.8(i)`). +* `ConicAlgebra.IsQuadraticAlgebra.isGPRRegular_conic_iff` : regularity of the norm is exactly + invertibility of the discriminant (`GPR 19.8(iii)`). +* `ConicAlgebra.IsQuadraticAlgebra.isComposition_conic` : **a quadratic étale algebra is a + composition algebra of rank two**. +* `ConicAlgebra.IsQuadraticAlgebra.finrank_eq_two`, `.rankAtStalk_eq_two` : its rank. +* `ConicAlgebra.exists_isQuadraticAlgebra_of_finrank_eq_two` : over a field, every commutative + algebra of dimension two admits such a presentation. +* `ConicAlgebra.IsQuadraticAlgebra.norm_quadraticAlgebraEquiv`, `.trace_quadraticAlgebraEquiv` : + the conic norm and trace are mathlib's `QuadraticAlgebra.norm` and `QuadraticAlgebra.trace`, and + `.isGPRRegular_conic_iff_isUnit_discr` restates `GPR 19.8(iii)` with mathlib's + `QuadraticAlgebra.discr`. +* `ConicAlgebra.isQuadraticAlgebra_omega` : conversely, mathlib's `QuadraticAlgebra k a b` is a + quadratic algebra in this sense, generated by `ω`. + +## Implementation notes + +The norm is *defined* by transporting the coefficient form `quadraticCoeffNorm` along the given +bijection, rather than by a formula on `L`; this is what makes the degree-two identity and +multiplicativity two-variable polynomial identities that `ring` discharges. + +Once the conic algebra exists, the ambient machinery applies to it with no duplication: the +discriminant criterion is `ConicAlgebra.normOnSpan_isGPRRegular_iff_isUnit_discriminant` read at +`C := h.conic`, since `h.conic.normOnSpan u` is `quadraticCoeffNorm t n₀` on the nose. + +⚠ **`t` is not `2a` for some `a`.** The presentation carries the *un-halved* trace, so the +characteristic-two case — where the discriminant is `t²` and étale means `t` invertible — is +included. Writing the norm as `(a + t b/2)² − (t² − 4n₀) b²/4` would need `2 ∈ kˣ` and would lose +exactly the separable quadratic extensions of a field of characteristic two. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.8. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section CoeffNorm + +variable (k : Type u) [CommRing k] + +/-- The quadratic form `(a, b) ↦ a² + t·ab + n₀·b²` on `k²`, in the coefficient coordinates of +`a·1 + b·u`. -/ +def quadraticCoeffNorm (t n₀ : k) : QuadraticForm k (k × k) := + QuadraticMap.linMulLin (LinearMap.fst k k k) (LinearMap.fst k k k) + + t • QuadraticMap.linMulLin (LinearMap.fst k k k) (LinearMap.snd k k k) + + n₀ • QuadraticMap.linMulLin (LinearMap.snd k k k) (LinearMap.snd k k k) + +variable {k} + +@[simp] theorem quadraticCoeffNorm_apply (t n₀ : k) (p : k × k) : + quadraticCoeffNorm k t n₀ p = p.1 * p.1 + t * (p.1 * p.2) + n₀ * (p.2 * p.2) := by + simp only [quadraticCoeffNorm, add_apply, smul_apply, + QuadraticMap.linMulLin_apply, LinearMap.fst_apply, LinearMap.snd_apply, smul_eq_mul] + +theorem polar_quadraticCoeffNorm (t n₀ : k) (p q : k × k) : + QuadraticMap.polar (quadraticCoeffNorm k t n₀) p q = + 2 * (p.1 * q.1) + t * (p.1 * q.2 + p.2 * q.1) + n₀ * (2 * (p.2 * q.2)) := by + simp only [QuadraticMap.polar, quadraticCoeffNorm_apply, Prod.fst_add, Prod.snd_add] + ring + +end CoeffNorm + +section Quadratic + +variable {k : Type u} {L : Type v} [CommRing k] [CommRing L] [Algebra k L] + +/-- **The data of a quadratic `k`-algebra (`GPR 19.8`)**: an element `u` whose square is the +prescribed combination `t·u − n₀·1`, and for which `(a, b) ↦ a·1 + b·u` is a bijection `k² ≃ L`. + +The second clause is `GPR 19.8(ii)`: `L` is free with basis `(1, u)`. No regularity is assumed — +that is the discriminant condition, and it is what separates étale from inseparable. -/ +structure IsQuadraticAlgebra (u : L) (t n₀ : k) : Prop where + /-- The generator satisfies its monic quadratic relation. -/ + mul_self_gen : u * u = t • u - n₀ • (1 : L) + /-- `(1, u)` is a basis of `L` over `k`. -/ + bijective_spanOne : Function.Bijective (spanOne k u) + +namespace IsQuadraticAlgebra + +variable {u : L} {t n₀ : k} (h : IsQuadraticAlgebra u t n₀) + +/-- The coefficient isomorphism `k² ≃ L`, `(a, b) ↦ a·1 + b·u`. -/ +noncomputable def equivCoeff : (k × k) ≃ₗ[k] L := + LinearEquiv.ofBijective (spanOne k u) h.bijective_spanOne + +@[simp] theorem equivCoeff_apply (p : k × k) : h.equivCoeff p = p.1 • (1 : L) + p.2 • u := rfl + +include h in +/-- Multiplication in coefficient coordinates, from the defining relation alone. -/ +theorem spanOne_mul_gen (p q : k × k) : + (spanOne k u p) * (spanOne k u q) = + spanOne k u (p.1 * q.1 - p.2 * q.2 * n₀, p.1 * q.2 + p.2 * q.1 + p.2 * q.2 * t) := by + simp only [spanOne_apply, add_mul, mul_add, smul_mul_assoc, mul_smul_comm, one_mul, mul_one, + h.mul_self_gen] + module + +/-- The norm of the quadratic algebra, transported from the coefficient form. -/ +noncomputable def norm : QuadraticForm k L := + (quadraticCoeffNorm k t n₀).comp h.equivCoeff.symm.toLinearMap + +theorem norm_spanOne (p : k × k) : + h.norm (spanOne k u p) = p.1 * p.1 + t * (p.1 * p.2) + n₀ * (p.2 * p.2) := by + change (quadraticCoeffNorm k t n₀).comp h.equivCoeff.symm.toLinearMap (spanOne k u p) = _ + rw [QuadraticMap.comp_apply] + change quadraticCoeffNorm k t n₀ (h.equivCoeff.symm (h.equivCoeff p)) = _ + rw [h.equivCoeff.symm_apply_apply, quadraticCoeffNorm_apply] + +theorem polar_norm_spanOne (p q : k × k) : + QuadraticMap.polar h.norm (spanOne k u p) (spanOne k u q) = + 2 * (p.1 * q.1) + t * (p.1 * q.2 + p.2 * q.1) + n₀ * (2 * (p.2 * q.2)) := by + rw [QuadraticMap.polar, ← map_add, h.norm_spanOne, h.norm_spanOne, h.norm_spanOne] + simp only [Prod.fst_add, Prod.snd_add] + ring + +theorem norm_one_eq : h.norm (1 : L) = 1 := by + rw [show (1 : L) = spanOne k u (1, 0) by simp, h.norm_spanOne] + ring + +theorem polar_norm_one_spanOne (p : k × k) : + QuadraticMap.polar h.norm 1 (spanOne k u p) = 2 * p.1 + t * p.2 := by + rw [show (1 : L) = spanOne k u (1, 0) by simp, h.polar_norm_spanOne] + ring + +/-- **`GPR 19.8`: a quadratic algebra is a conic algebra.** The degree-two identity is the +defining relation, written in coefficient coordinates. -/ +noncomputable def conic : ConicAlgebra k L where + norm := h.norm + norm_one := h.norm_one_eq + mul_self x := by + obtain ⟨p, rfl⟩ := h.bijective_spanOne.2 x + rw [h.spanOne_mul_gen p p, h.polar_norm_one_spanOne, h.norm_spanOne] + simp only [spanOne_apply] + match_scalars <;> ring + +@[simp] theorem conic_norm : h.conic.norm = h.norm := rfl + +theorem conic_norm_spanOne (p : k × k) : + h.conic.norm (spanOne k u p) = p.1 * p.1 + t * (p.1 * p.2) + n₀ * (p.2 * p.2) := + h.norm_spanOne p + +include h in +@[simp] theorem trace_conic_gen : h.conic.trace u = t := by + have key := h.polar_norm_spanOne (1, 0) (0, 1) + rw [show spanOne k u ((1 : k), (0 : k)) = (1 : L) by simp, + show spanOne k u ((0 : k), (1 : k)) = u by simp] at key + rw [trace_apply, conic_norm, key] + ring + +include h in +theorem norm_conic_gen : h.conic.norm u = n₀ := by + have key := h.norm_spanOne (0, 1) + rw [show spanOne k u ((0 : k), (1 : k)) = u by simp] at key + rw [conic_norm, key] + ring + +/-! ### Multiplicativity -/ + +include h in +/-- **`GPR 19.8(i)`.** The norm of a quadratic algebra permits composition, with no hypothesis on +the discriminant: it is the two-variable identity `n(xy) = n(x)n(y)` for the binary form +`a² + t·ab + n₀·b²`. -/ +theorem isMultiplicative_conic : h.conic.IsMultiplicative := by + intro x y + obtain ⟨p, rfl⟩ := h.bijective_spanOne.2 x + obtain ⟨q, rfl⟩ := h.bijective_spanOne.2 y + rw [h.spanOne_mul_gen p q, h.conic_norm_spanOne, h.conic_norm_spanOne, h.conic_norm_spanOne] + ring + +/-! ### Regularity and the discriminant -/ + +include h in +@[simp] theorem normOnSpan_conic : h.conic.normOnSpan u = quadraticCoeffNorm k t n₀ := by + ext p + change h.conic.norm (spanOne k u p) = _ + rw [h.conic_norm_spanOne, quadraticCoeffNorm_apply] + +include h in +@[simp] theorem elementDiscriminant_conic : + h.conic.elementDiscriminant u = t ^ 2 - 4 * n₀ := by + change h.conic.trace u ^ 2 - 4 * h.conic.norm u = _ + rw [h.trace_conic_gen, h.norm_conic_gen] + +include h in +/-- **`GPR 19.8(iii)`.** The norm of a quadratic algebra is regular exactly when the discriminant +`t² − 4n₀` is a unit — that is, exactly when the algebra is quadratic étale. -/ +theorem isGPRRegular_conic_iff : h.conic.norm.IsGPRRegular ↔ IsUnit (t ^ 2 - 4 * n₀) := by + rw [conic_norm, norm, QuadraticForm.isGPRRegular_comp_linearEquiv_iff, ← h.normOnSpan_conic, + h.conic.normOnSpan_isGPRRegular_iff_isUnit_discriminant u, h.elementDiscriminant_conic] + +/-! ### Rank -/ + +include h in +theorem module_free : Module.Free k L := Module.Free.of_equiv h.equivCoeff + +include h in +theorem module_finite : Module.Finite k L := Module.Finite.equiv h.equivCoeff + +include h in +/-- The generator lies outside `k · 1`: otherwise `(d, -1)` would be a nonzero element of the +kernel of the coefficient map. -/ +theorem ne_smul_one [Nontrivial k] (d : k) : u ≠ d • (1 : L) := by + intro hd + have h0 : spanOne k u ((d, -1) : k × k) = spanOne k u 0 := by + simp only [spanOne_apply, map_zero] + rw [hd] + module + have hneg : (-1 : k) = 0 := congrArg Prod.snd (h.bijective_spanOne.1 h0) + exact one_ne_zero (neg_eq_zero.mp hneg) + +include h in +theorem finrank_eq_two [Nontrivial k] : Module.finrank k L = 2 := by + rw [← LinearEquiv.finrank_eq h.equivCoeff, Module.finrank_prod, Module.finrank_self] + +include h in +theorem rankAtStalk_eq_two [Nontrivial k] : Module.rankAtStalk (R := k) L = fun _ ↦ 2 := + Module.rankAtStalk_eq_of_equiv h.equivCoeff.symm |>.trans (by + rw [Module.rankAtStalk_prod, Module.rankAtStalk_self] + rfl) + +include h in +/-- **A quadratic étale algebra is a composition algebra of rank two.** Non-singularity comes from +regularity of the norm (`GN (C.8.1)`), which by `GPR 19.8(iii)` is invertibility of the +discriminant; multiplicativity is unconditional. -/ +theorem isComposition_conic [Module.Finite k L] [Module.Projective k L] + (hdisc : IsUnit (t ^ 2 - 4 * n₀)) : h.conic.IsComposition.{u, v, u} := + ⟨((h.isGPRRegular_conic_iff).mpr hdisc).isGPRNonsingular, h.isMultiplicative_conic⟩ + +/-! ### mathlib's `QuadraticAlgebra` + +mathlib's `QuadraticAlgebra k a b` is the model quadratic algebra, `k ⊕ k ω` with `ω² = a + b ω`. +A presentation `u² = t u - n₀` with basis `(1, u)` says exactly that `L` is +`QuadraticAlgebra k (-n₀) t`, with `ω ↦ u`; the conic norm and trace are then mathlib's. -/ + +include h in +/-- The defining relation in the shape `QuadraticAlgebra.lift` asks for: `u² = (-n₀)·1 + t·u`. -/ +theorem mul_self_gen_eq_add : u * u = (-n₀) • (1 : L) + t • u := by + rw [h.mul_self_gen, neg_smul] + abel + +/-- **`L` is mathlib's `QuadraticAlgebra k (-n₀) t`**, by the algebra map sending `ω` to `u` +(`QuadraticAlgebra.lift`). It is bijective because `(1, u)` is a basis. -/ +noncomputable def quadraticAlgebraEquiv : QuadraticAlgebra k (-n₀) t ≃ₐ[k] L := + AlgEquiv.ofBijective (QuadraticAlgebra.lift ⟨u, h.mul_self_gen_eq_add⟩) <| by + have : ⇑(QuadraticAlgebra.lift ⟨u, h.mul_self_gen_eq_add⟩) = + h.equivCoeff ∘ QuadraticAlgebra.equivProd (-n₀) t := rfl + rw [this] + exact h.equivCoeff.bijective.comp (QuadraticAlgebra.equivProd (-n₀) t).bijective + +@[simp] theorem quadraticAlgebraEquiv_apply (z : QuadraticAlgebra k (-n₀) t) : + h.quadraticAlgebraEquiv z = z.re • (1 : L) + z.im • u := + rfl + +theorem quadraticAlgebraEquiv_omega : + h.quadraticAlgebraEquiv QuadraticAlgebra.omega = u := by + simp + +/-- Under `quadraticAlgebraEquiv`, the conic norm is mathlib's `QuadraticAlgebra.norm`. -/ +theorem norm_quadraticAlgebraEquiv (z : QuadraticAlgebra k (-n₀) t) : + h.conic.norm (h.quadraticAlgebraEquiv z) = QuadraticAlgebra.norm z := by + rw [show h.quadraticAlgebraEquiv z = spanOne k u (z.re, z.im) from rfl, h.conic_norm_spanOne, + QuadraticAlgebra.norm_def] + ring + +/-- Under `quadraticAlgebraEquiv`, the conic trace is mathlib's `QuadraticAlgebra.trace`. -/ +theorem trace_quadraticAlgebraEquiv (z : QuadraticAlgebra k (-n₀) t) : + h.conic.trace (h.quadraticAlgebraEquiv z) = QuadraticAlgebra.trace z := by + rw [show h.quadraticAlgebraEquiv z = spanOne k u (z.re, z.im) from rfl, trace_apply, + conic_norm, h.polar_norm_one_spanOne, QuadraticAlgebra.trace_def] + +include h in +/-- **`GPR 19.8(iii)` in mathlib's terms**: the norm is regular exactly when mathlib's +discriminant `QuadraticAlgebra.discr (-n₀) t = t² - 4n₀` is a unit. -/ +theorem isGPRRegular_conic_iff_isUnit_discr : + h.conic.norm.IsGPRRegular ↔ IsUnit (QuadraticAlgebra.discr (-n₀) t) := by + rw [h.isGPRRegular_conic_iff, QuadraticAlgebra.discr_def] + ring_nf + +end IsQuadraticAlgebra + +/-- Conversely, **mathlib's `QuadraticAlgebra k a b` is a quadratic algebra** in the sense of +`IsQuadraticAlgebra`, generated by `ω` with trace `b` and norm `-a`. -/ +theorem isQuadraticAlgebra_omega (a b : k) : + IsQuadraticAlgebra (QuadraticAlgebra.omega : QuadraticAlgebra k a b) b (-a) where + mul_self_gen := by + rw [QuadraticAlgebra.omega_mul_omega_eq_add, neg_smul, sub_neg_eq_add, add_comm] + bijective_spanOne := by + have : ⇑(spanOne k (QuadraticAlgebra.omega : QuadraticAlgebra k a b)) = + (QuadraticAlgebra.equivProd a b).symm := by + funext p + ext <;> simp [QuadraticAlgebra.re_one, QuadraticAlgebra.im_one] + rw [this] + exact (QuadraticAlgebra.equivProd a b).symm.bijective + +end Quadratic + +/-! ### Every two-dimensional commutative algebra over a field is quadratic -/ + +section Field + +variable {K : Type u} {L : Type v} [Field K] [CommRing L] [Algebra K L] [Nontrivial L] + +/-- Over a field, a commutative algebra of dimension two is a quadratic algebra: any element +outside `K · 1` generates, and its square is a combination of `1` and itself. -/ +theorem exists_isQuadraticAlgebra_of_finrank_eq_two (h : Module.finrank K L = 2) : + ∃ (u : L) (t n₀ : K), IsQuadraticAlgebra u t n₀ := by + have : FiniteDimensional K L := Module.finite_of_finrank_pos (by omega) + -- An element outside `K · 1` exists because the dimension exceeds one. + obtain ⟨u, hu⟩ : ∃ u : L, ∀ d : K, u ≠ d • (1 : L) := by + by_contra hcon + have hall : ∀ x : L, ∃ d : K, x = d • (1 : L) := by + intro x + by_contra hx + exact hcon ⟨x, fun d hd ↦ hx ⟨d, hd⟩⟩ + exact absurd (finrank_le_one_of_forall_exists_smul (1 : L) hall) (by omega) + -- `spanOne K u` is injective, hence bijective by equality of dimensions. + have hinj : Function.Injective (spanOne K u) := by + rw [injective_iff_map_eq_zero] + rintro ⟨a, b⟩ hab + rw [spanOne_apply] at hab + rcases eq_or_ne b 0 with rfl | hb + · rw [zero_smul, add_zero, smul_eq_zero] at hab + rcases hab with rfl | h1 + · rfl + · exact absurd h1 one_ne_zero + · refine absurd ?_ (hu (-(b⁻¹ * a))) + have hbu : b • u = (-a) • (1 : L) := by + linear_combination (norm := module) hab + calc u = b⁻¹ • (b • u) := by rw [smul_smul, inv_mul_cancel₀ hb, one_smul] + _ = b⁻¹ • ((-a) • (1 : L)) := by rw [hbu] + _ = (-(b⁻¹ * a)) • (1 : L) := by rw [smul_smul]; ring_nf + have hbij : Function.Bijective (spanOne K u) := + ⟨hinj, (LinearMap.injective_iff_surjective_of_finrank_eq_finrank (by simp [h])).mp hinj⟩ + -- The square of `u` lies in `K · 1 + K · u`, which supplies the structure constants. + obtain ⟨p, hp⟩ := hbij.2 (u * u) + exact ⟨u, p.2, -p.1, ⟨by rw [← hp, spanOne_apply]; module, hbij⟩⟩ + +end Field + +/-! ### Quadratic field extensions -/ + +section Extension + +variable {K : Type u} {M : Type v} [Field K] [Field M] [Algebra K M] + {u : M} {t n₀ : K} + +/-- **The discriminant of a quadratic field extension is a unit.** If it vanished, `u` would be a +double root: `u − c·1` would square to zero, hence vanish, putting `u` in `K · 1`. + +The hypothesis is consumed **only in characteristic two**, where the vanishing discriminant is +`t²` and the missing scalar `c` is a square root of `n₀`. In every other characteristic `c = t/2` +is available outright. -/ +theorem IsQuadraticAlgebra.isUnit_discriminant_of_field (h : IsQuadraticAlgebra u t n₀) + (hsq : (2 : K) = 0 → ∀ c : K, ∃ d : K, d * d = c) : IsUnit (t ^ 2 - 4 * n₀) := by + rw [isUnit_iff_ne_zero] + intro hzero + obtain ⟨c, htc, hcn⟩ : ∃ c : K, t = 2 * c ∧ c * c = n₀ := by + rcases eq_or_ne (2 : K) 0 with h2 | h2 + · have ht : t = 0 := by + have hsq0 : t * t = 0 := by linear_combination hzero + (2 * n₀ - t ^ 2 / 2 * 0) * h2 + exact mul_self_eq_zero.mp hsq0 + obtain ⟨d, hd⟩ := hsq h2 n₀ + exact ⟨d, by rw [ht, h2]; ring, hd⟩ + · refine ⟨t / 2, by field_simp, ?_⟩ + field_simp + linear_combination hzero + have hexp : + (u - c • (1 : M)) * (u - c • (1 : M)) = + (t - 2 * c) • u + (c * c - n₀) • (1 : M) := by + simp only [sub_mul, mul_sub, smul_mul_assoc, mul_smul_comm, one_mul, mul_one, h.mul_self_gen] + module + have hnil : (u - c • (1 : M)) * (u - c • (1 : M)) = 0 := by + rw [hexp, htc, hcn] + simp + exact h.ne_smul_one c (by + have := mul_self_eq_zero.mp hnil + linear_combination (norm := module) this) + +/-- Over a finite field of characteristic two every element is a square: squaring is injective, +because `(a − b)² = a² + b²` there, and an injective self-map of a finite type is surjective. -/ +theorem exists_mul_self_eq_of_finite [Finite K] (h2 : (2 : K) = 0) (c : K) : + ∃ d : K, d * d = c := by + have hinj : Function.Injective (fun x : K ↦ x * x) := by + intro a b hab + simp only at hab + have : (a - b) * (a - b) = 0 := by linear_combination hab + (b * (b - a)) * h2 + exact sub_eq_zero.mp (mul_self_eq_zero.mp this) + exact Finite.injective_iff_surjective.mp hinj c + +/-- **The discriminant of a quadratic extension of a finite field is a unit**, in every +characteristic. This is the separability of finite field extensions, in the only form the conic +structure needs. -/ +theorem IsQuadraticAlgebra.isUnit_discriminant_of_finite [Finite K] + (h : IsQuadraticAlgebra u t n₀) : IsUnit (t ^ 2 - 4 * n₀) := + h.isUnit_discriminant_of_field fun h2 ↦ exists_mul_self_eq_of_finite h2 + +end Extension + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticSubalgebra.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticSubalgebra.lean new file mode 100644 index 0000000000..a42471b201 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/QuadraticSubalgebra.lean @@ -0,0 +1,613 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.Conic.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ConstantRank +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Subalgebra +public import Mathlib.RingTheory.Flat.LocallyFree + +/-! +# Quadratic subalgebras generated by one element (`GPR 19.8`) + +For an element `u` of a conic algebra, the submodule `k · 1 + k · u` is closed under +multiplication because `u² = t(u)u - n(u)1`. This is the unital subalgebra denoted `k[u]` in +`GPR 19.8`. + +The discriminant `t(u)² - 4n(u)` controls whether `(1,u)` is a basis. If it is a unit, applying +the polar form at `1` and at `u` to a relation `a·1 + b·u = 0` gives a two-by-two linear system +whose determinant is the negative discriminant, forcing `a = b = 0`. + +## Main definitions + +* `ConicAlgebra.spanOne` : the linear map `(a,b) ↦ a·1 + b·u`. +* `ConicAlgebra.adjoinElement` : the unital non-associative subalgebra `k[u]`. +* `ConicAlgebra.normOnSpan` : the norm on `k·1 + k·u`, in coefficient coordinates. +* `ConicAlgebra.conicAdjoinElement` : the restricted conic structure on `k[u]`. +* `ConicAlgebra.RegularRankTwoCompositionStructure` : a witnessing abstract composition norm for + condition `GPR 19.8(i)`. +* `ConicAlgebra.IsRegularRankTwoComposition` : condition `GPR 19.8(i)`. + +## Main results + +* `ConicAlgebra.adjoinElement_mul_comm` and `ConicAlgebra.adjoinElement_mul_assoc` : `k[u]` is + commutative and associative. +* `ConicAlgebra.normOnSpan_isGPRRegular_iff_isUnit_discriminant` : regularity of the restricted + norm is equivalent to invertibility of the discriminant. +* `ConicAlgebra.basis_and_regular_iff_isUnit_discriminant` : `GPR 19.8(ii) ⇔ (iii)`. +* `ConicAlgebra.isRegularRankTwoComposition_iff_isUnit_discriminant` : `GPR 19.8(i) ⇔ (iii)`. +* `ConicAlgebra.regularRankTwoComposition_iff_basisAndRegular` : the full three-way equivalence. +* `ConicAlgebra.quadraticSpan_injective_of_isUnit_discriminant` : the unit-discriminant part of + `GPR 19.8`, proving that `(1,u)` is linearly independent. +* `ConicAlgebra.quadraticSpanEquiv` : under that hypothesis, `k² ≃ k[u]`. +* `ConicAlgebra.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two` : over an LG + ring, a finitely generated projective conic algebra of constant rank two is `k[u]` for some `u`, + with no composition hypothesis; hence it is commutative and associative + (`ConicAlgebra.mul_comm_of_isLGRing_of_rankAtStalk_eq_two`, + `ConicAlgebra.mul_assoc_of_isLGRing_of_rankAtStalk_eq_two`, `GPR 16.4`). + +## Implementation notes + +Condition (i) is genuinely existential: its composition norm is not defined to be the ambient +norm restricted to `k[u]`. In `(i) ⇒ (ii)`, projectivity and rank two first make the canonical +surjection `k² → k[u]` an equivalence; `ConicAlgebra.norm_eq_of_projective` then proves that the +witnessing conic norm equals the restriction of the ambient norm. Building that equality into the +definition of condition (i) would omit the uniqueness step in GPR's proof. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.24, 16.4, + 16.7, 19.8. +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + +omit C in +/-- The coefficient map `(a,b) ↦ a·1 + b·u` whose range is the quadratic subalgebra `k[u]`. -/ +def spanOne (k : Type u) [CommRing k] {A : Type v} [NonAssocRing A] [Module k A] + (u : A) : k × k →ₗ[k] A where + toFun p := p.1 • (1 : A) + p.2 • u + map_add' p q := by simp only [Prod.fst_add, Prod.snd_add, add_smul]; abel + map_smul' a p := by + simp only [Prod.smul_fst, Prod.smul_snd, smul_add, smul_smul, RingHom.id_apply, + smul_eq_mul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem spanOne_apply (u : A) (p : k × k) : + spanOne k u p = p.1 • (1 : A) + p.2 • u := rfl + +/-- The unital subalgebra `k[u] = k·1 + k·u` of `GPR 19.8`. + +Closure under multiplication consumes only the degree-two identity of a conic algebra. -/ +def adjoinElement (u : A) : NonAssocSubalgebra k A where + toNonUnitalSubalgebra := + { carrier := LinearMap.range (spanOne k u) + zero_mem' := Submodule.zero_mem _ + add_mem' := Submodule.add_mem _ + smul_mem' := fun c _ hx ↦ Submodule.smul_mem _ c hx + mul_mem' := by + rintro _ _ ⟨p, rfl⟩ ⟨q, rfl⟩ + rcases p with ⟨a, b⟩ + rcases q with ⟨c, d⟩ + refine ⟨(a * c - b * d * C.norm u, a * d + b * c + b * d * C.trace u), ?_⟩ + simp only [spanOne_apply, add_mul, mul_add, smul_mul_assoc, mul_smul_comm, + one_mul, mul_one, C.mul_self_eq] + module } + one_mem := ⟨(1, 0), by simp⟩ + +/-- The coefficient map from `k²` onto the quadratic subalgebra `k[u]`. -/ +def spanOneToAdjoin (u : A) : k × k →ₗ[k] C.adjoinElement u := + (spanOne k u).codRestrict (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule fun p ↦ + ⟨p, rfl⟩ + +@[simp] theorem coe_spanOneToAdjoin_apply (u : A) (p : k × k) : + (C.spanOneToAdjoin u p : A) = spanOne k u p := rfl + +/-- The coefficient map onto `k[u]` is always surjective. -/ +theorem spanOneToAdjoin_surjective (u : A) : Function.Surjective (C.spanOneToAdjoin u) := by + rintro ⟨x, ⟨p, hp⟩⟩ + exact ⟨p, Subtype.ext hp⟩ + +/-- The algebra `k[u]` is generated as a module by `1` and `u`, hence is finitely generated. -/ +theorem finite_adjoinElement (u : A) : Module.Finite k (C.adjoinElement u) := + Module.Finite.of_surjective (C.spanOneToAdjoin u) (C.spanOneToAdjoin_surjective u) + +@[simp] theorem mem_adjoinElement_iff (u x : A) : + x ∈ C.adjoinElement u ↔ ∃ a b : k, a • (1 : A) + b • u = x := by + constructor + · rintro ⟨⟨a, b⟩, rfl⟩ + exact ⟨a, b, rfl⟩ + · rintro ⟨a, b, rfl⟩ + exact ⟨(a, b), rfl⟩ + +/-- The algebra generated by one element of a conic algebra is commutative (`GPR 19.8`). -/ +theorem adjoinElement_mul_comm (u : A) (x y : C.adjoinElement u) : x * y = y * x := by + apply Subtype.ext + change (x : A) * (y : A) = (y : A) * (x : A) + obtain ⟨a, b, hx⟩ := (C.mem_adjoinElement_iff u x).mp x.2 + obtain ⟨c, d, hy⟩ := (C.mem_adjoinElement_iff u y).mp y.2 + rw [← hx, ← hy] + simp only [add_mul, mul_add, smul_mul_assoc, mul_smul_comm, one_mul, mul_one] + module + +/-- Every element of a conic algebra generates an associative cube. -/ +theorem mul_self_mul_eq_mul_mul_self (C : ConicAlgebra k A) (u : A) : + u * u * u = u * (u * u) := by + rw [C.mul_self_eq] + simp only [sub_mul, mul_sub, smul_mul_assoc, mul_smul_comm, one_mul, mul_one] + +/-- The algebra generated by one element of a conic algebra is associative (`GPR 19.8`). -/ +theorem adjoinElement_mul_assoc (u : A) (x y z : C.adjoinElement u) : + x * y * z = x * (y * z) := by + apply Subtype.ext + change ((x : A) * (y : A)) * (z : A) = (x : A) * ((y : A) * (z : A)) + obtain ⟨a, b, hx⟩ := (C.mem_adjoinElement_iff u x).mp x.2 + obtain ⟨c, d, hy⟩ := (C.mem_adjoinElement_iff u y).mp y.2 + obtain ⟨e, f, hz⟩ := (C.mem_adjoinElement_iff u z).mp z.2 + rw [← hx, ← hy, ← hz] + simp only [add_mul, mul_add, smul_mul_assoc, mul_smul_comm, one_mul, mul_one] + rw [C.mul_self_mul_eq_mul_mul_self] + +/-- The quadratic subalgebra `k[u]` as a commutative ring. -/ +@[instance_reducible] def adjoinElementCommRing (u : A) : CommRing (C.adjoinElement u) := + { (inferInstance : NonAssocRing (C.adjoinElement u)) with + mul_assoc := C.adjoinElement_mul_assoc u + mul_comm := C.adjoinElement_mul_comm u } + +/-- The quadratic subalgebra `k[u]` as an associative `k`-algebra. -/ +@[instance_reducible] def adjoinElementAlgebra (u : A) : + letI := C.adjoinElementCommRing u + Algebra k (C.adjoinElement u) := + letI := C.adjoinElementCommRing u + Algebra.ofModule (fun r x y ↦ by exact smul_mul_assoc r x y) + (fun r x y ↦ by exact mul_smul_comm r x y) + +/-- The discriminant attached to `u`, namely `t(u)² - 4n(u)` (`GPR 19.8(iii)`). -/ +def elementDiscriminant (u : A) : k := C.trace u ^ 2 - 4 * C.norm u + +/-- The restriction of the norm to `k·1 + k·u`, written in coefficient coordinates. -/ +def normOnSpan (u : A) : QuadraticForm k (k × k) := C.norm.comp (spanOne k u) + +/-- The norm of `C` restricted to the quadratic subalgebra `k[u]`. -/ +def normAdjoinElement (u : A) : QuadraticForm k (C.adjoinElement u) := + C.normRestrict (C.adjoinElement u) + +@[simp] theorem normAdjoinElement_apply (u : A) (x : C.adjoinElement u) : + C.normAdjoinElement u x = C.norm (x : A) := rfl + +/-- The conic structure on the quadratic subalgebra `k[u]`, obtained by restricting the norm. -/ +def conicAdjoinElement (u : A) : + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + ConicAlgebra k (C.adjoinElement u) := by + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + exact C.restrict (C.adjoinElement u) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem normOnSpan_apply (u : A) (p : k × k) : + C.normOnSpan u p = p.1 ^ 2 + p.1 * p.2 * C.trace u + p.2 ^ 2 * C.norm u := by + rw [normOnSpan, QuadraticMap.comp_apply, spanOne_apply, QuadraticMap.map_add C.norm, + C.norm.map_smul, C.norm.map_smul, QuadraticMap.polar_smul_left, + QuadraticMap.polar_smul_right, C.norm_one, ← C.trace_apply] + simp only [smul_eq_mul] + ring + +/-- Multiplication in the coefficient presentation of `k[u]`. -/ +theorem spanOne_mul (u : A) (p q : k × k) : + spanOne k u p * spanOne k u q = + spanOne k u + (p.1 * q.1 - p.2 * q.2 * C.norm u, + p.1 * q.2 + p.2 * q.1 + p.2 * q.2 * C.trace u) := by + simp only [spanOne_apply, add_mul, mul_add, smul_mul_assoc, mul_smul_comm, + one_mul, mul_one, C.mul_self_eq] + module + +/-- The restricted norm on `k[u]` is multiplicative (`GPR 19.8(i)`). -/ +theorem isMultiplicative_conicAdjoinElement (u : A) : + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + (C.conicAdjoinElement u).IsMultiplicative := by + let := C.adjoinElementCommRing u + let := C.adjoinElementAlgebra u + intro x y + obtain ⟨p, rfl⟩ := C.spanOneToAdjoin_surjective u x + obtain ⟨q, rfl⟩ := C.spanOneToAdjoin_surjective u y + change C.norm (spanOne k u p * spanOne k u q) = + C.norm (spanOne k u p) * C.norm (spanOne k u q) + rw [C.spanOne_mul] + change C.normOnSpan u _ = C.normOnSpan u p * C.normOnSpan u q + simp only [normOnSpan_apply] + ring + +/-- Coordinates on the dual of `k × k`, obtained by evaluation on `(1,0)` and `(0,1)`. -/ +def dualProdCoordinates : Module.Dual k (k × k) ≃ₗ[k] k × k where + toFun f := (f (1, 0), f (0, 1)) + invFun p := + { toFun := fun q ↦ p.1 * q.1 + p.2 * q.2 + map_add' := by intros; simp only [Prod.fst_add, Prod.snd_add]; ring + map_smul' := by intros; simp only [Prod.smul_fst, Prod.smul_snd, RingHom.id_apply]; ring } + left_inv f := by + apply LinearMap.ext + rintro ⟨x, y⟩ + change f (1, 0) * x + f (0, 1) * y = f (x, y) + rw [mul_comm (f (1, 0)) x, mul_comm (f (0, 1)) y] + change x • f (1, 0) + y • f (0, 1) = f (x, y) + rw [← map_smul, ← map_smul, ← map_add] + congr 1 + ext <;> simp + right_inv p := by ext <;> simp + map_add' f g := by ext <;> simp + map_smul' a f := by ext <;> simp + +/-- The polar map of `normOnSpan`, with its dual output written as two coordinates. -/ +def polarSpanCoordinates (u : A) : k × k →ₗ[k] k × k := + dualProdCoordinates.comp (QuadraticMap.polarBilin (C.normOnSpan u)) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem polarSpanCoordinates_apply (u : A) (p : k × k) : + C.polarSpanCoordinates u p = + (2 * p.1 + C.trace u * p.2, C.trace u * p.1 + 2 * C.norm u * p.2) := by + simp only [polarSpanCoordinates, LinearMap.comp_apply, dualProdCoordinates] + change + (polar (C.normOnSpan u) p (1, 0), polar (C.normOnSpan u) p (0, 1)) = _ + rw [show polar (C.normOnSpan u) p (1, 0) = + polar C.norm (spanOne k u p) (spanOne k u (1, 0)) by + simp only [polar, normOnSpan, QuadraticMap.comp_apply, LinearMap.map_add], + show polar (C.normOnSpan u) p (0, 1) = + polar C.norm (spanOne k u p) (spanOne k u (0, 1)) by + simp only [polar, normOnSpan, QuadraticMap.comp_apply, LinearMap.map_add]] + simp only [spanOne_apply, one_smul, zero_smul, add_zero, zero_add, + QuadraticMap.polar_add_left, QuadraticMap.polar_smul_left, + QuadraticMap.polar_self, smul_eq_mul, nsmul_eq_mul] + push_cast + ext <;> dsimp + · rw [C.norm_one, QuadraticMap.polar_comm C.norm u 1, ← C.trace_apply] + ring + · rw [← C.trace_apply] + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The coefficient norm is regular exactly when its coordinate polar map is bijective. -/ +theorem normOnSpan_isGPRRegular_iff_bijective_polarSpanCoordinates (u : A) : + (C.normOnSpan u).IsGPRRegular ↔ Function.Bijective (C.polarSpanCoordinates u) := by + constructor + · exact fun h ↦ dualProdCoordinates.bijective.comp h + · intro h + constructor + · intro x y hxy + apply h.1 + simp only [polarSpanCoordinates, LinearMap.comp_apply, hxy] + · intro φ + obtain ⟨x, hx⟩ := h.2 (dualProdCoordinates φ) + exact ⟨x, dualProdCoordinates.injective hx⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The two-by-two polar matrix is bijective exactly when its discriminant is a unit. + +Bijectivity of an endomorphism is invertibility (`Module.End.isUnit_iff`), which the matrix +algebra equivalence turns into invertibility of the Gram matrix `!![2, t(u); t(u), 2n(u)]`, hence +of its determinant `4n(u) - t(u)²`. That is the negative of the discriminant. -/ +theorem bijective_polarSpanCoordinates_iff_isUnit_discriminant (u : A) : + Function.Bijective (C.polarSpanCoordinates u) ↔ IsUnit (C.elementDiscriminant u) := by + have hmat : LinearMap.toMatrixAlgEquiv (Module.Basis.finTwoProd k) + (C.polarSpanCoordinates u) = !![2, C.trace u; C.trace u, 2 * C.norm u] := by + ext i j + fin_cases i <;> fin_cases j <;> + simp [LinearMap.toMatrixAlgEquiv_apply, polarSpanCoordinates_apply] + rw [← Module.End.isUnit_iff, + ← MulEquiv.isUnit_map (LinearMap.toMatrixAlgEquiv (Module.Basis.finTwoProd k)), + hmat, Matrix.isUnit_iff_isUnit_det, Matrix.det_fin_two_of, elementDiscriminant, + show 2 * (2 * C.norm u) - C.trace u * C.trace u = 4 * C.norm u - C.trace u ^ 2 by ring] + exact IsUnit.sub_iff + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 19.8`, regularity criterion.** The norm on `k·1 + k·u`, in coefficient +coordinates, is regular if and only if `t(u)² - 4n(u)` is a unit. -/ +theorem normOnSpan_isGPRRegular_iff_isUnit_discriminant (u : A) : + (C.normOnSpan u).IsGPRRegular ↔ IsUnit (C.elementDiscriminant u) := + (C.normOnSpan_isGPRRegular_iff_bijective_polarSpanCoordinates u).trans + (C.bijective_polarSpanCoordinates_iff_isUnit_discriminant u) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- A relation `a·1 + b·u = 0` gives the first row of the polar Gram matrix: +`2a + t(u)b = 0`. -/ +theorem trace_eq_zero_of_smul_one_add_smul_eq_zero {u : A} {a b : k} + (h : a • (1 : A) + b • u = 0) : 2 * a + C.trace u * b = 0 := by + have ht := congrArg C.trace h + simp only [map_add, map_smul, trace_one, map_zero, smul_eq_mul] at ht + linear_combination ht + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The same relation gives the second row of the polar Gram matrix: +`t(u)a + 2n(u)b = 0`. -/ +theorem polar_eq_zero_of_smul_one_add_smul_eq_zero {u : A} {a b : k} + (h : a • (1 : A) + b • u = 0) : C.trace u * a + 2 * C.norm u * b = 0 := by + have hp := congrArg (fun x ↦ polar C.norm u x) h + simp only [QuadraticMap.polar_add_right, QuadraticMap.polar_smul_right, + QuadraticMap.polar_zero_right, QuadraticMap.polar_self, QuadraticMap.polar_comm C.norm u 1, + smul_eq_mul, nsmul_eq_mul] at hp + push_cast at hp + change a * C.trace u + b * (2 * C.norm u) = 0 at hp + linear_combination hp + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 19.8`, `(iii) ⇒` linear independence.** If `t(u)² - 4n(u)` is a unit, then +`a·1 + b·u = 0` forces `a = b = 0`. -/ +theorem eq_zero_of_smul_one_add_smul_eq_zero {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) {a b : k} + (h : a • (1 : A) + b • u = 0) : a = 0 ∧ b = 0 := by + -- The two displayed rows are exactly the coordinates of `polarSpanCoordinates u (a, b)`, so + -- this is the injectivity half of the criterion above rather than a second `2 × 2` solve. + have hz : C.polarSpanCoordinates u (a, b) = 0 := by + rw [polarSpanCoordinates_apply, Prod.mk_eq_zero] + exact ⟨C.trace_eq_zero_of_smul_one_add_smul_eq_zero h, + C.polar_eq_zero_of_smul_one_add_smul_eq_zero h⟩ + have h0 := ((C.bijective_polarSpanCoordinates_iff_isUnit_discriminant u).mpr hdisc).1 + (hz.trans (map_zero _).symm) + exact ⟨congrArg Prod.fst h0, congrArg Prod.snd h0⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem quadraticSpan_injective_of_isUnit_discriminant {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) : Function.Injective (spanOne k u) := by + rw [← LinearMap.ker_eq_bot] + ext p + simp only [LinearMap.mem_ker, Submodule.mem_bot] + constructor + · intro hp + obtain ⟨h₁, h₂⟩ := C.eq_zero_of_smul_one_add_smul_eq_zero hdisc hp + exact Prod.ext h₁ h₂ + · rintro rfl + simp + +/-- **`GPR 19.8`, `(ii) ⇔ (iii)`.** The pair `(1,u)` is a basis of `k[u]` and the +restricted norm is regular if and only if `t(u)² - 4n(u)` is a unit. The restricted norm is +written through this basis as `normOnSpan`. -/ +theorem basis_and_regular_iff_isUnit_discriminant (u : A) : + (Function.Bijective (C.spanOneToAdjoin u) ∧ (C.normOnSpan u).IsGPRRegular) ↔ + IsUnit (C.elementDiscriminant u) := by + constructor + · exact fun h ↦ (C.normOnSpan_isGPRRegular_iff_isUnit_discriminant u).mp h.2 + · intro hdisc + refine ⟨⟨?_, C.spanOneToAdjoin_surjective u⟩, + (C.normOnSpan_isGPRRegular_iff_isUnit_discriminant u).mpr hdisc⟩ + intro p q hpq + exact C.quadraticSpan_injective_of_isUnit_discriminant hdisc (congrArg Subtype.val hpq) + +/-- Under the unit-discriminant hypothesis, `(1,u)` is a basis of `k[u]`, expressed as a linear +equivalence `k × k ≃ k[u]`. -/ +noncomputable def quadraticSpanEquiv {u : A} (hdisc : IsUnit (C.elementDiscriminant u)) : + (k × k) ≃ₗ[k] C.adjoinElement u where + toFun p := ⟨spanOne k u p, ⟨p, rfl⟩⟩ + invFun x := x.2.choose + left_inv p := C.quadraticSpan_injective_of_isUnit_discriminant hdisc + (⟨p, rfl⟩ : spanOne k u p ∈ C.adjoinElement u).choose_spec + right_inv x := Subtype.ext x.2.choose_spec + map_add' p q := Subtype.ext (map_add (spanOne k u) p q) + map_smul' a p := Subtype.ext (map_smul (spanOne k u) a p) + +/-- Under the unit-discriminant hypothesis `k[u]` has constant rank two, being the image of `k²` +under `quadraticSpanEquiv`. -/ +theorem rankAtStalk_adjoinElement [Nontrivial k] {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) : + Module.rankAtStalk (R := k) (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule = + fun _ ↦ 2 := by + change Module.rankAtStalk (R := k) (C.adjoinElement u) = fun _ ↦ 2 + rw [← Module.rankAtStalk_eq_of_equiv (C.quadraticSpanEquiv hdisc), Module.rankAtStalk_prod, + Module.rankAtStalk_self] + rfl + +/-- The coefficient norm is the restricted norm read through the coefficient equivalence. This is +the form of that identification consumed by `QuadraticForm.isGPRRegular_comp_linearEquiv_iff`. -/ +theorem normOnSpan_eq_comp_quadraticSpanEquiv {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) : + C.normOnSpan u = (C.normAdjoinElement u).comp (C.quadraticSpanEquiv hdisc).toLinearMap := + QuadraticMap.ext fun _ ↦ rfl + +/-- A unit discriminant makes the norm restricted to `k[u]` regular. -/ +theorem normAdjoinElement_isGPRRegular {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) : (C.normAdjoinElement u).IsGPRRegular := + (QuadraticForm.isGPRRegular_comp_linearEquiv_iff (C.quadraticSpanEquiv hdisc)).mp + (C.normOnSpan_eq_comp_quadraticSpanEquiv hdisc ▸ + (C.normOnSpan_isGPRRegular_iff_isUnit_discriminant u).mpr hdisc) + +/-- **`GPR 19.8`, `(iii) ⇒ (i)`.** A unit discriminant makes `k[u]`, with its restricted +norm, a regular rank-two composition algebra. The rank-two basis is `quadraticSpanEquiv`. -/ +theorem isComposition_conicAdjoinElement {u : A} + (hdisc : IsUnit (C.elementDiscriminant u)) : + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + letI : Module.Free k (C.adjoinElement u) := + Module.Free.of_equiv (C.quadraticSpanEquiv hdisc) + letI : Module.Finite k (C.adjoinElement u) := + Module.Finite.equiv (C.quadraticSpanEquiv hdisc) + (C.conicAdjoinElement u).IsComposition.{u, v, u} := by + let := C.adjoinElementCommRing u + let := C.adjoinElementAlgebra u + let : Module.Free k (C.adjoinElement u) := + Module.Free.of_equiv (C.quadraticSpanEquiv hdisc) + let : Module.Finite k (C.adjoinElement u) := + Module.Finite.equiv (C.quadraticSpanEquiv hdisc) + exact + { isGPRNonsingular := (C.normAdjoinElement_isGPRRegular hdisc).isGPRNonsingular + isMultiplicative := C.isMultiplicative_conicAdjoinElement u } + +/-- `k[u]` admits the structure of a regular rank-two composition algebra, the condition in +`GPR 19.8(i)`. + +The composition norm is existential data and is **not** assumed to be the ambient norm restricted +to `k[u]`. Identifying the two norms is a conclusion of `GPR 19.8(i) ⇒ (ii)`, using uniqueness +of conic norms on finitely generated projective algebras. -/ +structure RegularRankTwoCompositionStructure (u : A) where + /-- A conic structure on the abstract algebra `k[u]`; its norm is not definitionally the + restriction of the ambient norm. -/ + conic : ConicAlgebra k (C.adjoinElement u) + /-- The quadratic subalgebra is projective. -/ + projective : Module.Projective k (C.adjoinElement u) + /-- Its rank at every maximal ideal agrees with that of the free module `k²`. -/ + rank_two : ∀ (m : Ideal k) [m.IsMaximal], + Module.rankAtStalk (k × k) ⟨m, inferInstance⟩ = + Module.rankAtStalk (C.adjoinElement u) ⟨m, inferInstance⟩ + /-- The composition norm is regular in GPR's sense. -/ + regular : conic.norm.IsGPRRegular + /-- The chosen norm permits composition. -/ + isMultiplicative : conic.IsMultiplicative + +/-- The proposition that the abstract algebra `k[u]` admits a regular rank-two composition +structure. The witnessing norm is intentionally existential. -/ +def IsRegularRankTwoComposition (u : A) : Prop := + Nonempty (C.RegularRankTwoCompositionStructure u) + +/-- A regular rank-two quadratic-subalgebra structure is an actual composition algebra in the +sense of `ConicAlgebra.IsComposition`. -/ +theorem RegularRankTwoCompositionStructure.isComposition {u : A} + (h : C.RegularRankTwoCompositionStructure u) : + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + letI : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + letI : Module.Projective k (C.adjoinElement u) := h.projective + h.conic.IsComposition.{u, v, u} := by + let := C.adjoinElementCommRing u + let := C.adjoinElementAlgebra u + let : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + let : Module.Projective k (C.adjoinElement u) := h.projective + exact + { isGPRNonsingular := h.regular.isGPRNonsingular + isMultiplicative := h.isMultiplicative } + +/-- In condition `GPR 19.8(i)`, the abstract composition norm on `k[u]` is forced to equal the +ambient conic norm restricted to `k[u]`. This is the uniqueness step missing if condition (i) is +defined using the restricted norm from the outset. -/ +theorem RegularRankTwoCompositionStructure.conic_norm_eq_normAdjoinElement {u : A} + (h : C.RegularRankTwoCompositionStructure u) : + h.conic.norm = C.normAdjoinElement u := by + let : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + let : Module.Projective k (C.adjoinElement u) := h.projective + exact ConicAlgebra.norm_eq_of_projective h.conic (C.restrict (C.adjoinElement u)) + +/-- Pulling the restricted norm back through the coefficient equivalence preserves regularity. -/ +theorem normOnSpan_isGPRRegular_of_normAdjoinElement_isGPRRegular (u : A) + (hbasis : Function.Bijective (C.spanOneToAdjoin u)) + (hregular : (C.normAdjoinElement u).IsGPRRegular) : (C.normOnSpan u).IsGPRRegular := by + have he : C.normOnSpan u = + (C.normAdjoinElement u).comp (LinearEquiv.ofBijective _ hbasis).toLinearMap := + QuadraticMap.ext fun _ ↦ rfl + exact he ▸ hregular.comp_linearEquiv _ + +/-- **`GPR 19.8`, `(i) ⇔ (iii)`.** The generated algebra `k[u]` is a regular rank-two +composition algebra if and only if `t(u)² - 4n(u)` is a unit. -/ +theorem isRegularRankTwoComposition_iff_isUnit_discriminant (u : A) : + C.IsRegularRankTwoComposition u ↔ IsUnit (C.elementDiscriminant u) := by + constructor + · intro h + obtain ⟨h⟩ := h + let := C.finite_adjoinElement u + let := h.projective + have hbasis : Function.Bijective (C.spanOneToAdjoin u) := + Module.bijective_of_surjective_of_rankAtStalk_eq + (C.spanOneToAdjoin_surjective u) h.rank_two + have hregular : (C.normAdjoinElement u).IsGPRRegular := by + rw [← h.conic_norm_eq_normAdjoinElement] + exact h.regular + exact (C.normOnSpan_isGPRRegular_iff_isUnit_discriminant u).mp + (C.normOnSpan_isGPRRegular_of_normAdjoinElement_isGPRRegular u hbasis hregular) + · intro hdisc + let e := C.quadraticSpanEquiv hdisc + exact ⟨ + { conic := C.conicAdjoinElement u + projective := by + let : Module.Free k (C.adjoinElement u) := Module.Free.of_equiv e + infer_instance + rank_two := fun m _ ↦ congrFun (Module.rankAtStalk_eq_of_equiv e) ⟨m, inferInstance⟩ + regular := C.normAdjoinElement_isGPRRegular hdisc + isMultiplicative := C.isMultiplicative_conicAdjoinElement u }⟩ + +/-- **`GPR 19.8`.** The three conditions are equivalent: `k[u]` is a regular rank-two +composition algebra; `(1,u)` is a basis and the restricted norm is regular; and the discriminant +`t(u)² - 4n(u)` is a unit. -/ +theorem regularRankTwoComposition_iff_basisAndRegular (u : A) : + C.IsRegularRankTwoComposition u ↔ + Function.Bijective (C.spanOneToAdjoin u) ∧ (C.normOnSpan u).IsGPRRegular := + (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).trans + (C.basis_and_regular_iff_isUnit_discriminant u).symm + +/-! ### Constant rank two over an LG ring -/ + +section ConstantRankTwo + +variable [Module.Finite k A] [Module.Projective k A] + +/-- A finitely generated projective conic algebra of constant rank two over an LG ring is +generated by one element: `A = k[u]` (`GPR 19.8`). + +The unit is unimodular (`GPR 16.7`), so a functional `l` with `l 1 = 1` splits `A ≃ k × ker l`, +and `ker l` is projective of constant rank one, hence free (`GPR 11.24`); its generator is `u`. +`GPR 23.4` uses this over a local ring, extending `1` to a basis of `A`. No composition, +regularity or nontriviality hypothesis is needed. -/ +theorem exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : ∃ u : A, ∀ x : A, x ∈ C.adjoinElement u := by + rcases subsingleton_or_nontrivial k with hk | hk + · have : Subsingleton A := Module.subsingleton k A + exact ⟨0, fun x ↦ (C.mem_adjoinElement_iff 0 x).mpr ⟨0, 0, Subsingleton.elim _ _⟩⟩ + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp C.isUnimodular_one + set e := LinearMap.equivProdKerOfApplyEqOne l 1 hl + have : Module.Finite k (LinearMap.ker l) := Module.Finite.of_linearEquiv_prod e + have : Module.Projective k (LinearMap.ker l) := Module.Projective.of_linearEquiv_prod e + have hker : Module.rankAtStalk (R := k) (LinearMap.ker l) = fun _ ↦ 1 := by + have hM := Module.rankAtStalk_eq_of_equiv e + rw [Module.rankAtStalk_prod, Module.rankAtStalk_self] at hM + funext p + have := congrFun (hM.symm.trans hA) p + simp only [Pi.add_apply, Pi.one_apply] at this + omega + have : Module.Free k (LinearMap.ker l) := + Module.free_of_isLGRing_of_rankAtStalk_eq hLG 1 _ hker + have hfin : Module.finrank k (LinearMap.ker l) = 1 := by + obtain ⟨p⟩ : Nonempty (PrimeSpectrum k) := inferInstance + have := congrFun hker p + rwa [Module.rankAtStalk_eq_finrank_of_free] at this + let b := Module.finBasisOfFinrankEq k (LinearMap.ker l) hfin + refine ⟨(b 0 : A), fun x ↦ (C.mem_adjoinElement_iff _ x).mpr ?_⟩ + have hx : x - l x • (1 : A) ∈ LinearMap.ker l := by + simp only [LinearMap.mem_ker, map_sub, map_smul, hl, smul_eq_mul, mul_one, sub_self] + refine ⟨l x, b.repr ⟨_, hx⟩ 0, ?_⟩ + have hsum := b.sum_repr ⟨_, hx⟩ + rw [Fin.sum_univ_one] at hsum + have hcoe : b.repr ⟨_, hx⟩ 0 • (b 0 : A) = x - l x • 1 := congrArg Subtype.val hsum + rw [hcoe] + abel + +include C in +/-- A finitely generated projective conic algebra of constant rank two over an LG ring is +commutative, being `k[u]` (`GPR 16.4`). -/ +theorem mul_comm_of_isLGRing_of_rankAtStalk_eq_two (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x y : A) : x * y = y * x := by + obtain ⟨u, hmem⟩ := C.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two hLG hA + exact congrArg Subtype.val (C.adjoinElement_mul_comm u ⟨x, hmem x⟩ ⟨y, hmem y⟩) + +include C in +/-- A finitely generated projective conic algebra of constant rank two over an LG ring is +associative, being `k[u]` (`GPR 16.4`). -/ +theorem mul_assoc_of_isLGRing_of_rankAtStalk_eq_two (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x y z : A) : x * y * z = x * (y * z) := by + obtain ⟨u, hmem⟩ := C.exists_forall_mem_adjoinElement_of_isLGRing_of_rankAtStalk_eq_two hLG hA + exact congrArg Subtype.val (C.adjoinElement_mul_assoc u ⟨x, hmem x⟩ ⟨y, hmem y⟩ ⟨z, hmem z⟩) + +end ConstantRankTwo + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/RankDichotomy.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/RankDichotomy.lean new file mode 100644 index 0000000000..86905d3bdc --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/RankDichotomy.lean @@ -0,0 +1,203 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra + +/-! +# The regular-or-rank-one dichotomy for composition algebras + +This file proves the regular-or-rank-one dichotomy of **`GPR 19.11`**. Over a field, the norm of a +composition algebra is regular unless the algebra has dimension one; in the exceptional case the +field has characteristic two. The field result then globalizes: a constant-rank composition +algebra over a commutative ring is regular unless its rank is one and `2` is not a unit. + +The quadratic-form dichotomy of `GPR Exercise 11.37` says that a nonregular nonsingular form has a +one-dimensional polar radical and that the field has characteristic two. The extra algebraic step +is to show that the whole algebra, not merely that radical, is one-dimensional. Choose a nonzero +element `u` in the polar radical. Its norm is nonzero because the quadratic radical vanishes. +Norm-associativity and right alternativity then make right multiplication by `conj u` surjective, +so orthogonality of `u` forces the trace to vanish identically. Multiplicativity now forces the +whole polar form to vanish, and its one-dimensional kernel is therefore the whole algebra. + +## Main results + +* `ConicAlgebra.IsComposition.isGPRRegular_or_finrank_eq_one` : the field-fibre dichotomy in + `GPR 19.11`. +* `ConicAlgebra.IsComposition.isGPRRegular_of_forall_rankAtStalk_ne_one` : `GPR 19.11` for a + composition algebra whose rank is never `1`, without a constant-rank hypothesis. +* `ConicAlgebra.IsComposition.isGPRRegular_or_rank_eq_one` : the constant-rank ring statement. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.9, 19.11. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {F : Type u} {A : Type v} [Field F] [NonAssocRing A] [Module F A] + [SMulCommClass F A A] [IsScalarTower F A A] [Module.Finite F A] [Module.Projective F A] + {C : ConicAlgebra F A} + +/-- **The field-fibre core of `GPR 19.11`.** A composition algebra over a field has regular norm, +or it has dimension one and the field has characteristic two. -/ +theorem IsComposition.isGPRRegular_or_finrank_eq_one (h : C.IsComposition.{u, v, u}) : + C.norm.IsGPRRegular ∨ Module.finrank F A = 1 ∧ ringChar F = 2 := by + have hnd : QuadraticMap.Nondegenerate (Q := C.norm) := + (C.norm.isGPRNonsingular_iff_nondegenerate).mp h.isGPRNonsingular + rcases C.norm.isGPRRegular_xor_finrank_ker_polarBilin_eq_one hnd with + hreg | hker + · exact Or.inl hreg.1 + · right + have hdim := hker.1 + have h2 : (2 : F) = 0 := + C.norm.two_eq_zero_of_finrank_ker_polarBilin_eq_one h.isGPRNondegenerate hdim + let P := LinearMap.ker (QuadraticMap.polarBilin C.norm) + have hPpos : 0 < Module.finrank F P := by simp [P, hdim] + let : Nontrivial P := Module.nontrivial_of_finrank_pos hPpos + obtain ⟨u, hu⟩ : ∃ u : P, u ≠ 0 := exists_ne 0 + have hnu : C.norm (u : A) ≠ 0 := by + intro hnu + have hurad : (u : A) ∈ C.norm.radical := ⟨hnu, LinearMap.mem_ker.mp u.2⟩ + rw [h.isGPRNondegenerate, Submodule.mem_bot] at hurad + exact hu (Subtype.ext hurad) + let : IsAlternative A := h.isAlternative + have htu : C.trace (u : A) = 0 := by + rw [C.trace_apply, QuadraticMap.polar_comm] + exact DFunLike.congr_fun (LinearMap.mem_ker.mp u.2) 1 + have hconj : C.conj (u : A) = u := by + rw [conj_apply, htu, zero_smul, zero_sub] + apply neg_eq_iff_add_eq_zero.mpr + rw [← two_smul F (u : A), h2, zero_smul] + have huu : (u : A) * u = C.norm u • (1 : A) := by + calc + (u : A) * u = C.conj u * u := congrArg (fun a : A ↦ a * u) hconj.symm + _ = C.norm u • (1 : A) := C.conj_mul_self u + have htrace : ∀ x : A, C.trace x = 0 := by + intro x + set z : A := (C.norm u)⁻¹ • (x * u) + have hzu : z * C.conj u = x := by + dsimp [z] + rw [hconj, smul_mul_assoc, IsAlternative.mul_self_mul_right, huu, + mul_smul_comm, mul_one, inv_smul_smul₀ hnu] + have huorth : QuadraticMap.polar C.norm (u : A) z = 0 := + DFunLike.congr_fun (LinearMap.mem_ker.mp u.2) z + calc + C.trace x = QuadraticMap.polar C.norm 1 x := C.trace_apply x + _ = QuadraticMap.polar C.norm (1 * u) z := by + rw [h.polar_mul_right, hzu] + _ = 0 := by simpa only [one_mul] using huorth + have hpolar : QuadraticMap.polarBilin C.norm = 0 := by + ext x y + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] + exact h.isMultiplicative.polar_eq_zero_of_trace_eq_zero h2 htrace x y + have htop : LinearMap.ker (QuadraticMap.polarBilin C.norm) = ⊤ := by + rw [hpolar, LinearMap.ker_zero] + constructor + · rw [htop, finrank_top] at hdim + exact hdim + · exact C.norm.ringChar_eq_two_of_finrank_ker_polarBilin_eq_one + h.isGPRNondegenerate hdim + +section CommRing + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [SMulCommClass k B B] [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] + {D : ConicAlgebra k B} + +/-- **`GPR 19.11`, pointwise on `Spec k`.** A composition algebra whose rank is different from `1` +at every prime has regular norm. No constant-rank hypothesis is needed: regularity is checked +after base change to each field `F` +(`QuadraticForm.isGPRRegular_of_forall_baseChangeOfProjective_isGPRRegular`), and the dimension of +`F ⊗ A` is the rank of `A` at the single prime under the zero ideal of `F`. +`ConicAlgebra.IsComposition.isGPRRegular_of_rankAtStalk_ne_one` is the constant-rank case. -/ +theorem IsComposition.isGPRRegular_of_forall_rankAtStalk_ne_one (h : D.IsComposition.{u, v, u}) + (hrank : ∀ p, Module.rankAtStalk (R := k) B p ≠ 1) : D.norm.IsGPRRegular := by + apply QuadraticForm.isGPRRegular_of_forall_baseChangeOfProjective_isGPRRegular + intro F _ _ + rcases (h.baseChangeOfProjective F).isGPRRegular_or_finrank_eq_one with hreg | hdim + · exact hreg + · refine (hrank ((⊥ : PrimeSpectrum F).comap (algebraMap k F)) ?_).elim + have hbase := Module.rankAtStalk_baseChange (R := k) (M := B) (S := F) ⊥ + rw [Module.rankAtStalk_eq_finrank_of_free] at hbase + exact hbase.symm.trans hdim.1 + +/-- The non-rank-one half of **`GPR 19.11`**. If a composition algebra has constant rank other +than one, its norm is regular. + +The field-fibre dichotomy proves regularity after every field base change. Regularity then descends +by the local-global principle for the polar map +(`ConicAlgebra.IsComposition.isGPRRegular_of_forall_rankAtStalk_ne_one`). -/ +theorem IsComposition.isGPRRegular_of_rankAtStalk_ne_one (h : D.IsComposition.{u, v, u}) + {r : ℕ} (hrank : Module.rankAtStalk (R := k) B = fun _ ↦ r) (hr : r ≠ 1) : + D.norm.IsGPRRegular := + h.isGPRRegular_of_forall_rankAtStalk_ne_one fun p ↦ by rw [hrank]; exact hr + +/-- **`GPR 19.11`, for the project's finitely generated definition of composition algebra.** +If a composition algebra has constant rank `r`, then its norm is regular, or `r = 1` and `2` is +not a unit in the base ring. + +The finite-generation conclusion of `GPR 19.11` is already an instance hypothesis in this +project's deliberately narrower `ConicAlgebra.IsComposition` API. -/ +theorem IsComposition.isGPRRegular_or_rank_eq_one (h : D.IsComposition.{u, v, u}) {r : ℕ} + (hrank : Module.rankAtStalk (R := k) B = fun _ ↦ r) : + D.norm.IsGPRRegular ∨ r = 1 ∧ ¬ IsUnit (2 : k) := by + by_cases hreg : D.norm.IsGPRRegular + · exact Or.inl hreg + · right + have hr : r = 1 := by + by_contra hr + exact hreg (h.isGPRRegular_of_rankAtStalk_ne_one hrank hr) + refine ⟨hr, ?_⟩ + intro h2 + let : Invertible (2 : k) := h2.invertible + exact hreg h.isGPRRegular + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +/-- In a constant-rank-one conic algebra, every element is its `unitForm` coefficient times `1`. + +The unit splits off a free rank-one summand. Since the whole module already has rank one, the +kernel of `unitForm` has rank zero and is trivial. This argument remains valid in characteristic +two, where the polar norm itself may be nonregular. -/ +theorem eq_unitForm_smul_one_of_rankAtStalk_eq_one (D : ConicAlgebra k B) + [Nontrivial k] (hB : Module.rankAtStalk (R := k) B = fun _ ↦ 1) (x : B) : + x = D.unitForm x • (1 : B) := by + let N := LinearMap.ker D.unitForm + let p : B →ₗ[k] N := LinearMap.codRestrict N + (LinearMap.id - LinearMap.toSpanSingleton k B 1 ∘ₗ D.unitForm) (fun z ↦ by + simp [N, LinearMap.mem_ker, LinearMap.toSpanSingleton_apply, D.unitForm_one]) + have hpi : p ∘ₗ N.subtype = LinearMap.id := by + refine LinearMap.ext fun z ↦ Subtype.ext ?_ + have hz : D.unitForm (z : B) = 0 := z.2 + simp [p, hz, LinearMap.toSpanSingleton_apply] + let : Module.Finite k N := + Module.Finite.of_surjective p fun z ↦ ⟨(z : B), DFunLike.congr_fun hpi z⟩ + let : Module.Projective k N := Module.Projective.of_split N.subtype p hpi + let E := LinearMap.equivProdKerOfApplyEqOne D.unitForm (1 : B) D.unitForm_one + have hN : Module.rankAtStalk (R := k) N = 0 := by + have hprod := Module.rankAtStalk_prod (R := k) k N + have hE := Module.rankAtStalk_eq_of_equiv E + rw [hprod, Module.rankAtStalk_self] at hE + funext q + have hq := congrFun (hE.symm.trans hB) q + simp only [Pi.add_apply, Pi.one_apply, Pi.zero_apply] at hq ⊢ + omega + let : Subsingleton N := + (Module.rankAtStalk_eq_zero_iff_subsingleton (R := k)).mp hN + have hx : x - D.unitForm x • (1 : B) ∈ N := by + simp [N, LinearMap.mem_ker, D.unitForm_one] + have hzero : x - D.unitForm x • (1 : B) = 0 := + congrArg Subtype.val (Subsingleton.elim ⟨x - D.unitForm x • (1 : B), hx⟩ 0) + exact sub_eq_zero.mp hzero + +end CommRing + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/RankOneTwoFourEight.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/RankOneTwoFourEight.lean new file mode 100644 index 0000000000..0da5f11f9e --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/RankOneTwoFourEight.lean @@ -0,0 +1,571 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAlternative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAssociative +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Semilocal + +/-! +# The rank of a composition algebra is 1, 2, 4 or 8 (`GPR 19.18`) + +A composition algebra of constant rank over a nontrivial commutative ring is the base ring in +rank `1`; commutative associative with nontrivial conjugation in rank `2`; associative and +noncommutative in rank `4`; or alternative and nonassociative in rank `8`. In particular its rank +is `1`, `2`, `4`, or `8`. The positive identities descend from localizations, while the negative +ones are detected over a residue field. + +⚠ **No LG hypothesis.** The tower that proves the field case runs over a field, and every field is +an LG ring, so nothing here assumes `IsLGRing k`. + +## The two halves + +**The rank is a power of two.** That is `GPR 19.17` (`Composition/Tower.lean`): a composition +algebra of dimension `r > 2` is a Cayley–Dickson double of a composition subalgebra of dimension +`r / 2`. Iterating halves the dimension until it reaches `2`. + +**The tower stops at eight.** That is the converse half of `GPR 18.14(c)` +(`Conic/CayleyDicksonAlternative.lean`), and it is what the descent below is for. Reading the +chain downwards from a hypothetical algebra of dimension `16`: + +* it is alternative — every composition algebra over a field is (`GPR 19.3`) — and it is a double, + so its eight-dimensional half is **associative** (`ConicAlgebra.mul_assoc_of_isAlternative_cay`); +* an associative double forces its own half to be **commutative** + (`ConicAlgebra.exists_mul_mul_ne_mul_mul_cay`, contrapositive), so the four-dimensional rung is + commutative; +* a commutative double forces the conjugation of its half to be the **identity** + (`ConicAlgebra.exists_mul_ne_mul_cay`, contrapositive), so the two-dimensional rung has + `conj x = x`; +* but a composition algebra with trivial conjugation has dimension at most one + (`ConicAlgebra.IsComposition.finrank_le_one_of_conj_eq_id`) — contradiction. + +Only the first bullet is new; the middle two are the explicit witnesses already in +`Conic/CayleyDicksonAssociative.lean`, used in the contrapositive direction they were built for. + +## The bottom of the descent + +`finrank_le_one_of_conj_eq_id` is where the two characteristics part company. `conj x = x` reads +`2x = t(x) · 1`. When `2 ≠ 0` every element is therefore a scalar multiple of `1`, and the +dimension is at most one outright. When `2 = 0` it reads `t(x) · 1 = 0`, so `t ≡ 0` because +`1 ≠ 0`; then `n(1, y) = t(y) = 0` for every `y`, so `1` is a nonzero vector in the kernel of the +polar form, the norm is not regular, and `GPR 19.11` (`Composition/RankDichotomy.lean`) leaves only +dimension one. The characteristic-two branch is the one that needs `19.11`, and it is the reason +this file depends on it. + +## Implementation notes + +Each rung is identified with the next by `ConicAlgebra.cayToAlgebra`, a `LinearMap` that happens +to be bijective and multiplicative but is not a bundled algebra map, so alternativity, +associativity and commutativity are moved across by hand (`isAlternative_of_injective` and +friends). Injectivity alone suffices in every case. + +The induction runs over the carrier type as well as the dimension, since each rung is a subalgebra +of the previous one and so a different type. + +## Main results + +* `ConicAlgebra.IsComposition.rankAtStalk_classification` : full **`GPR 19.18`**, including the + structure in each of the four ranks. +* `ConicAlgebra.IsComposition.rankAtStalk_eq_one_or_two_or_four_or_eight` : its rank-only part. +* `ConicAlgebra.IsComposition.finrank_eq_one_or_two_or_four_or_eight` : the same over a field. +* `ConicAlgebra.mul_comm_of_rankAtStalk_eq_two`, `ConicAlgebra.mul_assoc_of_rankAtStalk_eq_two` : + a finitely generated projective conic algebra of constant rank two over any commutative ring is + commutative and associative (`GPR 16.4`); no composition hypothesis is needed. +* `ConicAlgebra.IsComposition.finrank_le_four_of_mul_assoc`, + `ConicAlgebra.IsComposition.finrank_le_two_of_mul_comm`, + `ConicAlgebra.IsComposition.finrank_le_one_of_conj_eq_id` : the three steps of the descent. +* `ConicAlgebra.not_isComposition_of_finrank_notMem` : the contrapositive. Applied to the + sixteen-dimensional double of an octonion algebra it says the **sedenions** are not a composition + algebra (`GPR 19.23`). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.4, 18.14(c), + 19.3, 19.11, 19.17, 19.18. +-/ + +@[expose] public section + +universe u v w + +open QuadraticMap (polar) +open scoped TensorProduct + +/-! ### Transporting multiplicative properties along an injective multiplicative map + +Each rung of the Cayley–Dickson tower is identified with an algebra by a bijection that is +multiplicative but is not an algebra homomorphism of any bundled kind (`ConicAlgebra.cayToAlgebra` +is a `LinearMap`), so the properties have to be moved by hand. Injectivity alone suffices in every +case — surjectivity is never used. -/ + +section Transport + +variable {X : Type v} {Y : Type w} [Mul X] [Mul Y] (f : X → Y) (hf : Function.Injective f) + (hmul : ∀ p q, f (p * q) = f p * f q) +include hf hmul + +/-- Alternativity pulls back along an injective multiplicative map. -/ +theorem isAlternative_of_injective [IsAlternative Y] : IsAlternative X where + left_alt a b := hf (by simp only [hmul]; exact IsAlternative.left_alt _ _) + right_alt a b := hf (by simp only [hmul]; exact IsAlternative.right_alt _ _) + +/-- Associativity pulls back along an injective multiplicative map. -/ +theorem mul_assoc_of_injective (h : ∀ a b c : Y, a * b * c = a * (b * c)) (a b c : X) : + a * b * c = a * (b * c) := + hf (by simp only [hmul]; exact h _ _ _) + +/-- Commutativity pulls back along an injective multiplicative map. -/ +theorem mul_comm_of_injective (h : ∀ a b : Y, a * b = b * a) (a b : X) : a * b = b * a := + hf (by simp only [hmul]; exact h _ _) + +end Transport + +/-- A unital subalgebra of an alternative algebra is alternative: both laws are checked on +elements of the ambient algebra. -/ +instance NonAssocSubalgebra.isAlternative {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] + [Module k A] [IsAlternative A] (B : NonAssocSubalgebra k A) : IsAlternative B := + isAlternative_of_injective (fun x ↦ (x : A)) Subtype.val_injective fun _ _ ↦ rfl + +namespace Module + +/-- Over a field, `Module.rankAtStalk` is the dimension. -/ +theorem finrank_of_rankAtStalk_eq {F : Type u} [Field F] {X : Type v} [AddCommGroup X] + [Module F X] {s : ℕ} (h : Module.rankAtStalk (R := F) X = fun _ ↦ s) : + Module.finrank F X = s := by + have hb := congrFun h ⊥ + rwa [Module.rankAtStalk_eq_finrank_of_free] at hb + +/-- Over a field, the dimension is `Module.rankAtStalk`. -/ +theorem rankAtStalk_eq_of_finrank_eq {F : Type u} [Field F] {X : Type v} [AddCommGroup X] + [Module F X] {s : ℕ} (h : Module.finrank F X = s) : + Module.rankAtStalk (R := F) X = fun _ ↦ s := by + rw [Module.rankAtStalk_eq_finrank_of_free, h] + rfl + +end Module + +namespace ConicAlgebra + +variable {F : Type u} {A : Type v} [Field F] [NonAssocRing A] [Module F A] + [SMulCommClass F A A] [IsScalarTower F A A] [Module.Finite F A] [Module.Projective F A] + {C : ConicAlgebra F A} + +/-- Over a field a unital subalgebra of a finite-dimensional algebra is finite-dimensional. The +corresponding statement for its underlying submodule is found by instance search; this moves it +across `ConicAlgebra.toSubmoduleEquiv`, which instance search will not do on its own. -/ +instance finite_nonAssocSubalgebra (B : NonAssocSubalgebra F A) : Module.Finite F B := + Module.Finite.equiv (toSubmoduleEquiv B) + +/-- **`GPR 19.17` over a field, in dimensions.** A composition algebra of dimension `r > 2` over a +field is a Cayley–Dickson double of a composition subalgebra of dimension `r / 2`. + +This is `ConicAlgebra.IsComposition.exists_bijective_cayToAlgebra` with `Module.rankAtStalk` +traded for `Module.finrank` — over a field the two agree — and with the subalgebra packaged as a +composition algebra in its own right, which is what lets the statement be applied to it again. -/ +theorem IsComposition.exists_isComposition_finrank_of_two_lt (h : C.IsComposition.{u, v, u}) + {r : ℕ} (hr : Module.finrank F A = r) (h2 : 2 < r) : + ∃ (B : NonAssocSubalgebra F A) (v : A) (s : ℕ), + 2 * s = r ∧ Module.finrank F B = s ∧ (C.restrict B).IsComposition.{u, v, u} ∧ + Function.Injective (cayToAlgebra C B v) ∧ + (∀ p q, cayToAlgebra C B v (p * q) = cayToAlgebra C B v p * cayToAlgebra C B v q) := by + have := h.isAlternative + obtain ⟨B, v, s, hs2, hsrank, hunit, hBreg, hbij, -, hmulmap, -⟩ := + h.exists_bijective_cayToAlgebra (isLGRing_of_field F) (Module.rankAtStalk_eq_of_finrank_eq hr) + h2 + refine ⟨B, v, s, hs2, ?_, ⟨hBreg.isGPRNonsingular, h.isMultiplicative.restrict⟩, hbij.1, + hmulmap⟩ + exact Module.finrank_of_rankAtStalk_eq ((rankAtStalk_toSubmodule B) ▸ hsrank) + +/-! ### The bottom of the tower: trivial conjugation forces dimension one -/ + +omit [SMulCommClass F A A] [IsScalarTower F A A] [Module.Finite F A] [Module.Projective F A] in +/-- A conic algebra over a nontrivial base is nonzero, because `n(1) = 1`. -/ +theorem nontrivial_of_conicAlgebra (C : ConicAlgebra F A) : Nontrivial A := by + rw [← not_subsingleton_iff_nontrivial] + intro hsub + have h1 : (1 : A) = 0 := Subsingleton.elim _ _ + have := C.norm_one + rw [h1, map_zero] at this + exact zero_ne_one this + +/-- **The last step of the descent.** A composition algebra over a field whose conjugation is the +identity has dimension at most one. + +The two characteristics are genuinely different. When `2 ≠ 0`, `conj x = x` reads `2x = t(x) · 1`, +so every element is a scalar multiple of `1` outright. When `2 = 0` it reads `t(x) · 1 = 0`, hence +`t ≡ 0` since `1 ≠ 0`; then `n(1, y) = t(y) = 0` for every `y`, so `1` is a nonzero vector in the +kernel of the polar form, the norm is not regular, and `GPR 19.11` leaves only dimension one. -/ +theorem IsComposition.finrank_le_one_of_conj_eq_id (h : C.IsComposition.{u, v, u}) + (hconj : ∀ x : A, C.conj x = x) : Module.finrank F A ≤ 1 := by + have := nontrivial_of_conicAlgebra C + have hkey : ∀ x : A, x + x = C.trace x • (1 : A) := fun x ↦ by + calc x + x = x + C.conj x := by rw [hconj] + _ = C.trace x • (1 : A) := C.add_conj x + by_cases h2 : (2 : F) = 0 + · by_contra hgt + replace hgt : 1 < Module.finrank F A := Nat.not_le.mp hgt + have htrace : ∀ x : A, C.trace x = 0 := by + intro x + have hx : C.trace x • (1 : A) = 0 := by + rw [← hkey x, ← two_smul F x, h2, zero_smul] + rcases smul_eq_zero.mp hx with h' | h' + · exact h' + · exact absurd h' one_ne_zero + have hmem : QuadraticMap.polarBilin C.norm 1 = 0 := by + ext y + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, ← C.trace_apply, htrace] + have hnotreg : ¬ C.norm.IsGPRRegular := fun hreg ↦ + one_ne_zero ((injective_iff_map_eq_zero _).mp hreg.1 1 hmem) + rcases h.isGPRRegular_or_finrank_eq_one with hreg | ⟨hdim, -⟩ + · exact hnotreg hreg + · omega + · have hinv : ∀ x : A, ((2 : F)⁻¹ * C.trace x) • (1 : A) = x := by + intro x + rw [mul_smul, ← hkey x, ← two_smul F x, inv_smul_smul₀ h2] + exact finrank_le_one (1 : A) fun x ↦ ⟨(2 : F)⁻¹ * C.trace x, hinv x⟩ + +/-! ### Climbing back up: commutative, then associative -/ + +/-- **A commutative composition algebra over a field has dimension at most two.** If it were +larger it would be a double `Cay(B, μ)`, and a commutative double forces the conjugation of `B` to +be the identity (`ConicAlgebra.exists_mul_ne_mul_cay`, contrapositive), which caps `B` at +dimension one and so the algebra itself at dimension two. -/ +theorem IsComposition.finrank_le_two_of_mul_comm (h : C.IsComposition.{u, v, u}) + (hcomm : ∀ a b : A, a * b = b * a) : Module.finrank F A ≤ 2 := by + by_contra hgt + replace hgt : 2 < Module.finrank F A := Nat.not_le.mp hgt + obtain ⟨B, v, s, hs2, hBrank, hBcomp, hinj, hmulmap⟩ := + h.exists_isComposition_finrank_of_two_lt rfl hgt + have hcay : ∀ p q : Cay (C.restrict B) (-C.norm v), p * q = q * p := + mul_comm_of_injective _ hinj hmulmap hcomm + have hid : ∀ b : B, (C.restrict B).conj b = b := by + intro b + by_contra hne + obtain ⟨x, y, hxy⟩ := exists_mul_ne_mul_cay (C.restrict B) (-C.norm v) hne + exact hxy (hcay x y) + have hle := hBcomp.finrank_le_one_of_conj_eq_id hid + omega + +/-- **An associative composition algebra over a field has dimension at most four.** The same +descent one rung higher: an associative double forces its input to be commutative +(`ConicAlgebra.exists_mul_mul_ne_mul_mul_cay`, contrapositive), which caps the input at dimension +two. This is what rules out an associative rank-eight algebra, and hence a ninth rung. -/ +theorem IsComposition.finrank_le_four_of_mul_assoc (h : C.IsComposition.{u, v, u}) + (hassoc : ∀ a b c : A, a * b * c = a * (b * c)) : Module.finrank F A ≤ 4 := by + by_contra hgt + replace hgt : 4 < Module.finrank F A := Nat.not_le.mp hgt + obtain ⟨B, v, s, hs2, hBrank, hBcomp, hinj, hmulmap⟩ := + h.exists_isComposition_finrank_of_two_lt rfl (by omega) + have := hBcomp.isAlternative + have hcay : ∀ p q r : Cay (C.restrict B) (-C.norm v), p * q * r = p * (q * r) := + mul_assoc_of_injective _ hinj hmulmap hassoc + have hcomm : ∀ a b : B, a * b = b * a := by + intro a b + by_contra hne + obtain ⟨x, y, z, hxyz⟩ := exists_mul_mul_ne_mul_mul_cay (C.restrict B) (-C.norm v) + (C.restrict B).conjIsInvolution_of_projective hne + exact hxyz (hcay x y z) + have hle := hBcomp.finrank_le_two_of_mul_comm hcomm + omega + +/-! ### `GPR 19.18` over a field -/ + +variable (F) in +/-- The induction behind `GPR 19.18` over a field, with an explicit fuel parameter `n` bounding +the dimension. The type varies from step to step — each rung is a subalgebra of the previous one — +so the induction quantifies over the carrier as well. -/ +private theorem finrank_mem_aux (n : ℕ) : + ∀ {X : Type v} [NonAssocRing X] [Module F X] [SMulCommClass F X X] [IsScalarTower F X X] + [Module.Finite F X] [Module.Projective F X] (D : ConicAlgebra F X), + D.IsComposition.{u, v, u} → Module.finrank F X ≤ n → + Module.finrank F X = 1 ∨ Module.finrank F X = 2 ∨ Module.finrank F X = 4 ∨ + Module.finrank F X = 8 := by + induction n with + | zero => + intro X _ _ _ _ _ _ D hD hle + have := nontrivial_of_conicAlgebra D + have := Module.finrank_pos (R := F) (M := X) + omega + | succ n ih => + intro X _ _ _ _ _ _ D hD hle + have := nontrivial_of_conicAlgebra D + have hpos := Module.finrank_pos (R := F) (M := X) + by_cases hsmall : Module.finrank F X ≤ 2 + · omega + · replace hsmall : 2 < Module.finrank F X := Nat.not_le.mp hsmall + obtain ⟨B, v, s, hs2, hBrank, hBcomp, hinj, hmulmap⟩ := + hD.exists_isComposition_finrank_of_two_lt rfl hsmall + have := hD.isAlternative + have : IsAlternative (Cay (D.restrict B) (-D.norm v)) := + isAlternative_of_injective _ hinj hmulmap + have hle4 := hBcomp.finrank_le_four_of_mul_assoc + (mul_assoc_of_isAlternative_cay (D.restrict B) (-D.norm v) inferInstance) + have hih := ih (D.restrict B) hBcomp (by omega) + omega + +/-- **`GPR 19.18` over a field.** A composition algebra over a field has dimension `1`, `2`, `4` +or `8`. + +The tower of `GPR 19.17` halves the dimension at every step, so it is a power of two; what stops +it at eight is the converse half of `GPR 18.14(c)`. A ninth rung would make the eight-dimensional +one associative (`ConicAlgebra.mul_assoc_of_isAlternative_cay`, applied to the alternativity that +every composition algebra over a field has), and +`ConicAlgebra.IsComposition.finrank_le_four_of_mul_assoc` says no associative composition algebra +gets past dimension four. -/ +theorem IsComposition.finrank_eq_one_or_two_or_four_or_eight (h : C.IsComposition.{u, v, u}) : + Module.finrank F A = 1 ∨ Module.finrank F A = 2 ∨ Module.finrank F A = 4 ∨ + Module.finrank F A = 8 := + finrank_mem_aux F (Module.finrank F A) C h le_rfl + +end ConicAlgebra + +/-! ### `GPR 19.18` over a commutative ring + +The rank is a fibrewise invariant, so the general case is the field case read off at a single +residue field. In particular **no LG hypothesis is needed**: the tower that proves the field case +runs over a field, and every field is an LG ring. -/ + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} + +/-- Over an LG ring, a rank-four composition algebra is associative. It is a double of its +rank-two associative commutative subalgebra, so `GPR 18.14(b)` applies. -/ +theorem IsComposition.mul_assoc_of_isLGRing_of_rankAtStalk_eq_four [Nontrivial k] + (h : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) (x y z : A) : + x * y * z = x * (y * z) := by + obtain ⟨B, a, s, hs, hB, ha, hreg, hbij, -, hmul, -⟩ := + h.exists_bijective_cayToAlgebra hLG hA (by omega) + have hs2 : s = 2 := by omega + subst s + let : Module.Finite k B := by + have := QuadraticForm.finite_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Finite.equiv (toSubmoduleEquiv B) + let : Module.Projective k B := by + have := QuadraticForm.projective_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Projective.of_equiv (toSubmoduleEquiv B) + have hBassoc := (C.restrict B).mul_assoc_of_isLGRing_of_rankAtStalk_eq_two hLG + ((rankAtStalk_toSubmodule B).symm.trans hB) + have hBcomm := (C.restrict B).mul_comm_of_isLGRing_of_rankAtStalk_eq_two hLG + ((rankAtStalk_toSubmodule B).symm.trans hB) + let : CommRing B := + { (inferInstance : NonAssocRing B) with mul_assoc := hBassoc, mul_comm := hBcomm } + let : Algebra k B := Algebra.ofModule + (fun r (p q : B) ↦ by exact smul_mul_assoc r p q) + (fun r (p q : B) ↦ by + rw [hBcomm p (r • q), hBcomm p q] + exact smul_mul_assoc r q p) + obtain ⟨px, hpx⟩ := hbij.2 x + obtain ⟨py, hpy⟩ := hbij.2 y + obtain ⟨pz, hpz⟩ := hbij.2 z + rw [← hpx, ← hpy, ← hpz, ← hmul, ← hmul, ← hmul, ← hmul] + exact congrArg (cayToAlgebra C B a) + (mul_assoc_cay (C.restrict B) (-C.norm a) + (C.restrict B).conjIsInvolution_of_projective px py pz) + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] + [Module.Projective k A] in +/-- Equality in a module can be checked after localizing at every maximal ideal, using tensor +product models for the localized modules. -/ +theorem eq_of_forall_localization_maximal (x y : A) + (hxy : ∀ (P : Ideal k) [P.IsMaximal], + (1 : Localization.AtPrime P) ⊗ₜ[k] x = + (1 : Localization.AtPrime P) ⊗ₜ[k] y) : x = y := + Module.eq_of_localization_maximal + (fun P _ ↦ Localization.AtPrime P ⊗[k] A) + (fun P _ ↦ TensorProduct.mk k (Localization.AtPrime P) A 1) + x y hxy + +/-- A finitely generated projective conic algebra of constant rank two over an arbitrary +commutative ring is commutative (`GPR 16.4`); for composition algebras this is the positive part of +`GPR 19.18(b)`. It is checked at each localization at a maximal ideal, where the algebra is `k[u]` +(`ConicAlgebra.mul_comm_of_isLGRing_of_rankAtStalk_eq_two`). -/ +theorem mul_comm_of_rankAtStalk_eq_two (C : ConicAlgebra k A) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x y : A) : x * y = y * x := by + apply eq_of_forall_localization_maximal (k := k) + intro P hP + let S := Localization.AtPrime P + have hSrank := Module.rankAtStalk_baseChange_of_eq S hA + have hLG : IsLGRing S := isLGRing_of_isLocalRing S + simpa only [one_tmul_mul] using + (C.baseChangeOfProjective S).mul_comm_of_isLGRing_of_rankAtStalk_eq_two hLG hSrank + (1 ⊗ₜ[k] x) (1 ⊗ₜ[k] y) + +/-- A finitely generated projective conic algebra of constant rank two over an arbitrary +commutative ring is associative (`GPR 16.4`); for composition algebras this is the positive part of +`GPR 19.18(b)`. It is checked at each localization at a maximal ideal, where the algebra is `k[u]` +(`ConicAlgebra.mul_assoc_of_isLGRing_of_rankAtStalk_eq_two`). -/ +theorem mul_assoc_of_rankAtStalk_eq_two (C : ConicAlgebra k A) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x y z : A) : x * y * z = x * (y * z) := by + apply eq_of_forall_localization_maximal (k := k) + intro P hP + let S := Localization.AtPrime P + have hSrank := Module.rankAtStalk_baseChange_of_eq S hA + have hLG : IsLGRing S := isLGRing_of_isLocalRing S + simpa only [one_tmul_mul] using + (C.baseChangeOfProjective S).mul_assoc_of_isLGRing_of_rankAtStalk_eq_two hLG hSrank + (1 ⊗ₜ[k] x) (1 ⊗ₜ[k] y) (1 ⊗ₜ[k] z) + +/-- A constant-rank-four composition algebra over an arbitrary commutative ring is +associative. This is the positive part of `GPR 19.18(c)`. -/ +theorem IsComposition.mul_assoc_of_rankAtStalk_eq_four + (h : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (x y z : A) : x * y * z = x * (y * z) := by + apply eq_of_forall_localization_maximal (k := k) + intro P hP + let S := Localization.AtPrime P + have hSrank := Module.rankAtStalk_baseChange_of_eq S hA + have hLG : IsLGRing S := isLGRing_of_isLocalRing S + simpa only [one_tmul_mul] using + (h.baseChangeOfProjective S).mul_assoc_of_isLGRing_of_rankAtStalk_eq_four hLG hSrank + (1 ⊗ₜ[k] x) (1 ⊗ₜ[k] y) (1 ⊗ₜ[k] z) + +/-- A constant-rank-two composition algebra over a nonzero ring has nontrivial conjugation. -/ +theorem IsComposition.exists_conj_ne_of_rankAtStalk_eq_two [Nontrivial k] + (h : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + ∃ x : A, C.conj x ≠ x := by + by_contra hn + push Not at hn + obtain ⟨P, hP⟩ := Ideal.exists_maximal k + let : P.IsMaximal := hP + let F := k ⧸ P + let : Field F := Ideal.Quotient.field P + let CF := C.baseChangeOfProjective F + have hconjF : ∀ x : F ⊗[k] A, CF.conj x = x := by + intro x + induction x with + | tmul r a => simp [CF, hn] + | add x y hx hy => simpa only [map_add] using congrArg₂ (· + ·) hx hy + have hdim : Module.finrank F (F ⊗[k] A) = 2 := + Module.finrank_baseChange_of_rankAtStalk_eq hA F + have hle := (h.baseChangeOfProjective F).finrank_le_one_of_conj_eq_id hconjF + omega + +/-- A constant-rank-four composition algebra over a nonzero ring is not commutative. -/ +theorem IsComposition.not_mul_comm_of_rankAtStalk_eq_four [Nontrivial k] + (h : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + ¬ ∀ x y : A, x * y = y * x := by + intro hcomm + have hassoc := h.mul_assoc_of_rankAtStalk_eq_four hA + let : CommRing A := + { (inferInstance : NonAssocRing A) with mul_assoc := hassoc, mul_comm := hcomm } + let : Algebra k A := Algebra.ofModule + (fun r (x y : A) ↦ by exact smul_mul_assoc r x y) + (fun r (x y : A) ↦ by exact (smul_comm r x y).symm) + obtain ⟨P, hP⟩ := Ideal.exists_maximal k + let : P.IsMaximal := hP + let F := k ⧸ P + let : Field F := Ideal.Quotient.field P + have hdim : Module.finrank F (F ⊗[k] A) = 4 := + Module.finrank_baseChange_of_rankAtStalk_eq hA F + have hle := (h.baseChangeOfProjective F).finrank_le_two_of_mul_comm fun x y ↦ mul_comm x y + omega + +/-- A constant-rank-eight composition algebra over a nonzero ring is not associative. -/ +theorem IsComposition.not_mul_assoc_of_rankAtStalk_eq_eight [Nontrivial k] + (h : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + ¬ ∀ x y z : A, x * y * z = x * (y * z) := by + intro hassoc + let : Ring A := { (inferInstance : NonAssocRing A) with mul_assoc := hassoc } + let : Algebra k A := Algebra.ofModule + (fun r (x y : A) ↦ by exact smul_mul_assoc r x y) + (fun r (x y : A) ↦ by exact (smul_comm r x y).symm) + obtain ⟨P, hP⟩ := Ideal.exists_maximal k + let : P.IsMaximal := hP + let F := k ⧸ P + let : Field F := Ideal.Quotient.field P + have hdim : Module.finrank F (F ⊗[k] A) = 8 := + Module.finrank_baseChange_of_rankAtStalk_eq hA F + have hle := (h.baseChangeOfProjective F).finrank_le_four_of_mul_assoc fun x y z ↦ + mul_assoc x y z + omega + +/-- A constant-rank-one conic algebra is isomorphic, as a unital non-associative algebra, to its +base ring. This is `GPR 19.18(a)` in the project's unbundled isomorphism convention. -/ +theorem exists_linearEquiv_map_one_map_mul_of_rankAtStalk_eq_one [Nontrivial k] + (C : ConicAlgebra k A) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) : + ∃ e : A ≃ₗ[k] k, e (1 : A) = 1 ∧ ∀ x y, e (x * y) = e x * e y := by + let e : A ≃ₗ[k] k := + { toLinearMap := C.unitForm + invFun := fun r ↦ r • (1 : A) + left_inv := fun x ↦ (C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA x).symm + right_inv := fun r ↦ by simp } + refine ⟨e, C.unitForm_one, fun x y ↦ ?_⟩ + change C.unitForm (x * y) = C.unitForm x * C.unitForm y + rw [C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA x, + C.eq_unitForm_smul_one_of_rankAtStalk_eq_one hA y] + simp only [smul_mul_smul_comm, map_smul, C.unitForm_one, smul_eq_mul, mul_one] + +/-- **`GPR 19.18`.** A composition algebra of constant rank over a nontrivial commutative ring has +rank `1`, `2`, `4` or `8`. + +Base change to the residue field at any maximal ideal is a composition algebra over a field of the +same dimension (`ConicAlgebra.finrank_quotient_tensor_eq_rankAtStalk`), so this is +`ConicAlgebra.IsComposition.finrank_eq_one_or_two_or_four_or_eight` read at one point of +`Spec k`. -/ +theorem IsComposition.rankAtStalk_eq_one_or_two_or_four_or_eight [Nontrivial k] + (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hrank : Module.rankAtStalk (R := k) A = fun _ ↦ r) : + r = 1 ∨ r = 2 ∨ r = 4 ∨ r = 8 := by + obtain ⟨𝔪, h𝔪⟩ := Ideal.exists_maximal k + have : 𝔪.IsMaximal := h𝔪 + let : Field (k ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + have hdim : Module.finrank (k ⧸ 𝔪) ((k ⧸ 𝔪) ⊗[k] A) = r := by + rw [finrank_quotient_tensor_eq_rankAtStalk, hrank] + have hfield := (h.baseChangeOfProjective (k ⧸ 𝔪)).finrank_eq_one_or_two_or_four_or_eight + rwa [hdim] at hfield + +/-- **Full `GPR 19.18`.** Besides the rank restriction, this records the algebraic structure in +each possible constant rank: rank one is the base ring; rank two is commutative associative with +nontrivial conjugation; rank four is associative but not commutative; and rank eight is +alternative but not associative. -/ +theorem IsComposition.rankAtStalk_classification [Nontrivial k] + (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) : + (r = 1 ∧ ∃ e : A ≃ₗ[k] k, e (1 : A) = 1 ∧ ∀ x y, e (x * y) = e x * e y) ∨ + (r = 2 ∧ (∀ x y : A, x * y = y * x) ∧ + (∀ x y z : A, x * y * z = x * (y * z)) ∧ ∃ x, C.conj x ≠ x) ∨ + (r = 4 ∧ (∀ x y z : A, x * y * z = x * (y * z)) ∧ + ¬ ∀ x y : A, x * y = y * x) ∨ + (r = 8 ∧ IsAlternative A ∧ ¬ ∀ x y z : A, x * y * z = x * (y * z)) := by + rcases h.rankAtStalk_eq_one_or_two_or_four_or_eight hA with h1 | h2 | h4 | h8 + · subst r + exact Or.inl ⟨rfl, exists_linearEquiv_map_one_map_mul_of_rankAtStalk_eq_one C hA⟩ + · subst r + exact Or.inr <| Or.inl ⟨rfl, C.mul_comm_of_rankAtStalk_eq_two hA, + C.mul_assoc_of_rankAtStalk_eq_two hA, h.exists_conj_ne_of_rankAtStalk_eq_two hA⟩ + · subst r + exact Or.inr <| Or.inr <| Or.inl + ⟨rfl, h.mul_assoc_of_rankAtStalk_eq_four hA, h.not_mul_comm_of_rankAtStalk_eq_four hA⟩ + · subst r + exact Or.inr <| Or.inr <| Or.inr + ⟨rfl, h.isAlternative_general, h.not_mul_assoc_of_rankAtStalk_eq_eight hA⟩ + +end ConicAlgebra + +namespace ConicAlgebra + +variable {F : Type u} {A : Type v} [Field F] [NonAssocRing A] [Module F A] + [SMulCommClass F A A] [IsScalarTower F A A] [Module.Finite F A] [Module.Projective F A] + +/-- **The dimension obstruction.** A conic algebra over a field whose dimension is none of +`1, 2, 4, 8` is not a composition algebra — no choice of conic norm on it permits composition. + +Applied to the sixteen-dimensional double of an octonion algebra this says the **sedenions** are +not a composition algebra (`GPR 19.23`), with no computation of an associator: the dimension alone +rules it out. -/ +theorem not_isComposition_of_finrank_notMem (C : ConicAlgebra F A) (h1 : Module.finrank F A ≠ 1) + (h2 : Module.finrank F A ≠ 2) (h4 : Module.finrank F A ≠ 4) + (h8 : Module.finrank F A ≠ 8) : + ¬ C.IsComposition.{u, v, u} := fun h ↦ by + rcases h.finrank_eq_one_or_two_or_four_or_eight with h' | h' | h' | h' + exacts [h1 h', h2 h', h4 h', h8 h'] + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/RankTwoSubalgebra.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/RankTwoSubalgebra.lean new file mode 100644 index 0000000000..42934ee024 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/RankTwoSubalgebra.lean @@ -0,0 +1,373 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Polynomial +public import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure + +/-! +# `GPR 19.16(b)`: rank greater than one gives a separable quadratic subalgebra + +A composition algebra `A` of rank at least two contains an element `u` whose discriminant +`t(u)² - 4n(u)` is a unit. By `GPR 19.8` (`Composition/QuadraticSubalgebra.lean`) the subalgebra +`k[u] = k·1 + k·u` is then free of rank two with regular norm — a *separable* quadratic subalgebra +— which is where the Cayley–Dickson tower of `GPR 19.17` starts. + +Starting the tower at a rank-two subalgebra rather than at `k·1` is not a convenience: in +characteristic 2 the norm `⟨1⟩` of `k·1` is non-singular but not regular, and +`ConicAlgebra.IsComposition.cay` needs a **regular** input (`Composition/CayleyDickson.lean`). +The content of this file is exactly that the obstruction can always be avoided. + +The field case is proved first and is the whole mathematical content; the passage to an LG ring is +the usual one, and reuses the machinery of the representation lemma +(`QuadraticForm/Representation.lean`) verbatim. + +## Main results + +* `ConicAlgebra.IsComposition.exists_isUnit_elementDiscriminant` : over a **field**. +* `ConicAlgebra.IsComposition.exists_isRegularRankTwoComposition` : the same, packaged as + `GPR 19.8(i)` — a regular rank-two composition subalgebra. +* `ConicAlgebra.discriminantForm` : `u ↦ t(u)² - 4n(u)` as a quadratic form, so that `GPR 11.8` + can turn it into a polynomial and the LG axiom can be applied to it. +* `ConicAlgebra.IsComposition.exists_isUnit_elementDiscriminant_of_isLGRing`, + `ConicAlgebra.IsComposition.exists_isRegularRankTwoComposition_of_isLGRing`, + `ConicAlgebra.IsComposition.exists_isRegularRankTwoComposition_of_rankAtStalk` : **`GPR + 19.16(b)`** over an LG ring, with the rank hypothesis stated at the residue fields (the form the + proof consumes) and in terms of `Module.rankAtStalk` (the form callers will have). + +## Implementation notes + +The two characteristics need different arguments over a field, and the characteristic-2 one is the +reason the statement is about the *discriminant* rather than about the trace. + +* **`2 ≠ 0`.** If every discriminant vanishes then `n` vanishes on `ker t`, hence so does the polar + form (`ker t` is a subspace, and `polar n u 1 = t(u)`), so `ker t` lies in the radical of `n`. + Over a field the radical of a composition norm vanishes + (`ConicAlgebra.IsComposition.isGPRNondegenerate`), so `t` is injective and the dimension is at + most one. + +* **`2 = 0`.** Here `t(u)² - 4n(u) = t(u)²`, so the hypothesis says exactly that the trace vanishes + identically, and no information about `n` is available over the base field: `t ≡ 0` is consistent + with a nonzero radical-free norm (`GPR 19.4`, the purely inseparable example, is a *conic* + algebra of this shape). The argument therefore moves to the algebraic closure — legitimate + precisely because non-singularity is stable under base change + (`ConicAlgebra.IsComposition.baseChangeOfProjective`), which is what that stability is *for*. + There, two steps: the polar form vanishes identically + (`ConicAlgebra.IsMultiplicative.polar_eq_zero_of_trace_eq_zero`, a short consequence of the + second linearization of multiplicativity), and then every element `x` equals `d • 1` for `d` a + square root of `n(x)`, because `x + d • 1` lies in the radical. So the dimension is at most one + there too, and dimension does not change under base change. + +Note that the characteristic-2 argument uses no alternativity and no regularity beyond the +vanishing of the radical over the algebraic closure; in particular it does not go through +`GPR 19.3`. + +Over an LG ring the discriminant is fed to the LG axiom as a polynomial. `A` need not be free, so +— exactly as in `QuadraticForm.exists_isUnit_apply_of_hasFullSupport` — the discriminant form is +pulled back along a presentation `kⁿ ↠ A`, where `GPR 11.8` applies. The residue-field hypothesis +of the axiom is discharged by the field case, since the base change of a composition algebra is a +composition algebra (`Composition/BaseChange.lean`) and the rank is unchanged. Note that the +representation lemma itself is *not* used: the discriminant form is not non-singular, so it is the +LG axiom and not `GPR 11.26` that does the work. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.8, 19.16(b). +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +open QuadraticMap (polar) + +namespace ConicAlgebra + +/-- A module spanned by a single element has dimension at most one. Used both here and in +`Composition/Fields/SepClosed.lean`, to produce an element outside `K · 1`. -/ +theorem finrank_le_one_of_forall_exists_smul {K : Type*} [Field K] {M : Type*} + [AddCommGroup M] [Module K M] (a : M) (h : ∀ x : M, ∃ d : K, x = d • a) : + Module.finrank K M ≤ 1 := by + have hrange : LinearMap.range (LinearMap.toSpanSingleton K M a) = ⊤ := by + rw [LinearMap.range_eq_top] + intro x + obtain ⟨d, rfl⟩ := h x + exact ⟨d, rfl⟩ + have hle := LinearMap.finrank_range_le (LinearMap.toSpanSingleton K M a) + rwa [hrange, finrank_top, Module.finrank_self] at hle + +section Field + +variable {F : Type u} {A : Type v} [Field F] [NonAssocRing A] [Module F A] + [SMulCommClass F A A] [IsScalarTower F A A] {C : ConicAlgebra F A} + +omit [SMulCommClass F A A] [IsScalarTower F A A] in +/-- **In characteristic 2 a traceless multiplicative conic norm has zero polar form.** + +Specialize the second linearization `n(xz, yw) + n(xw, yz) = n(x, y) n(z, w)` at `z = x`, `w = y`. +The degree-two identity turns `x²` and `y²` into multiples of `1`, so the first term is a multiple +of `n(1, 1) = t(1) = 0`; the linearized degree-two identity turns `yx` into `n(x, y)·1 + xy`, so the +second term is a combination of `t(xy) = 0` and `n(xy, xy) = 2n(xy) = 0`. What is left is +`n(x, y)² = 0`. + +Neither alternativity nor regularity is used, and the hypothesis is on the trace, not on the +algebra. -/ +theorem IsMultiplicative.polar_eq_zero_of_trace_eq_zero (h : C.IsMultiplicative) (h2 : (2 : F) = 0) + (ht : ∀ x : A, C.trace x = 0) (x y : A) : polar C.norm x y = 0 := by + have h11 : polar C.norm (1 : A) (1 : A) = 0 := by rw [← C.trace_apply, ht] + have hxy1 : polar C.norm (x * y) (1 : A) = 0 := by + rw [QuadraticMap.polar_comm, ← C.trace_apply, ht] + have hxyxy : polar C.norm (x * y) (x * y) = 0 := by + rw [QuadraticMap.polar_self, two_smul] + linear_combination C.norm (x * y) * h2 + have hxx : x * x = -(C.norm x • (1 : A)) := by rw [C.mul_self_eq, ht, zero_smul, zero_sub] + have hyy : y * y = -(C.norm y • (1 : A)) := by rw [C.mul_self_eq, ht, zero_smul, zero_sub] + have hyx : y * x = -(polar C.norm x y • (1 : A)) - x * y := by + have hmm := C.mul_add_mul x y + rw [ht, ht, zero_smul, zero_smul, zero_add, zero_sub] at hmm + linear_combination (norm := module) hmm + have key := h.polar_mul_add_polar_mul x y x y + rw [hxx, hyy, hyx] at key + simp only [QuadraticMap.polar_neg_left, QuadraticMap.polar_neg_right, + QuadraticMap.polar_smul_left, QuadraticMap.polar_smul_right, QuadraticMap.polar_sub_right, + smul_eq_mul, h11, hxy1, hxyxy] at key + exact mul_self_eq_zero.mp (by linear_combination -key) + +omit [SMulCommClass F A A] [IsScalarTower F A A] in +/-- **Over an algebraically closed field of characteristic 2, a traceless multiplicative conic +algebra with vanishing radical is spanned by `1`.** + +Every `x` has `n(x) = d²` for some `d`, and then `n(x + d • 1) = n(x) + d² = 2n(x) = 0` while the +polar form vanishes identically by +`ConicAlgebra.IsMultiplicative.polar_eq_zero_of_trace_eq_zero`; so `x + d • 1` lies in the radical, +which is zero. -/ +theorem IsMultiplicative.exists_eq_smul_one_of_isAlgClosed [IsAlgClosed F] (h : C.IsMultiplicative) + (h2 : (2 : F) = 0) (ht : ∀ x : A, C.trace x = 0) (hrad : C.norm.radical = ⊥) (x : A) : + ∃ d : F, x = d • (1 : A) := by + obtain ⟨d, hd⟩ := IsAlgClosed.exists_pow_nat_eq (C.norm x) (n := 2) two_pos + refine ⟨-d, ?_⟩ + have hmem : x + d • (1 : A) ∈ C.norm.radical := by + refine ⟨?_, ?_⟩ + · rw [C.norm_add, QuadraticMap.map_smul, C.norm_one, + h.polar_eq_zero_of_trace_eq_zero h2 ht, smul_eq_mul, mul_one, ← sq, hd, add_zero] + linear_combination C.norm x * h2 + · ext z + simp only [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] + exact h.polar_eq_zero_of_trace_eq_zero h2 ht _ z + rw [hrad, Submodule.mem_bot] at hmem + rw [neg_smul] + linear_combination (norm := module) hmem + +variable [Module.Finite F A] [Module.Projective F A] + +omit [SMulCommClass F A A] [IsScalarTower F A A] [Module.Finite F A] [Module.Projective F A] in +/-- If the trace of a conic algebra over a field is injective, the algebra has dimension at most +one. Used in characteristic `≠ 2`, where `ker t` is shown to lie in the radical of the norm. -/ +private theorem finrank_le_one_of_trace_injective (hinj : Function.Injective C.trace) : + Module.finrank F A ≤ 1 := by + simpa using LinearMap.finrank_le_finrank_of_injective (f := C.trace) hinj + +/-- **The field case of `GPR 19.16(b)`.** A composition algebra of dimension at least two over a +field contains an element of nonzero — hence invertible — discriminant, so by `GPR 19.8` it +contains a separable quadratic subalgebra. + +The two characteristics are genuinely different arguments; see the module docstring. -/ +theorem IsComposition.exists_isUnit_elementDiscriminant (h : C.IsComposition.{u, v, u}) + (hrank : 1 < Module.finrank F A) : ∃ u : A, IsUnit (C.elementDiscriminant u) := by + by_contra hcon + have hzero : ∀ u : A, C.elementDiscriminant u = 0 := fun u ↦ + not_not.mp fun hne ↦ hcon ⟨u, isUnit_iff_ne_zero.mpr hne⟩ + rcases eq_or_ne (2 : F) 0 with h2 | h2 + · -- Characteristic 2: the trace vanishes identically, and the algebraic closure is a line. + have ht : ∀ x : A, C.trace x = 0 := by + intro x + have hx := hzero x + rw [elementDiscriminant, show (4 : F) = 2 * 2 by norm_num, h2, zero_mul, zero_mul, + sub_zero] at hx + exact pow_eq_zero_iff two_ne_zero |>.mp hx + set K := AlgebraicClosure F with hKdef + have hK := h.baseChangeOfProjective K + have h2K : (2 : K) = 0 := by + have hmap : algebraMap F K (2 : F) = 0 := by rw [h2, map_zero] + rwa [map_ofNat] at hmap + have htK : ∀ X : K ⊗[F] A, (C.baseChangeOfProjective K).trace X = 0 := by + intro X + induction X with + | tmul s a => rw [baseChangeOfProjective_trace_apply_tmul, ht, zero_smul] + | add X Y hX hY => rw [map_add, hX, hY, add_zero] + have hrankK : 1 < Module.finrank K (K ⊗[F] A) := by rwa [Module.finrank_baseChange] + exact absurd hrankK (not_lt.mpr (finrank_le_one_of_forall_exists_smul (1 : K ⊗[F] A) + (hK.isMultiplicative.exists_eq_smul_one_of_isAlgClosed h2K htK hK.isGPRNondegenerate))) + · -- Characteristic ≠ 2: the kernel of the trace lies in the radical of the norm. + have h4 : (4 : F) ≠ 0 := fun h4 ↦ h2 <| by + have h22 : (2 : F) * 2 = 0 := by linear_combination h4 + rcases mul_eq_zero.mp h22 with hz | hz <;> exact hz + have hrad : C.norm.radical = ⊥ := h.isGPRNondegenerate + have hnorm : ∀ u : A, C.trace u = 0 → C.norm u = 0 := by + intro u hu + have hu' := hzero u + rw [elementDiscriminant, hu] at hu' + have h4n : (4 : F) * C.norm u = 0 := by linear_combination -hu' + rcases mul_eq_zero.mp h4n with hz | hz + · exact absurd hz h4 + · exact hz + have hker : ∀ u : A, C.trace u = 0 → u = 0 := by + intro u hu + have hmem : u ∈ C.norm.radical := by + refine ⟨hnorm u hu, ?_⟩ + ext y + set c : F := (2 : F)⁻¹ * C.trace y with hc + set y₀ : A := y - c • (1 : A) with hy₀ + have hty₀ : C.trace y₀ = 0 := by + rw [hy₀, map_sub, map_smul, C.trace_one, smul_eq_mul, hc] + field_simp + ring + have h1 : polar C.norm u (1 : A) = 0 := by + rw [QuadraticMap.polar_comm, ← C.trace_apply, hu] + have h0 : polar C.norm u y₀ = 0 := by + have hadd := C.norm_add u y₀ + rw [hnorm u hu, hnorm y₀ hty₀, + hnorm _ (by rw [map_add, hu, hty₀, add_zero])] at hadd + linear_combination -hadd + have hy : y = y₀ + c • (1 : A) := by rw [hy₀]; abel + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, hy, + QuadraticMap.polar_add_right, QuadraticMap.polar_smul_right, h0, h1, smul_zero, add_zero] + rwa [hrad, Submodule.mem_bot] at hmem + refine absurd hrank + (not_lt.mpr (finrank_le_one_of_trace_injective (C := C) fun X Y hXY ↦ ?_)) + have hsub := hker (X - Y) (by rw [map_sub, hXY, sub_self]) + linear_combination (norm := module) hsub + +/-- **The field case of `GPR 19.16(b)`, packaged.** A composition algebra of dimension at least two +over a field contains a regular rank-two composition subalgebra `k[u]` (`GPR 19.8(i)`). -/ +theorem IsComposition.exists_isRegularRankTwoComposition (h : C.IsComposition.{u, v, u}) + (hrank : 1 < Module.finrank F A) : ∃ u : A, C.IsRegularRankTwoComposition u := by + obtain ⟨u, hu⟩ := h.exists_isUnit_elementDiscriminant hrank + exact ⟨u, (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mpr hu⟩ + +end Field + +/-! ### Globalization over an LG ring -/ + +section LGRing + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + (C : ConicAlgebra k A) + +/-- The element discriminant `t(u)² - 4n(u)` of `GPR 19.8`, as a **quadratic form** on `A`. + +The trace is linear and the norm is quadratic, so this is quadratic; packaging it as a +`QuadraticForm` is what lets `GPR 11.8` turn it into a polynomial and hence hand it to the LG +axiom. -/ +def discriminantForm : QuadraticForm k A := QuadraticMap.sq.comp C.trace - (4 : k) • C.norm + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +@[simp] theorem discriminantForm_apply (u : A) : + C.discriminantForm u = C.elementDiscriminant u := by + simp only [discriminantForm, sub_apply, smul_apply, + QuadraticMap.comp_apply, QuadraticMap.sq_apply, smul_eq_mul, elementDiscriminant] + ring + +/-- The discriminant form commutes with base change: on `1 ⊗ₜ a` both sides are the image of +`t(a)² - 4n(a)`, and a quadratic form on a base changed module is determined by those values. -/ +theorem discriminantForm_baseChangeOfProjective (S : Type w) [CommRing S] [Algebra k S] : + (C.baseChangeOfProjective S).discriminantForm = + C.discriminantForm.baseChangeOfProjective S := by + refine _root_.baseChange_ext fun a ↦ ?_ + rw [discriminantForm_apply, QuadraticForm.baseChangeOfProjective_tmul, discriminantForm_apply, + elementDiscriminant, elementDiscriminant, baseChangeOfProjective_trace_apply_tmul, + baseChangeOfProjective_norm_apply_tmul] + simp only [Algebra.smul_def, map_sub, map_pow, map_mul, map_ofNat, mul_one] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The dimension of the fibre `(k ⧸ 𝔪) ⊗ A` is mathlib's `Module.rankAtStalk` at `𝔪`. + +The two differ only in which model of the residue field they use: `rankAtStalk` goes through +`Ideal.ResidueField`, the residue field of the localization, whereas the LG axiom speaks about +`k ⧸ 𝔪`. For `𝔪` maximal these agree, and base change along the comparison map does not change +the rank. -/ +theorem finrank_quotient_tensor_eq_rankAtStalk (𝔪 : Ideal k) [𝔪.IsMaximal] : + Module.finrank (k ⧸ 𝔪) ((k ⧸ 𝔪) ⊗[k] A) = + Module.rankAtStalk A ⟨𝔪, inferInstance⟩ := by + let : Field (k ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + rw [← Ideal.finrank_fiber_eq_rankAtStalk, + ← Module.finrank_baseChange (R := 𝔪.ResidueField) (S := k ⧸ 𝔪) + (M' := (k ⧸ 𝔪) ⊗[k] A), + (TensorProduct.AlgebraTensorModule.cancelBaseChange k (k ⧸ 𝔪) 𝔪.ResidueField + 𝔪.ResidueField A).finrank_eq] + +/-- **`GPR 19.16(b)`.** Over an LG ring, a composition algebra whose rank exceeds one at every +residue field contains an element of invertible discriminant. + +This is where the LG axiom is applied, and the shape is that of the representation lemma +(`QuadraticForm/Representation.lean`): `A` need not be free, so pull the discriminant form back +along a presentation `kⁿ ↠ A`, where `GPR 11.8` writes it as a polynomial. Over each residue field +the base changed algebra is again a composition algebra +(`ConicAlgebra.IsComposition.baseChangeOfProjective`) of dimension at least two, so +`exists_isUnit_elementDiscriminant` supplies the required unit value there, and `π ⊗ κ` stays +surjective so the witness lifts to the free module. The LG axiom then descends a witness to `k`. -/ +theorem IsComposition.exists_isUnit_elementDiscriminant_of_isLGRing {C : ConicAlgebra k A} + (hLG : IsLGRing k) (h : C.IsComposition.{u, v, u}) + (hrank : ∀ (𝔪 : Ideal k) [𝔪.IsMaximal], + 1 < Module.finrank (k ⧸ 𝔪) ((k ⧸ 𝔪) ⊗[k] A)) : + ∃ u : A, IsUnit (C.elementDiscriminant u) := by + obtain ⟨n, π, hπ⟩ := Module.Finite.exists_fin' k A + set bm : Module.Basis (Fin n) k (Fin n → k) := Pi.basisFun k (Fin n) with hbm + set q' : QuadraticForm k (Fin n → k) := C.discriminantForm.comp π with hq' + have hrep : (QuadraticForm.toMvPolynomial q' bm).RepresentsUnit k := by + refine (hLG n _).mpr fun 𝔪 _ ↦ ?_ + let : Field (k ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + obtain ⟨x, hx⟩ := + (h.baseChangeOfProjective (k ⧸ 𝔪)).exists_isUnit_elementDiscriminant (hrank 𝔪) + rw [← discriminantForm_apply, C.discriminantForm_baseChangeOfProjective] at hx + obtain ⟨y, rfl⟩ := LinearMap.baseChange_surjective (k ⧸ 𝔪) hπ x + set b' := Algebra.TensorProduct.basis (k ⧸ 𝔪) bm with hb' + refine ⟨fun i ↦ b'.repr y i, ?_⟩ + have hy : ∑ i, b'.repr y i • ((1 : k ⧸ 𝔪) ⊗ₜ[k] bm i) = y := by + simpa [hb', Algebra.TensorProduct.basis_apply] using b'.sum_repr y + rw [QuadraticForm.aeval_toMvPolynomial, hy, hq', + QuadraticForm.baseChangeOfProjective_comp, QuadraticMap.comp_apply] + exact hx + obtain ⟨t, ht⟩ := hrep + rw [QuadraticForm.aeval_toMvPolynomial_self] at ht + have hsum : ∑ i, t i • bm i = t := by + simpa [hbm] using (Pi.basisFun k (Fin n)).sum_repr t + rw [hsum, hq', QuadraticMap.comp_apply, discriminantForm_apply] at ht + exact ⟨π t, ht⟩ + +/-- **`GPR 19.16(b)`, packaged.** Over an LG ring, a composition algebra of rank greater than one +contains a regular rank-two composition subalgebra `k[u]` — the subalgebra the Cayley–Dickson +tower starts from. -/ +theorem IsComposition.exists_isRegularRankTwoComposition_of_isLGRing {C : ConicAlgebra k A} + (hLG : IsLGRing k) (h : C.IsComposition.{u, v, u}) + (hrank : ∀ (𝔪 : Ideal k) [𝔪.IsMaximal], + 1 < Module.finrank (k ⧸ 𝔪) ((k ⧸ 𝔪) ⊗[k] A)) : + ∃ u : A, C.IsRegularRankTwoComposition u := by + obtain ⟨u, hu⟩ := h.exists_isUnit_elementDiscriminant_of_isLGRing hLG hrank + exact ⟨u, (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mpr hu⟩ + +/-- **`GPR 19.16(b)`, in the project's standard rank language.** Over an LG ring, a composition +algebra of rank greater than one everywhere on `Spec k` contains a regular rank-two composition +subalgebra. This is the form the Cayley–Dickson tower of `GPR 19.17` will consume, where the rank +is constant and greater than one. -/ +theorem IsComposition.exists_isRegularRankTwoComposition_of_rankAtStalk {C : ConicAlgebra k A} + (hLG : IsLGRing k) (h : C.IsComposition.{u, v, u}) + (hrank : ∀ 𝔭 : PrimeSpectrum k, 1 < Module.rankAtStalk A 𝔭) : + ∃ u : A, C.IsRegularRankTwoComposition u := + h.exists_isRegularRankTwoComposition_of_isLGRing hLG fun 𝔪 _ ↦ by + rw [finrank_quotient_tensor_eq_rankAtStalk] + exact hrank _ + +end LGRing + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Capstone.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Capstone.lean new file mode 100644 index 0000000000..2bd5973606 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Capstone.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Classification + +/-! +# Splitting octonion algebras from their quadratic étale subalgebras + +This file formalizes the final paragraph of `GN Example 3.15`. Let `k` be an LG ring over which +every quadratic étale algebra is split. A rank-eight composition algebra contains a regular +rank-two composition subalgebra by `GPR 19.16(b)`. The hypothesis makes that subalgebra split, so +an elementary idempotent in it gives one in the ambient algebra. The reduced classification +`GPR 22.16` then makes the octonion algebra split. + +The hypothesis is stated only for the regular rank-two subalgebras `k[u]` which the proof +consumes. This avoids replacing the mathematical condition by the stronger assertion that every +rank-two conic algebra, with arbitrary norm data, is split. + +## Main results + +* `ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_adjoinElement` : every composition + algebra of constant rank two, four, or eight over the stated LG ring is split. +* `ConicAlgebra.IsComposition.isSplitOfRank_eight_of_forall_isSplit_adjoinElement` : every + rank-eight composition algebra over the stated LG ring is split. + +## Implementation notes + +The conic norm bundled by `GPR 19.16(b)` is initially existential. Its uniqueness on the finite +projective quadratic subalgebra identifies it with the ambient restricted norm (`GPR 19.8`), +which is the step that transports the elementary idempotent into the octonion algebra. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Example 3.15. +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.8, 19.16(b), + 22.9, 22.16. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] + [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} + +omit [Module.Finite k A] [Module.Projective k A] in +/-- An elementary idempotent of a regular quadratic subalgebra remains elementary in the ambient +conic algebra. The substantive input is uniqueness of the conic norm on the finite projective +subalgebra (`GPR 19.8`). -/ +theorem RegularRankTwoCompositionStructure.isElementaryIdempotent_ambient {u : A} + (h : C.RegularRankTwoCompositionStructure u) {c : C.adjoinElement u} + (hc : h.conic.IsElementaryIdempotent c) : C.IsElementaryIdempotent (c : A) := by + have hnorm := h.conic_norm_eq_normAdjoinElement + constructor + · rw [← C.normAdjoinElement_apply u c, ← hnorm] + exact hc.norm_eq_zero + · have htrace := hc.trace_eq_one + rw [trace_apply, hnorm] at htrace + rw [trace_apply] + exact htrace + +/-- **Final paragraph of `GN Example 3.15`, in every constant rank greater than one.** Let `k` be +an LG ring such that every regular rank-two composition subalgebra `k[u]` is split. Then every +composition algebra over `k` of constant rank `2`, `4`, or `8` is split. + +The hypothesis is precisely the "every quadratic étale algebra is split" input needed by the +proof, specialized to the subalgebras produced by `GPR 19.16(b)`. Over a field this is the class +of fields — separably closed fields among them — over which `GPR 23.12` gives a unique composition +algebra in each dimension. -/ +theorem IsComposition.isSplitOfRank_of_forall_isSplit_adjoinElement {r : ℕ} + (hcomp : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : r = 2 ∨ r = 4 ∨ r = 8) + (hsplit : ∀ (u : A) (h : C.RegularRankTwoCompositionStructure u), + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + letI : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + letI : Module.Projective k (C.adjoinElement u) := h.projective + h.conic.IsSplitOfRank 2) : C.IsSplitOfRank r := by + rcases subsingleton_or_nontrivial k with hk | hk + · let := hk + rcases hr with rfl | rfl | rfl <;> exact Isomorphic.of_subsingleton + let := hk + obtain ⟨u, ⟨h⟩⟩ := hcomp.exists_isRegularRankTwoComposition_of_rankAtStalk hLG (by + intro p + simp only [hA] + rcases hr with rfl | rfl | rfl <;> omega) + let := C.adjoinElementCommRing u + let := C.adjoinElementAlgebra u + let : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + let : Module.Projective k (C.adjoinElement u) := h.projective + obtain ⟨c, hc⟩ := + (hsplit u h).hasElementaryIdempotent_of_two_or_four_or_eight (Or.inl rfl) + have hcA : C.IsElementaryIdempotent (c : A) := + h.isElementaryIdempotent_ambient hc + have hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA + (by rcases hr with rfl | rfl | rfl <;> omega) + let : IsAlternative A := + hcomp.isMultiplicative.isAlternative hreg.isGPRNondegenerate + rcases hr with rfl | rfl | rfl + · exact hcA.isSplitOfRank_two hA + · exact hcA.isSplitOfRank_four_of_isLGRing hLG hcomp hA + · exact hcA.isSplitOfRank_eight_of_isLGRing hLG hcomp hA + +/-- **Final paragraph of `GN Example 3.15`.** Let `k` be an LG ring such that every regular +rank-two composition subalgebra `k[u]` is split. Then every constant-rank-eight composition +algebra over `k` is split. This is the octonion case of +`ConicAlgebra.IsComposition.isSplitOfRank_of_forall_isSplit_adjoinElement`, and it is the +statement `GN Example 3.15` makes for the ring of all algebraic integers. -/ +theorem IsComposition.isSplitOfRank_eight_of_forall_isSplit_adjoinElement + (hcomp : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) + (hsplit : ∀ (u : A) (h : C.RegularRankTwoCompositionStructure u), + letI := C.adjoinElementCommRing u + letI := C.adjoinElementAlgebra u + letI : Module.Finite k (C.adjoinElement u) := C.finite_adjoinElement u + letI : Module.Projective k (C.adjoinElement u) := h.projective + h.conic.IsSplitOfRank 2) : C.IsSplitOfRank 8 := + hcomp.isSplitOfRank_of_forall_isSplit_adjoinElement hLG hA (Or.inr (Or.inr rfl)) hsplit + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean new file mode 100644 index 0000000000..35a1899bea --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean @@ -0,0 +1,565 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankTwo +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Reducedness +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ConstantRank +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Semilocal +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentFactor + +/-! +# Reduced and split composition algebras (`GPR 22.16`) + +The structure theorems in ranks two, four, and eight identify a reduced composition algebra with +the split quadratic algebra, twisted matrices on a line bundle, or twisted Zorn matrices on a +rank-three projective module. If constant-rank finite projectives over every idempotent factor are +free, the latter two presentations are the standard split models. This proves the converse half +of `GPR 22.16`; the LG-ring theorem follows because idempotent factors remain LG and their +constant-rank projectives are free (`GPR 11.24`, `GN 2.6(b)`). + +⚠ **On "division".** In this file "division algebra" is expressed by +`ConicAlgebra.HasTwoSidedInverses` — every nonzero element has a two-sided inverse — which in +general is weaker than being a division algebra in the sense of `GPR 8.6`. For composition algebras +over a field, which are alternative, the two agree once `1 ≠ 0` (`GPR 13.8`, +`ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses`), and +`ConicAlgebra.IsComposition.isSplitOfRank_iff_not_isDivision` restates the field case of `GPR 22.18` +with `IsDivision`; both are in `Composition/Fields/Basic.lean`. + +## Main results + +* `ConicAlgebra.isSplitOfRank_one` : the rank-one case. +* `ConicAlgebra.IsElementaryIdempotent.isSplitOfRank_two` : the rank-two case. +* `ConicAlgebra.IsElementaryIdempotent.isSplitOfRank_four_of_isLGRing` : the rank-four case. +* `ConicAlgebra.IsElementaryIdempotent.isSplitOfRank_eight_of_isLGRing` : the rank-eight case. +* `ConicAlgebra.IsReduced.isSplit_of_projectiveConstantRankFree` : the converse of + **`GPR 22.16`** under `GPR`'s own hypothesis, that constant-rank finite projective `k`-modules + are free; `ConicAlgebra.IsElementaryIdempotent.ProjectiveConstantRankFree.onFactors` passes the + hypothesis to the idempotent factors. +* `ConicAlgebra.IsReduced.isSplit_of_projective_constantRank_free_on_factors` : the same under + the factorwise freeness hypothesis. +* `ConicAlgebra.IsReduced.isSplit_of_isLGRing` : **`GPR 22.16`**, reduced implies split over an + LG ring. +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_isGPRIsotropic_of_projectiveConstantRankFree`, + `IsComposition.isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_projectiveConstantRankFree` : + **`GPR 22.18`** (i) ↔ (ii) ↔ (iii) under `GPR`'s hypothesis, in ranks two, four, and eight. +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_isGPRIsotropic_of_isLGRing`, + `ConicAlgebra.IsComposition.isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_isLGRing`, + `ConicAlgebra.IsComposition.isSplitOfRank_of_isometryEquiv_dualProd` : the LG-ring case. +* `ConicAlgebra.isGPRIsotropic_norm_of_isometryEquiv_dualProd` : a hyperbolic norm is isotropic + (`GPR 22.9`, (iv) ⇒ (iii)), with no hypothesis on the hyperbolic module. +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_not_hasTwoSidedInverses` : over a field, splitness + is equivalent to failure of the division property (**`GPR 22.18`**). +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_not_anisotropic_of_pid` : over a PID, splitness + is equivalent to the existence of a nonzero null vector (**`GPR 22.19`**). +* `ConicAlgebra.IsComposition.isSplitOfRank_iff_not_noZeroDivisors_of_pid` : over a PID, + splitness is equivalent to having zero divisors (**`GPR 22.19`**). + +Together with `isSplitOfRank_iff_isGPRIsotropic_of_pid` these are conditions (ii)–(v) of +`GPR 22.19`. Condition (i), splitness after extension to the fraction field, is +`Composition/Fields/FractionField.lean`. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Lemma 2.6(b). +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.24, + 22.16, 22.18--22.19. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] + [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {c : A} + +omit [SMulCommClass k A A] [IsAlternative A] in +/-- A constant-rank-one conic algebra over a nontrivial ring is the standard rank-one algebra. -/ +theorem isSplitOfRank_one [Nontrivial k] + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 1) : C.IsSplitOfRank 1 := + exists_isometryEquiv_map_one_map_mul_of_rankAtStalk_eq_one C (baseRing k) hA + (by rw [Module.rankAtStalk_self]; rfl) + +namespace IsElementaryIdempotent + +/-- The factor-stable freeness hypothesis used in the converse of `GPR 22.16`: every finite +projective module of constant rank over every idempotent factor of `k` is free. -/ +def ProjectiveConstantRankFreeOnFactors (k : Type u) [CommRing k] : Prop := + ∀ (e : k), IsIdempotentElem e → + ∀ (M : Type (max u v)) [AddCommGroup M] [Module (k ⧸ Ideal.span {1 - e}) M] + [Module.Finite (k ⧸ Ideal.span {1 - e}) M] + [Module.Projective (k ⧸ Ideal.span {1 - e}) M], ∀ (r : ℕ), + (Module.rankAtStalk (R := k ⧸ Ideal.span {1 - e}) M = fun _ ↦ r) → + Module.Free (k ⧸ Ideal.span {1 - e}) M + +/-- **`GPR`'s freeness hypothesis** in `GPR 22.16`–`22.18`: every finitely generated projective +`k`-module of constant rank (in the universe `w`) is free. It holds over every LG ring +(`ProjectiveConstantRankFree.of_isLGRing`, `GPR 11.24`), and its factorwise form +`ProjectiveConstantRankFreeOnFactors` follows from it (`ProjectiveConstantRankFree.onFactors`). -/ +def ProjectiveConstantRankFree (k : Type u) [CommRing k] : Prop := + ∀ (M : Type w) [AddCommGroup M] [Module k M] [Module.Finite k M] [Module.Projective k M], + ∀ (r : ℕ), (Module.rankAtStalk (R := k) M = fun _ ↦ r) → Module.Free k M + +/-- `GPR`'s freeness hypothesis implies its factorwise form: a constant-rank projective module over +an idempotent factor `k ⧸ (1 - e)` is free, by `Module.free_of_forall_free_of_isIdempotentElem`. -/ +theorem ProjectiveConstantRankFree.onFactors (h : ProjectiveConstantRankFree.{u, max u v} k) : + ProjectiveConstantRankFreeOnFactors.{u, v} k := + fun _ he M _ _ _ _ r hM ↦ Module.free_of_forall_free_of_isIdempotentElem he + (fun N _ _ _ _ r hN ↦ h N r hN) M r hM + +/-- Over an LG ring every finitely generated projective module of constant rank is free +(`GPR 11.24`, `GN 2.6(b)`), so `GPR`'s freeness hypothesis holds. -/ +theorem ProjectiveConstantRankFree.of_isLGRing (hLG : IsLGRing k) : + ProjectiveConstantRankFree.{u, w} k := + fun M _ _ _ _ r hM ↦ Module.free_of_isLGRing_of_rankAtStalk_eq hLG r M hM + +private theorem finrank_eq_of_rankAtStalk_eq [Nontrivial k] + {M : Type v} [AddCommGroup M] [Module k M] [Module.Free k M] + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ n) : Module.finrank k M = n := by + obtain ⟨p, hp⟩ := Ideal.exists_maximal k + have h := congrFun (Module.rankAtStalk_eq_finrank_of_free.symm.trans hM) + ⟨p, hp.isPrime⟩ + simpa only [Pi.natCast_apply, Nat.cast_id] using h + +omit [IsAlternative A] in +/-- **`GPR 22.16`, rank two:** a reduced constant-rank-two composition algebra is split. -/ +theorem isSplitOfRank_two (hc : C.IsElementaryIdempotent c) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : C.IsSplitOfRank 2 := by + let e := hc.splitEtaleEquiv hA + have hiso : (splitEtale k).Isomorphic C := + ⟨⟨e, fun x ↦ by + rw [splitEtale_norm] + exact hc.norm_splitEtaleEquiv hA x⟩, + hc.splitEtaleEquiv_one hA, hc.splitEtaleEquiv_mul hA⟩ + exact hiso.symm + +/-- **`GPR 22.16`, rank four:** over a nontrivial LG ring, a reduced constant-rank-four +composition algebra is split. -/ +theorem isSplitOfRank_four_of_isLGRing [Nontrivial k] + (hc : C.IsElementaryIdempotent c) (hLG : IsLGRing k) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : C.IsSplitOfRank 4 := by + let L := TwistingModule (k := k) c + let : Module.Finite k L := IsAlternative.finite_peirceComponent true false + let : Module.Projective k L := + IsAlternative.projective_peirceComponent hc.mul_self true false + have hL : Module.rankAtStalk (R := k) L = 1 := + hc.rankAtStalk_offDiagonal_eq_one hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) hA true + let : Module.Free k L := Module.free_of_isLGRing_of_rankAtStalk_eq hLG 1 L hL + let b : Module.Basis Unit k L := + Module.basisUnique Unit (finrank_eq_of_rankAtStalk_eq hL) + exact (hc.isomorphic_twistedMat (k := k) hcomp hA).symm.trans + (isomorphic_twistedMat_ofBasis k b) + +/-- **`GPR 22.16`, rank four under its abstract freeness hypothesis.** -/ +theorem isSplitOfRank_four_of_projective_constantRank_free [Nontrivial k] + (hc : C.IsElementaryIdempotent c) + (hfree : ∀ (M : Type v) [AddCommGroup M] [Module k M] [Module.Finite k M] + [Module.Projective k M], ∀ (r : ℕ), + (Module.rankAtStalk (R := k) M = fun _ ↦ r) → Module.Free k M) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : C.IsSplitOfRank 4 := by + let L := TwistingModule (k := k) c + let : Module.Finite k L := IsAlternative.finite_peirceComponent true false + let : Module.Projective k L := + IsAlternative.projective_peirceComponent hc.mul_self true false + have hL : Module.rankAtStalk (R := k) L = fun _ ↦ 1 := + hc.rankAtStalk_offDiagonal_eq_one hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) hA true + let : Module.Free k L := hfree L 1 hL + let b : Module.Basis Unit k L := Module.basisUnique Unit (finrank_eq_of_rankAtStalk_eq hL) + exact (hc.isomorphic_twistedMat (k := k) hcomp hA).symm.trans + (isomorphic_twistedMat_ofBasis k b) + +/-- **`GPR 22.19`, rank four:** over a PID, a reduced constant-rank-four composition algebra is +split. The twisting line is projective, hence flat and torsion-free, and a finite torsion-free +module over a PID is free. -/ +theorem isSplitOfRank_four_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : C.IsSplitOfRank 4 := by + let L := TwistingModule (k := k) c + let : Module.Finite k L := IsAlternative.finite_peirceComponent true false + let : Module.Projective k L := + IsAlternative.projective_peirceComponent hc.mul_self true false + let : Module.IsTorsionFree k L := inferInstance + let : Module.Free k L := Module.free_of_finite_type_torsion_free' + have hL : Module.rankAtStalk (R := k) L = 1 := + hc.rankAtStalk_offDiagonal_eq_one hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) hA true + let b : Module.Basis Unit k L := + Module.basisUnique Unit (finrank_eq_of_rankAtStalk_eq hL) + exact (hc.isomorphic_twistedMat (k := k) hcomp hA).symm.trans + (isomorphic_twistedMat_ofBasis k b) + +/-- **`GPR 22.16`, rank eight:** over a nontrivial LG ring, a reduced constant-rank-eight +composition algebra is split. -/ +theorem isSplitOfRank_eight_of_isLGRing [Nontrivial k] + (hc : C.IsElementaryIdempotent c) (hLG : IsLGRing k) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : C.IsSplitOfRank 8 := by + let M := ZornTwistingModule (k := k) c + let : Module.Finite k M := IsAlternative.finite_peirceComponent true false + let : Module.Projective k M := + IsAlternative.projective_peirceComponent hc.mul_self true false + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let P := hc.peirceVectorProductPair hcomp.isMultiplicative hreg + have hM : Module.rankAtStalk (R := k) M = 3 := + hc.rankAtStalk_twistingModule_eq_three hcomp.isMultiplicative hreg hA + let : Module.Free k M := Module.free_of_isLGRing_of_rankAtStalk_eq hLG 3 M hM + let b : Module.Basis (Fin 3) k M := + Module.finBasisOfFinrankEq k M (finrank_eq_of_rankAtStalk_eq hM) + exact (hc.isomorphic_twistedZor (k := k) hcomp.isMultiplicative hreg).symm.trans + (isomorphic_twistedZor_of_exists_basis P b) + +/-- **`GPR 22.16`, rank eight under its abstract freeness hypothesis.** -/ +theorem isSplitOfRank_eight_of_projective_constantRank_free [Nontrivial k] + (hc : C.IsElementaryIdempotent c) + (hfree : ∀ (M : Type v) [AddCommGroup M] [Module k M] [Module.Finite k M] + [Module.Projective k M], ∀ (r : ℕ), + (Module.rankAtStalk (R := k) M = fun _ ↦ r) → Module.Free k M) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : C.IsSplitOfRank 8 := by + let M := ZornTwistingModule (k := k) c + let : Module.Finite k M := IsAlternative.finite_peirceComponent true false + let : Module.Projective k M := + IsAlternative.projective_peirceComponent hc.mul_self true false + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let P := hc.peirceVectorProductPair hcomp.isMultiplicative hreg + have hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3 := + hc.rankAtStalk_twistingModule_eq_three hcomp.isMultiplicative hreg hA + let : Module.Free k M := hfree M 3 hM + let b : Module.Basis (Fin 3) k M := + Module.finBasisOfFinrankEq k M (finrank_eq_of_rankAtStalk_eq hM) + exact (hc.isomorphic_twistedZor (k := k) hcomp.isMultiplicative hreg).symm.trans + (isomorphic_twistedZor_of_exists_basis P b) + +/-- **`GPR 22.19`, rank eight:** over a PID, a reduced constant-rank-eight composition algebra is +split. The rank-three twisting module is projective, hence finite free over the PID. -/ +theorem isSplitOfRank_eight_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : C.IsSplitOfRank 8 := by + let M := ZornTwistingModule (k := k) c + let : Module.Finite k M := IsAlternative.finite_peirceComponent true false + let : Module.Projective k M := + IsAlternative.projective_peirceComponent hc.mul_self true false + let : Module.IsTorsionFree k M := inferInstance + let : Module.Free k M := Module.free_of_finite_type_torsion_free' + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let P := hc.peirceVectorProductPair hcomp.isMultiplicative hreg + have hM : Module.rankAtStalk (R := k) M = 3 := + hc.rankAtStalk_twistingModule_eq_three hcomp.isMultiplicative hreg hA + let b : Module.Basis (Fin 3) k M := + Module.finBasisOfFinrankEq k M (finrank_eq_of_rankAtStalk_eq hM) + exact (hc.isomorphic_twistedZor (k := k) hcomp.isMultiplicative hreg).symm.trans + (isomorphic_twistedZor_of_exists_basis P b) + +end IsElementaryIdempotent + +namespace IsReduced + +omit [IsAlternative A] in +/-- **Full converse of `GPR 22.16`, in a factor-stable formulation of its freeness hypothesis.** +If finite projective constant-rank modules over the idempotent factors of `k` are free, every +reduced composition algebra over `k` is split. Together with `IsSplit.isReduced`, this gives both +directions of `GPR 22.16` over arbitrary commutative rings satisfying that hypothesis. -/ +theorem isSplit_of_projective_constantRank_free_on_factors (h : C.IsReduced) + (hfree : IsElementaryIdempotent.ProjectiveConstantRankFreeOnFactors.{u, v} k) : + C.IsSplit := by + let S₁ := SplitRankFactor k A 1 + let S₂ := SplitRankFactor k A 2 + let S₄ := SplitRankFactor k A 4 + let S₈ := SplitRankFactor k A 8 + have hrank₁ : Module.rankAtStalk (R := S₁) (S₁ ⊗[k] A) = fun _ ↦ 1 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 1 + have hrank₂ : Module.rankAtStalk (R := S₂) (S₂ ⊗[k] A) = fun _ ↦ 2 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 2 + have hrank₄ : Module.rankAtStalk (R := S₄) (S₄ ⊗[k] A) = fun _ ↦ 4 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 4 + have hrank₈ : Module.rankAtStalk (R := S₈) (S₈ ⊗[k] A) = fun _ ↦ 8 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 8 + have hone : (C.splitRankComponent 1).IsSplitOfRank 1 := by + rcases subsingleton_or_nontrivial S₁ with hS | hS + · let := hS; exact Isomorphic.of_subsingleton + · let := hS; exact isSplitOfRank_one hrank₁ + have htwo : (C.splitRankComponent 2).IsSplitOfRank 2 := by + obtain ⟨c₂, hc₂⟩ := h.hasElementaryIdempotent_splitRankComponent_two + exact hc₂.isSplitOfRank_two hrank₂ + have hfour : (C.splitRankComponent 4).IsSplitOfRank 4 := by + rcases subsingleton_or_nontrivial S₄ with hS | hS + · let := hS; exact Isomorphic.of_subsingleton + · let := hS + have hc := h.isComposition.baseChangeOfProjective S₄ + let : IsAlternative (S₄ ⊗[k] A) := hc.isAlternative_general + obtain ⟨c₄, hc₄⟩ := h.hasElementaryIdempotent_splitRankComponent_four + exact hc₄.isSplitOfRank_four_of_projective_constantRank_free + (hfree _ (Module.isIdempotentElem_rankIdempotent k A 4)) hc hrank₄ + have height : (C.splitRankComponent 8).IsSplitOfRank 8 := by + rcases subsingleton_or_nontrivial S₈ with hS | hS + · let := hS; exact Isomorphic.of_subsingleton + · let := hS + have hc := h.isComposition.baseChangeOfProjective S₈ + let : IsAlternative (S₈ ⊗[k] A) := hc.isAlternative_general + obtain ⟨c₈, hc₈⟩ := h.hasElementaryIdempotent_splitRankComponent_eight + exact hc₈.isSplitOfRank_eight_of_projective_constantRank_free + (hfree _ (Module.isIdempotentElem_rankIdempotent k A 8)) hc hrank₈ + exact ⟨h.isComposition, hone, htwo, hfour, height⟩ + +omit [IsAlternative A] in +/-- **`GPR 22.16`, converse, under `GPR`'s own hypothesis.** If every finitely generated projective +`k`-module of constant rank is free, every reduced composition algebra over `k` is split. The +hypothesis passes to the idempotent factors of the rank decomposition +(`IsElementaryIdempotent.ProjectiveConstantRankFree.onFactors`). -/ +theorem isSplit_of_projectiveConstantRankFree (h : C.IsReduced) + (hfree : IsElementaryIdempotent.ProjectiveConstantRankFree.{u, max u v} k) : C.IsSplit := + h.isSplit_of_projective_constantRank_free_on_factors hfree.onFactors + +omit [IsAlternative A] in +/-- **`GPR 22.16`, reduced ⇒ split over an LG ring.** Each rank component has constant rank by +the rank decomposition. Its base is again LG because it is an idempotent factor; ranks four and +eight are therefore untwisted by freeness of constant-rank projective modules. -/ +theorem isSplit_of_isLGRing (h : C.IsReduced) (hLG : IsLGRing k) : C.IsSplit := by + let S₁ := SplitRankFactor k A 1 + let S₂ := SplitRankFactor k A 2 + let S₄ := SplitRankFactor k A 4 + let S₈ := SplitRankFactor k A 8 + have hrank₁ : Module.rankAtStalk (R := S₁) (S₁ ⊗[k] A) = fun _ ↦ 1 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 1 + have hrank₂ : Module.rankAtStalk (R := S₂) (S₂ ⊗[k] A) = fun _ ↦ 2 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 2 + have hrank₄ : Module.rankAtStalk (R := S₄) (S₄ ⊗[k] A) = fun _ ↦ 4 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 4 + have hrank₈ : Module.rankAtStalk (R := S₈) (S₈ ⊗[k] A) = fun _ ↦ 8 := + Module.rankAtStalk_quotientTensor_rankIdempotent k A 8 + have hcomp₄ := h.isComposition.baseChangeOfProjective S₄ + have hcomp₈ := h.isComposition.baseChangeOfProjective S₈ + have hone : (C.splitRankComponent 1).IsSplitOfRank 1 := by + rcases subsingleton_or_nontrivial S₁ with hS₁ | hS₁ + · let := hS₁ + exact Isomorphic.of_subsingleton + · let := hS₁ + exact isSplitOfRank_one hrank₁ + have htwo : (C.splitRankComponent 2).IsSplitOfRank 2 := by + obtain ⟨c₂, hc₂⟩ := h.hasElementaryIdempotent_splitRankComponent_two + exact hc₂.isSplitOfRank_two hrank₂ + have hfour : (C.splitRankComponent 4).IsSplitOfRank 4 := by + rcases subsingleton_or_nontrivial S₄ with hS₄ | hS₄ + · let := hS₄ + exact Isomorphic.of_subsingleton + · let := hS₄ + have hLG₄ : IsLGRing S₄ := + hLG.quotient_span_one_sub_of_isIdempotentElem + (Module.isIdempotentElem_rankIdempotent k A 4) + let hreg₄ := hcomp₄.isGPRRegular_of_rankAtStalk_ne_one hrank₄ (by omega) + let : IsAlternative (S₄ ⊗[k] A) := + hcomp₄.isMultiplicative.isAlternative hreg₄.isGPRNondegenerate + obtain ⟨c₄, hc₄⟩ := h.hasElementaryIdempotent_splitRankComponent_four + exact hc₄.isSplitOfRank_four_of_isLGRing hLG₄ hcomp₄ hrank₄ + have height : (C.splitRankComponent 8).IsSplitOfRank 8 := by + rcases subsingleton_or_nontrivial S₈ with hS₈ | hS₈ + · let := hS₈ + exact Isomorphic.of_subsingleton + · let := hS₈ + have hLG₈ : IsLGRing S₈ := + hLG.quotient_span_one_sub_of_isIdempotentElem + (Module.isIdempotentElem_rankIdempotent k A 8) + let hreg₈ := hcomp₈.isGPRRegular_of_rankAtStalk_ne_one hrank₈ (by omega) + let : IsAlternative (S₈ ⊗[k] A) := + hcomp₈.isMultiplicative.isAlternative hreg₈.isGPRNondegenerate + obtain ⟨c₈, hc₈⟩ := h.hasElementaryIdempotent_splitRankComponent_eight + exact hc₈.isSplitOfRank_eight_of_isLGRing hLG₈ hcomp₈ hrank₈ + exact ⟨h.isComposition, hone, htwo, hfour, height⟩ + +end IsReduced + +omit [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] [Module.Finite k A] + [Module.Projective k A] in +/-- **A hyperbolic norm is isotropic** (`GPR 22.9`, (iv) ⇒ (iii)). If `n ≅ dualProd k M`, write +`1 = e₁ + e₂` across the two totally isotropic summands: the preimage `(φ, m)` of `1` has +`φ m = n(1) = 1`, so `m` is unimodular and `(0, m)` is a unimodular null vector. No hypothesis on +`M` is needed. -/ +theorem isGPRIsotropic_norm_of_isometryEquiv_dualProd {M : Type*} [AddCommGroup M] [Module k M] + (e : (QuadraticForm.dualProd k M).IsometryEquiv C.norm) : C.norm.IsGPRIsotropic := by + have h1 : QuadraticForm.dualProd k M (e.symm 1) = 1 := by rw [e.symm.map_app, C.norm_one] + have hm : Module.IsUnimodular k (e.symm 1).2 := + Module.isUnimodular_of_apply_eq_one (f := (e.symm 1).1) h1 + exact (QuadraticForm.isGPRIsotropic_dualProd hm).map_isometryEquiv e + +namespace IsComposition + +omit [IsAlternative A] in +/-- **`GPR 22.18`, split ↔ isotropic, under `GPR`'s hypothesis.** If every finitely generated +projective `k`-module of constant rank is free, a composition algebra of constant rank two, four, +or eight is split exactly when its norm has a unimodular null vector. The reverse implication +produces an elementary idempotent (`GPR 22.9`) and then untwists the reduced model with the +freeness hypothesis (`GPR 22.16`). -/ +theorem isSplitOfRank_iff_isGPRIsotropic_of_projectiveConstantRankFree [Nontrivial k] + (hfree : IsElementaryIdempotent.ProjectiveConstantRankFree.{u, v} k) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r ↔ C.norm.IsGPRIsotropic := by + constructor + · intro hsplit + obtain ⟨c, hc⟩ := hsplit.hasElementaryIdempotent_of_two_or_four_or_eight hr + exact hc.isGPRIsotropic + · intro hiso + have hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + obtain ⟨c, hc⟩ := exists_isElementaryIdempotent_of_isGPRIsotropic + hreg hcomp.isMultiplicative hiso + let : IsAlternative A := + hcomp.isMultiplicative.isAlternative hreg.isGPRNondegenerate + rcases hr with rfl | rfl | rfl + · exact hc.isSplitOfRank_two hA + · exact hc.isSplitOfRank_four_of_projective_constantRank_free hfree hcomp hA + · exact hc.isSplitOfRank_eight_of_projective_constantRank_free hfree hcomp hA + +omit [IsAlternative A] in +/-- **`GPR 22.18`, split ↔ hyperbolic, under `GPR`'s hypothesis.** If every finitely generated +projective `k`-module of constant rank is free, a composition algebra of constant rank two, four, +or eight is split exactly when its norm is hyperbolic, i.e. isometric to +`QuadraticForm.dualProd k M` for a finitely generated projective `M`. Forwards, an elementary +idempotent gives the Peirce presentation `peirceHyperbolicIsometryEquiv` (`GPR 22.9`, +(i) ⇒ (iv)); backwards, a hyperbolic norm is isotropic +(`isGPRIsotropic_norm_of_isometryEquiv_dualProd`). -/ +theorem isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_projectiveConstantRankFree + [Nontrivial k] (hfree : IsElementaryIdempotent.ProjectiveConstantRankFree.{u, v} k) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ↔ ∃ (M : Type (max u v)) (_ : AddCommGroup M) (_ : Module k M) + (_ : Module.Finite k M) (_ : Module.Projective k M), + Nonempty ((QuadraticForm.dualProd k M).IsometryEquiv C.norm) := by + constructor + · intro hsplit + obtain ⟨c, hc⟩ := hsplit.hasElementaryIdempotent_of_two_or_four_or_eight hr + have hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let : IsAlternative A := hcomp.isMultiplicative.isAlternative hreg.isGPRNondegenerate + have := IsAlternative.finite_peirceComponent (R := k) (c := c) true false + have := IsAlternative.projective_peirceComponent (R := k) hc.mul_self true false + exact ⟨_, _, _, inferInstance, inferInstance, + ⟨hc.peirceHyperbolicIsometryEquiv hcomp.isMultiplicative hreg⟩⟩ + · rintro ⟨M, _, _, _, _, ⟨e⟩⟩ + exact (hcomp.isSplitOfRank_iff_isGPRIsotropic_of_projectiveConstantRankFree hfree hA hr).mpr + (isGPRIsotropic_norm_of_isometryEquiv_dualProd e) + +omit [IsAlternative A] in +/-- **`GPR 22.18`, split ↔ hyperbolic over an LG ring**: the case of +`isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_projectiveConstantRankFree` where the +freeness hypothesis is `GPR 11.24`. -/ +theorem isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_isLGRing [Nontrivial k] + (hcomp : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.IsSplitOfRank r ↔ ∃ (M : Type (max u v)) (_ : AddCommGroup M) (_ : Module k M) + (_ : Module.Finite k M) (_ : Module.Projective k M), + Nonempty ((QuadraticForm.dualProd k M).IsometryEquiv C.norm) := + hcomp.isSplitOfRank_iff_exists_isometryEquiv_dualProd_of_projectiveConstantRankFree + (.of_isLGRing hLG) hA hr + +omit [IsAlternative A] in +/-- **`GPR 22.18`, split ↔ isotropic over an LG ring.** For a constant-rank composition +algebra of rank two, four, or eight, splitness is equivalent to the existence of a unimodular null +vector. The forward implication transports the elementary idempotent of the standard model; the +reverse implication uses `GPR 22.9` and the reduced classification of `GPR 22.16`. -/ +theorem isSplitOfRank_iff_isGPRIsotropic_of_isLGRing [Nontrivial k] + (hcomp : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r ↔ C.norm.IsGPRIsotropic := by + constructor + · intro hsplit + obtain ⟨c, hc⟩ := hsplit.hasElementaryIdempotent_of_two_or_four_or_eight hr + exact hc.isGPRIsotropic + · intro hiso + have hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + obtain ⟨c, hc⟩ := exists_isElementaryIdempotent_of_isGPRIsotropic + hreg hcomp.isMultiplicative hiso + let : IsAlternative A := + hcomp.isMultiplicative.isAlternative hreg.isGPRNondegenerate + rcases hr with rfl | rfl | rfl + · exact hc.isSplitOfRank_two hA + · exact hc.isSplitOfRank_four_of_isLGRing hLG hcomp hA + · exact hc.isSplitOfRank_eight_of_isLGRing hLG hcomp hA + +omit [IsAlternative A] in +/-- **`GPR 22.18`, hyperbolic ⇒ split over an LG ring.** A norm isometric to a hyperbolic form +`QuadraticForm.dualProd k M` is isotropic (`isGPRIsotropic_norm_of_isometryEquiv_dualProd`), with +no hypothesis on `M`; the split/isotropic equivalence finishes the argument. -/ +theorem isSplitOfRank_of_isometryEquiv_dualProd [Nontrivial k] + (hcomp : C.IsComposition.{u, v, u}) (hLG : IsLGRing k) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) {M : Type*} [AddCommGroup M] [Module k M] + (e : (QuadraticForm.dualProd k M).IsometryEquiv C.norm) : C.IsSplitOfRank r := + (hcomp.isSplitOfRank_iff_isGPRIsotropic_of_isLGRing hLG hA hr).mpr + (isGPRIsotropic_norm_of_isometryEquiv_dualProd e) + +omit [IsAlternative A] in +/-- **`GPR 22.18`, split ↔ not division over a field.** For a constant-rank composition algebra +of rank two, four, or eight, splitness is equivalent to the failure of the property that every +nonzero element has a two-sided inverse. -/ +theorem isSplitOfRank_iff_not_hasTwoSidedInverses {K : Type u} [Field K] {B : Type v} + [NonAssocRing B] [Module K B] [SMulCommClass K B B] [IsScalarTower K B B] + [Module.Finite K B] [Module.Projective K B] {D : ConicAlgebra K B} + (hcomp : D.IsComposition.{u, v, u}) + (hB : Module.rankAtStalk (R := K) B = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : D.IsSplitOfRank r ↔ ¬ D.HasTwoSidedInverses := + ((hcomp.isSplitOfRank_iff_isGPRIsotropic_of_isLGRing (isLGRing_of_field K) hB hr).trans + QuadraticMap.isGPRIsotropic_iff_not_anisotropic).trans + (not_congr hcomp.isMultiplicative.hasTwoSidedInverses_iff_anisotropic.symm) + +omit [IsAlternative A] in +/-- **`GPR 22.19`, split ↔ GPR-isotropic over a PID.** For a constant-rank composition algebra +of rank two, four, or eight, a unimodular null vector is equivalent to splitness. Projective +twisting modules are free over the PID, replacing the LG-ring freeness step in `GPR 22.18`. -/ +theorem isSplitOfRank_iff_isGPRIsotropic_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r ↔ C.norm.IsGPRIsotropic := by + constructor + · intro hsplit + obtain ⟨c, hc⟩ := hsplit.hasElementaryIdempotent_of_two_or_four_or_eight hr + exact hc.isGPRIsotropic + · intro hiso + have hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + obtain ⟨c, hc⟩ := exists_isElementaryIdempotent_of_isGPRIsotropic + hreg hcomp.isMultiplicative hiso + let : IsAlternative A := + hcomp.isMultiplicative.isAlternative hreg.isGPRNondegenerate + rcases hr with rfl | rfl | rfl + · exact hc.isSplitOfRank_two hA + · exact hc.isSplitOfRank_four_of_pid hcomp hA + · exact hc.isSplitOfRank_eight_of_pid hcomp hA + +omit [IsAlternative A] in +/-- **`GPR 22.19`, split ↔ a nonzero null vector over a PID.** This is where GPR's +unimodular-vector isotropy and mathlib's failure of anisotropy become equivalent, by +`GPR Exc. 12.38(c)` (`QuadraticMap.isGPRIsotropic_iff_not_anisotropic_of_pid`). -/ +theorem isSplitOfRank_iff_not_anisotropic_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r ↔ ¬ C.norm.Anisotropic := + (hcomp.isSplitOfRank_iff_isGPRIsotropic_of_pid hA hr).trans + QuadraticMap.isGPRIsotropic_iff_not_anisotropic_of_pid + +omit [IsAlternative A] in +/-- **`GPR 22.19`, split ↔ zero divisors over a PID.** Here "has zero divisors" is expressed +canonically as the negation of mathlib's `NoZeroDivisors` predicate. -/ +theorem isSplitOfRank_iff_not_noZeroDivisors_of_pid [IsDomain k] [IsPrincipalIdealRing k] + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hr : r = 2 ∨ r = 4 ∨ r = 8) : C.IsSplitOfRank r ↔ ¬ NoZeroDivisors A := + (hcomp.isSplitOfRank_iff_not_anisotropic_of_pid hA hr).trans + (not_congr hcomp.isMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain) + +end IsComposition + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean new file mode 100644 index 0000000000..41aadb5bc5 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean @@ -0,0 +1,396 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Split +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Isotropic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneSplitting + +/-! +# Elementary idempotents and reduced composition algebras (`GPR 22.6–22.9`) + +An **elementary idempotent** of a conic algebra (`GPR Exc. 16.23`) is an element `c` with + + `n(c) = 0` and `t(c) = 1`. + +The degree-two identity then makes it an idempotent for free, `c² = t(c)c - n(c)1 = c`, and its +conjugate `conj c = 1 - c` is a second elementary idempotent orthogonal to it. Elementary +idempotents are what "reduced" means in practice: a composition algebra of rank `> 1` is reduced in +the sense of `GPR 22.6` exactly when it has one (`GPR 22.7`). + +This file proves the part of **`GPR 22.9`** that needs no Peirce decomposition: for a conic algebra +`C`, being reduced, containing a split quadratic étale subalgebra, and — under the two hypotheses +the proof actually consumes — having isotropic norm, are all the same condition. + +## The three conditions + +* **(i)** `C` has an elementary idempotent (`ConicAlgebra.HasElementaryIdempotent`). +* **(ii)** `C` contains a split quadratic étale subalgebra + (`ConicAlgebra.HasSplitEtaleSubalgebra`), spelled concretely as an injective, unital, + multiplicative norm-preserving `k`-linear map `k × k → A`, with `k × k` carrying the conic + structure `ConicAlgebra.splitEtale` of `GPR 21.19(b)`. +* **(iii)** the norm is isotropic in `GPR`'s sense — a **unimodular** null vector + (`QuadraticMap.IsGPRIsotropic`), not merely a nonzero one; see overview §6(c). + +`(i) ↔ (ii)` holds in **every** conic algebra, with no regularity, no projectivity, no +multiplicativity and no hypothesis on `2`: both directions are a direct computation with `c` and +`conj c`. `(i) → (iii)` is likewise free — the trace is a functional taking the value `1` at `c`, +which is exactly unimodularity (`GPR 9.13`). Only `(iii) → (i)` costs anything, and what it +costs is `GPR`'s own argument: regularity of the norm and multiplicativity. + +## Main definitions + +* `ConicAlgebra.IsElementaryIdempotent` : `n(c) = 0` and `t(c) = 1` (`GPR Exc. 16.23`). +* `ConicAlgebra.HasElementaryIdempotent`, `ConicAlgebra.HasSplitEtaleSubalgebra` : conditions (i) + and (ii) of `GPR 22.9`. +* `ConicAlgebra.elementaryIdempotentEmbedding` : the map `(a, b) ↦ a c + b (conj c)`. + +## Main results + +* `ConicAlgebra.hasSplitEtaleSubalgebra_iff_hasElementaryIdempotent` : **`GPR 22.9` (i) ↔ (ii)**. +* `ConicAlgebra.hasElementaryIdempotent_iff_isGPRIsotropic` : **`GPR 22.9` (i) ↔ (iii)**, for a + regular multiplicative norm. +* `ConicAlgebra.IsElementaryIdempotent.isHyperbolicPair` : `(c, conj c)` is a hyperbolic pair of the + norm, and `ConicAlgebra.IsElementaryIdempotent.isometryEquivPlaneProd` splits the plane + `k c ⊕ k (conj c)` off orthogonally. The full hyperbolic presentation is in + `Composition/Reduced/Hyperbolic.lean`. + +## Implementation notes + +⚠ **"Reduced" is not defined here, and `HasElementaryIdempotent` is not it.** `GPR 22.6` defines a +composition algebra to be *reduced* if it contains an **absolutely primitive** idempotent, and +`GPR 22.7` proves that in rank `> 1` those are exactly the elementary ones. The two notions really +do differ in rank one: `1 ∈ k` is absolutely primitive, so `k` is reduced, while an elementary +idempotent of `k` would need `c² = 0` and `2c = 1`, which `ℝ` does not supply. Absolute +primitivity quantifies over all base changes and nothing downstream needs it, so this file states +the +elementary-idempotent condition under its own name and records the discrepancy rather than +overloading `GPR`'s word. + +Clause (iv) of `GPR 22.9` — that the norm is hyperbolic — is completed in +`Composition/Reduced/Hyperbolic.lean`. What is proved here is the hypothesis-free first step: the +plane `k c ⊕ k (conj c)` splits off orthogonally +(`IsElementaryIdempotent.isometryEquivPlaneProd`). + +**Why (ii) is not stated with a `NonAssocSubalgebra`.** The content of "contains a split quadratic +étale subalgebra" is the *map* from `k × k`, since that is what carries the norm, and phrasing it +as a submodule with induced structure would need the restricted conic algebra of +`Conic/Subalgebra.lean` plus an isomorphism anyway. The injective unital multiplicative isometry is +the same data, presented once. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.13, + Exc. 16.23, 21.19, 22.6, 22.7, 22.9. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] + +/-- `c` is an **elementary idempotent** of the conic algebra `C` (`GPR Exc. 16.23`): its norm +vanishes and its trace is `1`. + +Idempotency is a consequence, not a hypothesis: the degree-two identity gives +`c² = t(c) c - n(c) 1 = c` (`ConicAlgebra.IsElementaryIdempotent.mul_self`). Nothing here needs +regularity, projectivity, multiplicativity or an assumption on `2`. -/ +structure IsElementaryIdempotent (C : ConicAlgebra k A) (c : A) : Prop where + /-- The norm of an elementary idempotent vanishes. -/ + norm_eq_zero : C.norm c = 0 + /-- The trace of an elementary idempotent is `1`. -/ + trace_eq_one : C.trace c = 1 + +namespace IsElementaryIdempotent + +variable {C : ConicAlgebra k A} {c : A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- An elementary idempotent is an idempotent, by the degree-two identity. -/ +theorem mul_self (hc : C.IsElementaryIdempotent c) : c * c = c := by + rw [C.mul_self_eq c, hc.norm_eq_zero, hc.trace_eq_one, one_smul, zero_smul, sub_zero] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The conjugate of an elementary idempotent is `1 - c`. -/ +theorem conj_eq (hc : C.IsElementaryIdempotent c) : C.conj c = 1 - c := by + rw [ConicAlgebra.conj_apply, hc.trace_eq_one, one_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The conjugate of an elementary idempotent is again one: `conj c = 1 - c` is the complementary +idempotent. -/ +theorem conj (hc : C.IsElementaryIdempotent c) : C.IsElementaryIdempotent (C.conj c) where + norm_eq_zero := by rw [ConicAlgebra.norm_conj, hc.norm_eq_zero] + trace_eq_one := by rw [ConicAlgebra.trace_conj, hc.trace_eq_one] + +omit [IsScalarTower k A A] in +/-- The two complementary idempotents are orthogonal: `c (conj c) = 0`. (Not a `simp` lemma: +`ConicAlgebra.mul_conj_self` already rewrites the left-hand side to `n(c) • 1`.) -/ +theorem mul_conj (hc : C.IsElementaryIdempotent c) : c * C.conj c = 0 := by + rw [ConicAlgebra.mul_conj_self, hc.norm_eq_zero, zero_smul] + +omit [SMulCommClass k A A] in +/-- The two complementary idempotents are orthogonal: `(conj c) c = 0`. -/ +theorem conj_mul (hc : C.IsElementaryIdempotent c) : C.conj c * c = 0 := by + rw [ConicAlgebra.conj_mul_self, hc.norm_eq_zero, zero_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- `c + conj c = 1`. -/ +theorem add_conj_eq_one (hc : C.IsElementaryIdempotent c) : c + C.conj c = 1 := by + rw [ConicAlgebra.add_conj, hc.trace_eq_one, one_smul] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`(c, conj c)` is a hyperbolic pair**: both are null and `n(c, conj c) = 1`. This is what makes +the norm of a reduced algebra hyperbolic (`GPR 22.9(iv)`). -/ +theorem polar_conj (hc : C.IsElementaryIdempotent c) : + QuadraticMap.polar C.norm c (C.conj c) = 1 := by + have h := C.norm_add c (C.conj c) + rw [hc.add_conj_eq_one, C.norm_one, hc.norm_eq_zero, hc.conj.norm_eq_zero] at h + simpa using h.symm + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`(c, conj c)` is a hyperbolic pair of the norm**, in the sense of +`QuadraticMap.IsHyperbolicPair`. This is what connects a reduced algebra to the hyperbolic-form +machinery: by `QuadraticMap.IsHyperbolicPair.isometryEquivPlaneProd` the plane `k c ⊕ k (conj c)` +splits off the norm orthogonally. -/ +theorem isHyperbolicPair (hc : C.IsElementaryIdempotent c) : + QuadraticMap.IsHyperbolicPair C.norm c (C.conj c) where + apply_left := hc.norm_eq_zero + apply_right := hc.conj.norm_eq_zero + polar_eq_one := hc.polar_conj + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- An elementary idempotent is **unimodular** (`GPR 9.13`): the trace is a functional taking the +value `1` on it. -/ +theorem isUnimodular (hc : C.IsElementaryIdempotent c) : Module.IsUnimodular k c := + Module.isUnimodular_of_apply_eq_one (f := C.trace) hc.trace_eq_one + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 22.9`, (i) ⇒ (iii)**: an elementary idempotent is a unimodular null vector, so the norm +is isotropic in `GPR`'s sense. No hypotheses. -/ +theorem isGPRIsotropic (hc : C.IsElementaryIdempotent c) : C.norm.IsGPRIsotropic := + ⟨c, hc.isUnimodular, hc.norm_eq_zero⟩ + +end IsElementaryIdempotent + +/-- `C` **has an elementary idempotent**. For a composition algebra of rank `> 1` this is `GPR`'s +*reduced* (`GPR 22.6`, via `GPR 22.7`); in rank one the two conditions differ, which is why this +one carries its own name — see the module docstring. -/ +def HasElementaryIdempotent (C : ConicAlgebra k A) : Prop := ∃ c : A, C.IsElementaryIdempotent c + +/-! ### The split quadratic étale subalgebra `k c ⊕ k (conj c)` -/ + +variable (C : ConicAlgebra k A) + +/-- The map `k × k → A`, `(a, b) ↦ a c + b (conj c)`, whose image is the subalgebra +`k c ⊕ k (conj c)` of `GPR 22.9`'s proof of (i) ⇒ (ii). It is unital, multiplicative and an +isometry from the split quadratic étale norm exactly when `c` is an elementary idempotent. -/ +def elementaryIdempotentEmbedding (c : A) : (k × k) →ₗ[k] A := + (LinearMap.toSpanSingleton k A c).comp (LinearMap.fst k k k) + + (LinearMap.toSpanSingleton k A (C.conj c)).comp (LinearMap.snd k k k) + +variable {C} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem elementaryIdempotentEmbedding_apply (c : A) (x : k × k) : + C.elementaryIdempotentEmbedding c x = x.1 • c + x.2 • C.conj c := rfl + +namespace IsElementaryIdempotent + +variable {c : A} (hc : C.IsElementaryIdempotent c) +include hc + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The embedding is unital: `c + conj c = 1`. (Not a `simp` lemma: +`elementaryIdempotentEmbedding_apply` already rewrites the left-hand side.) -/ +theorem elementaryIdempotentEmbedding_one : + C.elementaryIdempotentEmbedding c 1 = 1 := by + simpa using hc.add_conj_eq_one + +theorem elementaryIdempotentEmbedding_mul (x y : k × k) : + C.elementaryIdempotentEmbedding c (x * y) = + C.elementaryIdempotentEmbedding c x * C.elementaryIdempotentEmbedding c y := by + simp only [elementaryIdempotentEmbedding_apply, Prod.fst_mul, Prod.snd_mul, add_mul, mul_add, + smul_mul_smul_comm, hc.mul_self, hc.conj.mul_self, hc.mul_conj, hc.conj_mul, smul_zero, + add_zero, zero_add] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The embedding carries the split quadratic étale norm `(a, b) ↦ ab` of `GPR 21.19(b)` to the +norm of `C`. -/ +theorem norm_elementaryIdempotentEmbedding (x : k × k) : + C.norm (C.elementaryIdempotentEmbedding c x) = QuadraticForm.plane k x := by + rw [elementaryIdempotentEmbedding_apply, C.norm_add, QuadraticMap.polar_smul_left, + QuadraticMap.polar_smul_right, hc.polar_conj, QuadraticMap.map_smul, QuadraticMap.map_smul, + hc.norm_eq_zero, hc.conj.norm_eq_zero, QuadraticForm.plane_apply] + simp + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The coefficient `a` is recovered from `a c + b (conj c)` by pairing with `conj c`, which is what +makes the embedding injective — with no regularity hypothesis on `C`. -/ +theorem polar_elementaryIdempotentEmbedding_conj (x : k × k) : + QuadraticMap.polar C.norm (C.elementaryIdempotentEmbedding c x) (C.conj c) = x.1 := by + rw [elementaryIdempotentEmbedding_apply, QuadraticMap.polar_add_left, + QuadraticMap.polar_smul_left, QuadraticMap.polar_smul_left, hc.polar_conj, + QuadraticMap.polar_self, hc.conj.norm_eq_zero] + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The coefficient `b` is recovered from `a c + b (conj c)` by pairing with `c`. -/ +theorem polar_elementaryIdempotentEmbedding_self (x : k × k) : + QuadraticMap.polar C.norm (C.elementaryIdempotentEmbedding c x) c = x.2 := by + have hcc : QuadraticMap.polar C.norm (C.conj c) c = 1 := by + rw [QuadraticMap.polar_comm]; exact hc.polar_conj + rw [elementaryIdempotentEmbedding_apply, QuadraticMap.polar_add_left, + QuadraticMap.polar_smul_left, QuadraticMap.polar_smul_left, QuadraticMap.polar_self, hcc, + hc.norm_eq_zero] + simp + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem injective_elementaryIdempotentEmbedding : + Function.Injective (C.elementaryIdempotentEmbedding c) := by + intro x y hxy + refine Prod.ext ?_ ?_ + · rw [← hc.polar_elementaryIdempotentEmbedding_conj x, + ← hc.polar_elementaryIdempotentEmbedding_conj y, hxy] + · rw [← hc.polar_elementaryIdempotentEmbedding_self x, + ← hc.polar_elementaryIdempotentEmbedding_self y, hxy] + +end IsElementaryIdempotent + +/-- `C` **contains a split quadratic étale subalgebra** (`GPR 22.9`(ii)): there is an injective +`k`-linear map from `k × k` which preserves the unit and the multiplication and carries the split +quadratic étale norm of `GPR 21.19(b)` to the norm of `C`. + +Presented as a map rather than as a submodule with induced structure: the map is the same data and +carries the norm along with it. -/ +def HasSplitEtaleSubalgebra (C : ConicAlgebra k A) : Prop := + ∃ f : (k × k) →ₗ[k] A, + Function.Injective f ∧ f 1 = 1 ∧ (∀ x y : k × k, f (x * y) = f x * f y) ∧ + ∀ x : k × k, C.norm (f x) = QuadraticForm.plane k x + +/-- **`GPR 22.9`, (i) ⇔ (ii)**, in an arbitrary conic algebra: `C` has an elementary idempotent +if and only if it contains a split quadratic étale subalgebra. + +Forwards, the subalgebra is `k c ⊕ k (conj c)`. Backwards, the image of `(1, 0)` is an elementary +idempotent: it has norm `1 * 0 = 0`, and its trace is `n(1, ·)` computed in `k × k`, namely +`1 * 0 + 1 * 1 = 1`. Neither direction uses regularity, projectivity, multiplicativity of the norm +of `C`, or any hypothesis on `2`. -/ +theorem hasSplitEtaleSubalgebra_iff_hasElementaryIdempotent {C : ConicAlgebra k A} : + C.HasSplitEtaleSubalgebra ↔ C.HasElementaryIdempotent := by + constructor + · rintro ⟨f, -, hf1, -, hfn⟩ + refine ⟨f (1, 0), ⟨by simpa using hfn (1, 0), ?_⟩⟩ + have hpolar : QuadraticMap.polar C.norm (f 1) (f (1, 0)) = + QuadraticMap.polar (QuadraticForm.plane k) 1 (1, 0) := by + rw [QuadraticMap.polar, QuadraticMap.polar, ← map_add, hfn, hfn, hfn] + rw [ConicAlgebra.trace_apply, ← hf1, hpolar, QuadraticForm.polar_plane_one] + simp + · rintro ⟨c, hc⟩ + exact ⟨C.elementaryIdempotentEmbedding c, hc.injective_elementaryIdempotentEmbedding, + hc.elementaryIdempotentEmbedding_one, hc.elementaryIdempotentEmbedding_mul, + hc.norm_elementaryIdempotentEmbedding⟩ + +/-! ### Isotropy produces an idempotent + +This is the one implication of `GPR 22.9` with hypotheses, and they are exactly the two +`GPR`'s proof uses: the norm must be **regular** — so that a functional can be realized as +`n(v, ·)` — and it must be **multiplicative** — so that `n(uv) = n(u)n(v) = 0`. -/ + +omit [SMulCommClass k A A] in +/-- **`GPR 22.9`, (iii) ⇒ (i)**: a regular multiplicative norm with a unimodular null vector +produces an elementary idempotent. + +Given a unimodular null `u`, unimodularity gives a functional `l` with `l(u) = 1`; precomposing +with the conjugation and inverting the polar map produces `v` with `n(v, conj u) = 1`. +Norm-associativity (`GPR 16.5`) turns that into `t(uv) = 1`, while multiplicativity gives +`n(uv) = n(u) n(v) = 0`. So `c = uv` is elementary. -/ +theorem exists_isElementaryIdempotent_of_isGPRIsotropic {C : ConicAlgebra k A} + (hreg : C.norm.IsGPRRegular) (hmul : C.IsMultiplicative) + (hiso : C.norm.IsGPRIsotropic) : C.HasElementaryIdempotent := by + obtain ⟨u, hu, hnu⟩ := hiso + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hu + obtain ⟨v, hv⟩ := hreg.2 (l.comp C.conj) + refine ⟨u * v, ⟨by rw [hmul u v, hnu, zero_mul], ?_⟩⟩ + have hpolar : QuadraticMap.polar C.norm v (C.conj u) = 1 := by + have := congrArg (fun f : Module.Dual k A ↦ f (C.conj u)) hv + simpa [QuadraticMap.polarBilin_apply_apply, hl] using this + rw [ConicAlgebra.trace_apply, QuadraticMap.polar_comm, hmul.polar_mul_left u v 1, mul_one, + hpolar] + +omit [SMulCommClass k A A] in +/-- **`GPR 22.9`, (i) ⇔ (iii)** for a regular multiplicative norm: `C` has an elementary +idempotent if and only if its norm is isotropic in `GPR`'s sense (a *unimodular* null vector, +overview §6(c)). + +For a composition algebra of rank `> 1` the hypotheses are automatic: multiplicativity is part of +the definition, and regularity of the norm is `GPR 19.11`. -/ +theorem hasElementaryIdempotent_iff_isGPRIsotropic {C : ConicAlgebra k A} + (hreg : C.norm.IsGPRRegular) (hmul : C.IsMultiplicative) : + C.HasElementaryIdempotent ↔ C.norm.IsGPRIsotropic := + ⟨fun ⟨_, hc⟩ ↦ hc.isGPRIsotropic, + exists_isElementaryIdempotent_of_isGPRIsotropic hreg hmul⟩ + +/-- **`GPR 22.9`, (ii) ⇔ (iii)** for a regular multiplicative norm. -/ +theorem hasSplitEtaleSubalgebra_iff_isGPRIsotropic {C : ConicAlgebra k A} + (hreg : C.norm.IsGPRRegular) (hmul : C.IsMultiplicative) : + C.HasSplitEtaleSubalgebra ↔ C.norm.IsGPRIsotropic := + hasSplitEtaleSubalgebra_iff_hasElementaryIdempotent.trans + (hasElementaryIdempotent_iff_isGPRIsotropic hreg hmul) + +/-! ### The norm splits off a hyperbolic plane + +`GPR 22.9`(iv) says the norm of a reduced composition algebra is hyperbolic. What follows from the +pair `(c, conj c)` alone, with no Peirce decomposition and no hypothesis whatever on `C`, is that it +splits off *one* hyperbolic plane. `Composition/Reduced/Hyperbolic.lean` uses the Peirce +decomposition and regularity to identify the entire norm with a hyperbolic form. -/ + +/-- **Towards `GPR 22.9`(iv)**: an elementary idempotent splits a hyperbolic plane off the norm, + + `n ≅ ⟨plane⟩ ⊥ n|_{(k c ⊕ k (conj c))ᗮ}`. + +The plane is `k c ⊕ k (conj c)`, and the restriction of `n` to it is regular by +`QuadraticMap.IsHyperbolicPair.isGPRRegular_comp_planeSubmodule_subtype` — so no regularity of `n` +itself, no projectivity, and no hypothesis on `2` is needed. The ingredients for full hyperbolicity +from `GPR Exc. 19.35` are developed in `Composition/Reduced/Peirce.lean`. -/ +noncomputable def IsElementaryIdempotent.isometryEquivPlaneProd {C : ConicAlgebra k A} {c : A} + (hc : C.IsElementaryIdempotent c) : + ((QuadraticForm.plane k).prod (C.norm.comp (C.norm.polarOrthogonal + (QuadraticMap.IsHyperbolicPair.planeSubmodule c (C.conj c))).subtype)).IsometryEquiv + C.norm := + hc.isHyperbolicPair.isometryEquivPlaneProd + +/-! ### The split algebras are reduced (`GPR 22.16`) + +Each split model of `GPR 21.19` of rank `> 1` carries a visible elementary idempotent — the +"first diagonal entry" in each case. By `GPR 22.9` this makes each of their norms isotropic and +exhibits a split quadratic étale subalgebra in each. No hypothesis on the base ring. -/ + +section SplitModels + +variable (k : Type u) [CommRing k] + +/-- **`k × k` is reduced**: `(1, 0)` is an elementary idempotent. -/ +theorem hasElementaryIdempotent_splitEtale : (splitEtale k).HasElementaryIdempotent := + ⟨(1, 0), ⟨by simp, by simp⟩⟩ + +/-- **`Mat₂(k)` is reduced**: the matrix unit `e₁₁` is an elementary idempotent — it has +determinant `0` and trace `1`. -/ +theorem hasElementaryIdempotent_splitQuaternion : + (splitQuaternion k).HasElementaryIdempotent := + ⟨!![1, 0; 0, 0], ⟨by simp, by simp [Matrix.trace_fin_two]⟩⟩ + +/-- **`Zor(k)` is reduced**: the Zorn vector matrix `[[1, 0], [0, 0]]` is an elementary +idempotent. -/ +theorem hasElementaryIdempotent_zor : (zor k).HasElementaryIdempotent := + ⟨((1, 0), (0, 0)), ⟨(zorNorm_apply (((1, 0), (0, 0)) : Zor k)).trans (by simp), + (trace_zor_apply (((1, 0), (0, 0)) : Zor k)).trans (by simp)⟩⟩ + +end SplitModels + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Hyperbolic.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Hyperbolic.lean new file mode 100644 index 0000000000..a94f142b49 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Hyperbolic.lean @@ -0,0 +1,183 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedMatrix + +/-! +# The norm of a reduced composition algebra is hyperbolic (`GPR 22.9(iv)`) + +At an elementary idempotent `c`, the Peirce decomposition writes an element as + + `a₁ c + x₁₂ + x₂₁ + a₂ (conj c)` + +and `GPR Exc. 19.35(3)` gives its norm as `a₁a₂ + n(x₁₂, x₂₁)`. When the norm is regular, the +polar pairing identifies `C₁₂` with `C₂₁*`. Consequently the whole norm is the hyperbolic form +`QuadraticForm.dualProd k (k × C₂₁)` of `k ⊕ C₂₁`. This file packages that coordinate calculation +as an isometry equivalence and completes clause (iv) of `GPR 22.9`. + +## Main definitions + +* `ConicAlgebra.IsElementaryIdempotent.peirceHyperbolicEquiv` : the Peirce-coordinate linear + equivalence from the hyperbolic module on `k ⊕ C₂₁` to the algebra. +* `ConicAlgebra.IsElementaryIdempotent.peirceHyperbolicIsometryEquiv` : the same map as an + isometry of quadratic forms. + +## Main results + +* `ConicAlgebra.IsElementaryIdempotent.norm_peirceHyperbolicEquiv` : the coordinate map carries + the norm to the hyperbolic form. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 19.35, 22.9. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra.IsElementaryIdempotent + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] + {C : ConicAlgebra k A} {c : A} + +/-- The lower-left Peirce component used as one half of the hyperbolic presentation. -/ +abbrev HyperbolicModule (c : A) := + IsAlternative.peirceComponent (R := k) c true false + +/-- The Peirce-coordinate map from the hyperbolic module on `k ⊕ C₂₁` to the algebra. +The first hyperbolic coordinate is a functional on `k ⊕ C₂₁`; `dualProdEquiv` separates it +into its scalar and `C₂₁*` parts, and off-diagonal duality turns the latter into the `C₁₂` +coordinate. -/ +noncomputable def peirceHyperbolicTo (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + (Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c)) →ₗ[k] A := by + let e := hc.offDiagonalDuality hmul hreg + let d := dualProdEquiv k (HyperbolicModule (k := k) c) + exact + { toFun := fun x ↦ + peirceElement c x.2.1 (d.symm x.1).1 (e.symm (-(d.symm x.1).2)) x.2.2 + map_add' := fun x y ↦ by + simp only [map_add, Prod.fst_add, Prod.snd_add, map_neg, neg_add_rev, + peirceElement, add_smul, Submodule.coe_add] + module + map_smul' := fun a x ↦ by + change peirceElement c (a * x.2.1) (d.symm (a • x.1)).1 + (e.symm (-(d.symm (a • x.1)).2)) (a • x.2.2) = + a • peirceElement c x.2.1 (d.symm x.1).1 (e.symm (-(d.symm x.1).2)) x.2.2 + rw [map_smul] + simp only [Prod.smul_fst, Prod.smul_snd] + rw [show -(a • (d.symm x.1).2) = a • (-(d.symm x.1).2) by module, map_smul] + simp only [peirceElement, mul_smul, Submodule.coe_smul, smul_add] + module } + +@[simp] theorem peirceHyperbolicTo_apply (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c)) : + peirceHyperbolicTo hc hmul hreg x = + peirceElement c x.2.1 + ((dualProdEquiv k (HyperbolicModule (k := k) c)).symm x.1).1 + ((hc.offDiagonalDuality hmul hreg).symm + (-((dualProdEquiv k (HyperbolicModule (k := k) c)).symm x.1).2)) x.2.2 := + rfl + +/-- The Peirce-coordinate map from the hyperbolic module is bijective. -/ +theorem bijective_peirceHyperbolicTo (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + Function.Bijective (peirceHyperbolicTo hc hmul hreg) := by + let e := hc.offDiagonalDuality hmul hreg + let d := dualProdEquiv k (HyperbolicModule (k := k) c) + constructor + · intro x y hxy + have hproj (i j : Bool) := congrArg + (IsAlternative.peirceProjection (R := k) c i j) hxy + apply Prod.ext + · apply d.symm.injective + apply Prod.ext + · have h := congrArg C.trace (hproj true true) + rw [peirceHyperbolicTo_apply, peirceHyperbolicTo_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simp only [Prod.mk.injEq, Bool.true_eq_false, and_self, false_and, and_false, + ite_false] at h + have ht : C.trace (IsAlternative.peirceIdempotent c true) = 1 := + (hc.peirceIdempotent true).trace_eq_one + simpa only [map_smul, ht, smul_eq_mul, mul_one] using h + · apply neg_injective + apply e.symm.injective + have h := hproj false true + rw [peirceHyperbolicTo_apply, peirceHyperbolicTo_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa using h + · apply Prod.ext + · have h := congrArg C.trace (hproj false false) + rw [peirceHyperbolicTo_apply, peirceHyperbolicTo_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa [hc.trace_eq_one] using h + · have h := hproj true false + rw [peirceHyperbolicTo_apply, peirceHyperbolicTo_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa using h + · intro a + obtain ⟨a₁, a₂, x₁₂, x₂₁, ha⟩ := hc.exists_eq_peirceElement hmul a + let x : Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c) := + (d (a₂, -(e x₁₂)), (a₁, x₂₁)) + refine ⟨x, ?_⟩ + rw [ha, peirceHyperbolicTo_apply] + change peirceElement c a₁ (d.symm (d (a₂, -(e x₁₂)))).1 + (e.symm (-(d.symm (d (a₂, -(e x₁₂)))).2)) x₂₁ = _ + rw [d.symm_apply_apply, neg_neg, e.symm_apply_apply] + +/-- The Peirce-coordinate linear equivalence from the hyperbolic module on `k ⊕ C₂₁` to +`A`. -/ +noncomputable def peirceHyperbolicEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + (Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c)) ≃ₗ[k] A := + LinearEquiv.ofBijective (peirceHyperbolicTo hc hmul hreg) + (hc.bijective_peirceHyperbolicTo hmul hreg) + +@[simp] theorem peirceHyperbolicEquiv_apply (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c)) : + hc.peirceHyperbolicEquiv hmul hreg x = hc.peirceHyperbolicTo hmul hreg x := + rfl + +/-- **`GPR 22.9(iv)`: the Peirce-coordinate equivalence identifies the norm with the hyperbolic +form `QuadraticForm.dualProd k (k × C₂₁)`.** -/ +theorem norm_peirceHyperbolicEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : Module.Dual k (k × HyperbolicModule (k := k) c) × + (k × HyperbolicModule (k := k) c)) : + C.norm (hc.peirceHyperbolicEquiv hmul hreg x) = + QuadraticForm.dualProd k (k × HyperbolicModule (k := k) c) x := by + let e := hc.offDiagonalDuality hmul hreg + let d := dualProdEquiv k (HyperbolicModule (k := k) c) + rw [peirceHyperbolicEquiv_apply, peirceHyperbolicTo_apply, + hc.norm_peirceElement hmul, QuadraticForm.dualProd_apply] + have hd : x.1 x.2 = + (d.symm x.1).1 * x.2.1 - (d.symm x.1).2 x.2.2 := by + conv_lhs => rw [← d.apply_symm_apply x.1] + exact dualProdEquiv_apply _ _ + change x.2.1 * (d.symm x.1).1 + e (e.symm (-(d.symm x.1).2)) x.2.2 = x.1 x.2 + rw [e.apply_symm_apply, hd, LinearMap.neg_apply] + ring + +/-- **The norm of a reduced regular multiplicative conic algebra is hyperbolic**, `GPR 22.9(iv)`. +The displayed isometry uses the hyperbolic form `QuadraticForm.dualProd k (k × C₂₁)`. -/ +noncomputable def peirceHyperbolicIsometryEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + (QuadraticForm.dualProd k (k × HyperbolicModule (k := k) c)).IsometryEquiv C.norm where + toLinearEquiv := hc.peirceHyperbolicEquiv hmul hreg + map_app' := hc.norm_peirceHyperbolicEquiv hmul hreg + +end ConicAlgebra.IsElementaryIdempotent diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Orientation.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Orientation.lean new file mode 100644 index 0000000000..5b3720752c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Orientation.lean @@ -0,0 +1,586 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ConstantRank +public import LeanPool.CompositionAlgebrasOverRings.Module.AlternatingBaseChange +public import LeanPool.CompositionAlgebrasOverRings.Module.ExteriorPower +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition +public import LeanPool.CompositionAlgebrasOverRings.Module.VectorProduct +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import Mathlib.LinearAlgebra.ExteriorPower.Basis + +/-! +# Oriented rank-three projective modules (`GPR 22.14`) + +An orientation `θ : ⋀³ M ≃ k` of a finite projective module of constant rank three induces +the two associated vector products used to define twisted Zorn vector matrices. To prove +Binet–Cauchy over an arbitrary commutative ring, we localize at each maximal ideal. The localized +module is free of rank three, while base change for projective duals identifies its dual with the +localized dual. The primal and dual volume coefficients multiply to one by the determinant +identity from `GPR 21.7`; the based calculation then applies. Descent from all maximal +localizations proves the global identity. + +Conversely, on such a module **every** vector-product pair is `ofOrientation` of exactly one +orientation, namely its volume form `u ∧ v ∧ w ↦ ⟨u × v, w⟩`. Base change along any commutative +`k`-algebra carries a pair to a pair (`Module.VectorProductPair.baseChange`, with the dual handled +by `GPR 9.15`). At a maximal ideal the module is free, so the base-changed pair is the pair of a +basis (`Module.VectorProductPair.exists_eq_ofBasis`) and its two volume forms multiply to the +determinant of pairings; descending from all maximal ideals gives that triple identity, +`GPR (22.14.1)`, over `k`. The volume form `⋀³ M → k` is then surjective, because on a local basis +its value is a unit, and injective, because by the triple identity and the perfect pairing +`GPR 21.7` every functional on the projective module `⋀³ M` is a multiple of it. Applying the triple +identity once to the pair and once to the dual orientation `θ*⁻¹` identifies the dual products. +`Composition/Reduced/OrientedRankEight.lean` applies this to the Peirce pair of a reduced octonion +algebra (`GPR 22.15`). + +⚠ **Orientation** means `GPR`'s notion, a linear isomorphism `⋀³ M ≃ k` (`GPR 21.8`, `22.14`), not +mathlib's `Orientation`, which is a ray of volume forms. + +## Main definitions + +* `Module.VectorProductPair.ofOrientation` : the pair of associated vector products induced by + an orientation of a constant-rank-three finite projective module. +* `Module.VectorProductPair.baseChange` : the scalar extension of a vector-product pair on a + finite projective module. +* `Module.VectorProductPair.orientation` : the orientation `⋀³ M ≃ k` of a vector-product pair on + a constant-rank-three finite projective module. +* `Module.VectorProductPair.orientationEquiv` : orientations and vector-product pairs correspond. + +## Main results + +* `Module.VectorProductPair.crossAlternating_mul_crossDualAlternating` : the triple identity + `GPR (22.14.1)` for an arbitrary pair. +* `Module.VectorProductPair.ofOrientation_orientation` : every pair is induced by its orientation; + `Module.VectorProductPair.orientation_ofOrientation` : and that orientation is unique. + +## Implementation notes + +Nothing here involves a composition algebra; the file sits in `Composition/Reduced/` beside its +consumers. Duals are base changed with TauCeti's `TauCeti.Module.Dual.baseChangeEvaluationEquiv` +(`GPR 9.15`). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.15, 21.7, 21.8, + 22.14, 22.15. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace Module + +section OfOrientation + +variable {k : Type u} {M : Type v} [CommRing k] [AddCommGroup M] [Module k M] + [Module.Finite k M] [Module.Projective k M] + +/-- **Binet–Cauchy for an orientation.** The vector products induced by an orientation `θ` of a +finite projective module of constant rank three (`GPR 22.14`) satisfy +`⟨v × w, f × g⟩ = ⟨f, v⟩⟨g, w⟩ - ⟨f, w⟩⟨g, v⟩`. It is checked at every maximal ideal, where the +module is free of rank three: the primal and dual volume coefficients of a basis are inverse +(`GPR (22.14.1)`, via the duality `GPR 21.7`), so the based calculation applies. -/ +theorem cross_apply_crossDual_of_orientation + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (v w : M) (f g : Module.Dual k M) : + crossOfOrientation theta v w (crossDualOfOrientation theta f g) = + f v * g w - f w * g v := by + apply sub_eq_zero.mp + apply eq_zero_of_localization + intro J hJ + let S := Localization.AtPrime J + let MS := TensorProduct k S M + let e : TensorProduct k S (Module.Dual k M) ≃ₗ[S] Module.Dual S MS := + TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S) + let A : MS [⋀^Fin 3]→ₗ[S] S := + AlternatingMap.baseChangeAlternatingFinThree (S := S) (orientationAlternating theta) + let D : TensorProduct k S (Module.Dual k M) [⋀^Fin 3]→ₗ[S] S := + AlternatingMap.baseChangeAlternatingFinThree (S := S) + (dualOrientationAlternating theta) + let Dt : Module.Dual S MS [⋀^Fin 3]→ₗ[S] S := + D.compLinearMap e.symm.toLinearMap + obtain ⟨b⟩ := nonempty_basis_atPrime_of_rankAtStalk_eq hM J + let P : VectorProductPair S MS := VectorProductPair.ofBasis b + let vS : MS := 1 ⊗ₜ[k] v + let wS : MS := 1 ⊗ₜ[k] w + let fS : Module.Dual S MS := e (1 ⊗ₜ[k] f) + let gS : Module.Dual S MS := e (1 ⊗ₜ[k] g) + let a : S := A b + let d : S := Dt b.dualBasis + have he (r s : S) (q : Module.Dual k M) (x : M) : + e (r ⊗ₜ[k] q) (s ⊗ₜ[k] x) = r * s * algebraMap k S (q x) := by + rw [TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply, + TauCeti.Module.Dual.baseChangeEvaluation_tmul] + have had : a * d = 1 := by + have h := AlternatingMap.baseChangeFinThree_mul_eq_det + (S := S) (orientationAlternating theta) (dualOrientationAlternating theta) e he + (orientationAlternating_mul_dualOrientationAlternating_apply theta) + (b 0) (b 1) (b 2) (e.symm (b.dualBasis 0)) + (e.symm (b.dualBasis 1)) (e.symm (b.dualBasis 2)) + change a * d = 1 + simpa [a, d, A, D, Dt, AlternatingMap.baseChangeAlternatingFinThree, + Matrix.det_fin_three] using h + have hcross (x : MS) : + e (1 ⊗ₜ[k] crossOfOrientation theta v w) x = + AlternatingMap.baseChangeFinThree (S := S) (orientationAlternating theta) + vS wS x := by + induction x using TensorProduct.inductionOn with + | add x y hx hy => simp [hx, hy] + | tmul s x => + rw [AlternatingMap.baseChangeFinThree_tmul] + simp [he, crossOfOrientation_apply] + have hcrossEq : e (1 ⊗ₜ[k] crossOfOrientation theta v w) = + a • P.cross vS wS := by + apply LinearMap.ext + intro x + rw [hcross] + change A ![vS, wS, x] = _ + have h := DFunLike.congr_fun (A.eq_smul_basis_det b) ![vS, wS, x] + rw [← VectorProductPair.crossAlternating_ofBasis b] at h + simpa [a, P] using h + have hcrossDual (h : Module.Dual S MS) : + h (1 ⊗ₜ[k] crossDualOfOrientation theta f g) = Dt ![fS, gS, h] := by + let q := e.symm h + rw [← e.apply_symm_apply h] + simp only [Dt, D, fS, gS, AlternatingMap.compLinearMap_apply, + AlternatingMap.baseChangeAlternatingFinThree] + have hvec : (fun i ↦ e.symm + (![e (1 ⊗ₜ[k] f), e (1 ⊗ₜ[k] g), e (e.symm h)] i)) = + ![(1 ⊗ₜ[k] f), (1 ⊗ₜ[k] g), q] := by + ext i + fin_cases i <;> simp [q] + change e (e.symm h) (1 ⊗ₜ[k] crossDualOfOrientation theta f g) = + AlternatingMap.baseChangeAlternatingFinThree (S := S) + (dualOrientationAlternating theta) + (fun i ↦ e.symm (![e (1 ⊗ₜ[k] f), e (1 ⊗ₜ[k] g), e (e.symm h)] i)) + rw [hvec] + change e q (1 ⊗ₜ[k] crossDualOfOrientation theta f g) = + AlternatingMap.baseChangeFinThree (S := S) (dualOrientationAlternating theta) + (1 ⊗ₜ[k] f) (1 ⊗ₜ[k] g) q + induction q using TensorProduct.inductionOn with + | add x y hx hy => simp [hx, hy] + | tmul r q => + rw [AlternatingMap.baseChangeFinThree_tmul] + simp [he, apply_crossDualOfOrientation] + have hcrossDualEq : (1 ⊗ₜ[k] crossDualOfOrientation theta f g : MS) = + d • P.crossDual fS gS := by + apply (Module.evalEquiv S MS).injective + ext h + simp only [Module.evalEquiv_apply, Module.Dual.eval_apply] + rw [hcrossDual] + rw [← alternating_fin_three_cycle Dt h fS gS] + have hdet := DFunLike.congr_fun (Dt.eq_smul_basis_det b.dualBasis) ![h, fS, gS] + rw [← VectorProductPair.crossDualAlternating_ofBasis b] at hdet + simpa [d, P] using hdet + have hleft : algebraMap k S + (crossOfOrientation theta v w (crossDualOfOrientation theta f g)) = + e (1 ⊗ₜ[k] crossOfOrientation theta v w) + (1 ⊗ₜ[k] crossDualOfOrientation theta f g) := by + symm + simpa using he 1 1 (crossOfOrientation theta v w) + (crossDualOfOrientation theta f g) + rw [map_sub, map_sub, map_mul, map_mul, hleft, hcrossEq, hcrossDualEq] + simp only [LinearMap.smul_apply, smul_eq_mul, map_smul] + rw [← mul_assoc, mul_comm d a, had, one_mul] + rw [P.cross_apply_crossDual] + simp [fS, gS, vS, wS, he] + ring + +/-- **`GPR 22.14`.** An orientation of a finite projective module of constant rank three over an +arbitrary commutative ring induces its pair of associated vector products. -/ +noncomputable def VectorProductPair.ofOrientation + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : VectorProductPair k M where + cross := crossOfOrientation theta + crossDual := crossDualOfOrientation theta + cross_self v := by + apply LinearMap.ext + intro w + rw [crossOfOrientation_apply] + exact (orientationAlternating theta).map_eq_zero_of_eq ![v, v, w] + (by rfl) (show (0 : Fin 3) ≠ 1 by decide) + crossDual_self f := by + apply (Module.evalEquiv k M).injective + ext h + simp only [Module.evalEquiv_apply, Module.Dual.eval_apply, map_zero] + rw [apply_crossDualOfOrientation] + exact (dualOrientationAlternating theta).map_eq_zero_of_eq ![f, f, h] + (by rfl) (show (0 : Fin 3) ≠ 1 by decide) + cross_apply_left v w := by + rw [crossOfOrientation_apply] + exact (orientationAlternating theta).map_eq_zero_of_eq ![v, w, v] + (by rfl) (show (0 : Fin 3) ≠ 2 by decide) + apply_crossDual_left f g := by + rw [apply_crossDualOfOrientation] + exact (dualOrientationAlternating theta).map_eq_zero_of_eq ![f, g, f] + (by rfl) (show (0 : Fin 3) ≠ 2 by decide) + cross_apply_crossDual := cross_apply_crossDual_of_orientation hM theta + +@[simp] theorem VectorProductPair.ofOrientation_cross + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : + (VectorProductPair.ofOrientation hM theta).cross = crossOfOrientation theta := rfl + +@[simp] theorem VectorProductPair.ofOrientation_crossDual + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : + (VectorProductPair.ofOrientation hM theta).crossDual = + crossDualOfOrientation theta := rfl + +end OfOrientation + +namespace VectorProductPair + +variable {k : Type u} {M : Type v} [CommRing k] [AddCommGroup M] [Module k M] + (P : VectorProductPair k M) + +/-- The trilinear form of the dual vector product, read with its last argument as the +functional: `⟨χ, φ × ψ⟩`. -/ +theorem crossDualAlternating_apply_cycle (φ ψ χ : Module.Dual k M) : + P.crossDualAlternating ![φ, ψ, χ] = χ (P.crossDual φ ψ) := by + rw [alternating_fin_three_cycle, alternating_fin_three_cycle] + simp + +/-- The linear form on `⋀³ M` induced by the volume form `(u, v, w) ↦ ⟨u × v, w⟩` of a +vector-product pair. -/ +noncomputable def orientationLinearMap : ⋀[k]^3 M →ₗ[k] k := + exteriorPower.alternatingMapLinearEquiv P.crossAlternating + +@[simp] theorem orientationLinearMap_ιMulti (x : Fin 3 → M) : + P.orientationLinearMap (exteriorPower.ιMulti k 3 x) = P.crossAlternating x := + exteriorPower.alternatingMapLinearEquiv_apply_ιMulti _ x + +section BaseChange + +variable [Module.Finite k M] [Module.Projective k M] (S : Type w) [CommRing S] [Algebra k S] + +/-- The dual vector product of the base change of a vector-product pair: the curried scalar +extension of the dual volume form, transported along the projective dual-base-change +equivalence `GPR 9.15` and read back in `S ⊗ M` by reflexivity. -/ +noncomputable def baseChangeCrossDual : + Module.Dual S (S ⊗[k] M) →ₗ[S] Module.Dual S (S ⊗[k] M) →ₗ[S] S ⊗[k] M := + (AlternatingMap.curryFinThree + ((AlternatingMap.baseChangeAlternatingFinThree (S := S) P.crossDualAlternating).compLinearMap + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) + (A := S)).symm.toLinearMap)).compr₂ + (Module.evalEquiv S (S ⊗[k] M)).symm.toLinearMap + +/-- The defining property of the base-changed dual vector product: `⟨χ, φ × ψ⟩` is the scalar +extension of the dual volume form evaluated at `(φ, ψ, χ)`, read in `S ⊗ M*`. This is the rule +`θ*⁻¹(φ ∧ ψ ∧ χ) = ⟨χ, φ × ψ⟩` of `GPR (22.14.2)`. -/ +theorem apply_baseChangeCrossDual (f g h : Module.Dual S (S ⊗[k] M)) : + h (P.baseChangeCrossDual S f g) = + AlternatingMap.baseChangeFinThree (S := S) P.crossDualAlternating + ((TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S)).symm f) + ((TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S)).symm g) + ((TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S)).symm h) := by + change Module.evalEquiv S (S ⊗[k] M) ((Module.evalEquiv S (S ⊗[k] M)).symm _) h = _ + rw [LinearEquiv.apply_symm_apply] + rfl + +/-- The base-changed dual vector product on pure tensors. -/ +theorem baseChangeCrossDual_tmul (r s : S) (φ ψ : Module.Dual k M) : + P.baseChangeCrossDual S (TauCeti.Module.Dual.baseChangeEvaluation (A := S) (r ⊗ₜ[k] φ)) + (TauCeti.Module.Dual.baseChangeEvaluation (A := S) (s ⊗ₜ[k] ψ)) = + (r * s) ⊗ₜ[k] P.crossDual φ ψ := by + let e := TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S) + apply (Module.evalEquiv S (S ⊗[k] M)).injective + ext h + rw [Module.evalEquiv_apply, Module.evalEquiv_apply, Module.Dual.eval_apply, + Module.Dual.eval_apply, apply_baseChangeCrossDual, + ← TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply, + ← TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply, LinearEquiv.symm_apply_apply, + LinearEquiv.symm_apply_apply] + obtain ⟨q, rfl⟩ := e.surjective h + rw [LinearEquiv.symm_apply_apply] + induction q using TensorProduct.inductionOn with + | add q₁ q₂ h₁ h₂ => simp only [map_add, LinearMap.add_apply]; rw [h₁, h₂] + | tmul t χ => + rw [AlternatingMap.baseChangeFinThree_tmul, crossDualAlternating_apply_cycle] + simp only [e, TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply, + TauCeti.Module.Dual.baseChangeEvaluation_tmul] + ring + +/-- **Base change of a vector-product pair** along a commutative `k`-algebra `S`, for `M` finitely +generated projective. The first product is the scalar extension of the volume form +`(u, v, w) ↦ ⟨u × v, w⟩`; the second is the scalar extension of the dual volume form, read +through the identification `S ⊗ M* = (S ⊗ M)*` of `GPR 9.15`. The axioms are checked on pure +tensors. -/ +noncomputable def baseChange : VectorProductPair S (S ⊗[k] M) where + cross := AlternatingMap.baseChangeFinThree (S := S) P.crossAlternating + crossDual := P.baseChangeCrossDual S + cross_self v := LinearMap.ext fun w ↦ by + rw [AlternatingMap.baseChangeFinThree_self_zero_one] + rfl + crossDual_self f := by + apply (Module.evalEquiv S (S ⊗[k] M)).injective + ext h + rw [Module.evalEquiv_apply, Module.Dual.eval_apply, apply_baseChangeCrossDual, + AlternatingMap.baseChangeFinThree_self_zero_one, map_zero, LinearMap.zero_apply] + cross_apply_left v w := AlternatingMap.baseChangeFinThree_self_zero_two _ v w + apply_crossDual_left f g := by + rw [apply_baseChangeCrossDual, AlternatingMap.baseChangeFinThree_self_zero_two] + cross_apply_crossDual v w f g := by + let e := TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := k) (M := M) (A := S) + obtain ⟨q, rfl⟩ := e.surjective f + obtain ⟨q', rfl⟩ := e.surjective g + induction q using TensorProduct.inductionOn with + | add q₁ q₂ h₁ h₂ => + simp only [map_add, LinearMap.add_apply] at h₁ h₂ ⊢ + rw [h₁, h₂] + ring + | tmul r φ => + induction q' using TensorProduct.inductionOn with + | add q₁ q₂ h₁ h₂ => + simp only [map_add, LinearMap.add_apply] at h₁ h₂ ⊢ + rw [h₁, h₂] + ring + | tmul s ψ => + simp only [e, TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply] + rw [baseChangeCrossDual_tmul] + induction v using TensorProduct.inductionOn with + | add v₁ v₂ h₁ h₂ => + simp only [map_add, LinearMap.add_apply] at h₁ h₂ ⊢ + rw [h₁, h₂] + ring + | tmul t x => + induction w using TensorProduct.inductionOn with + | add w₁ w₂ h₁ h₂ => + simp only [map_add, LinearMap.add_apply] at h₁ h₂ ⊢ + rw [h₁, h₂] + ring + | tmul t' y => + rw [AlternatingMap.baseChangeFinThree_tmul] + simp only [TauCeti.Module.Dual.baseChangeEvaluation_tmul] + have h := P.cross_apply_crossDual x y φ ψ + simp only [crossAlternating_apply, Matrix.cons_val_zero, Matrix.cons_val_one, + Matrix.cons_val_two, Matrix.head_cons, Matrix.tail_cons, h, map_sub, map_mul] + ring + +@[simp] theorem baseChange_cross : + (P.baseChange S).cross = AlternatingMap.baseChangeFinThree (S := S) P.crossAlternating := rfl + +@[simp] theorem baseChange_crossDual : (P.baseChange S).crossDual = P.baseChangeCrossDual S := rfl + +/-- The volume form of the base change is the scalar extension of the volume form. -/ +theorem crossAlternating_baseChange : + (P.baseChange S).crossAlternating = + AlternatingMap.baseChangeAlternatingFinThree (S := S) P.crossAlternating := + rfl + +/-- The volume form of the base change on scalar extensions of vectors of `M`. -/ +theorem crossAlternating_baseChange_one_tmul (x : Fin 3 → M) : + (P.baseChange S).crossAlternating (fun i ↦ 1 ⊗ₜ[k] x i) = + algebraMap k S (P.crossAlternating x) := by + have hx : ![x 0, x 1, x 2] = x := by + ext i + fin_cases i <;> rfl + rw [crossAlternating_apply, baseChange_cross, AlternatingMap.baseChangeFinThree_tmul, hx] + ring + +/-- The dual volume form of the base change on scalar extensions of functionals on `M`. -/ +theorem crossDualAlternating_baseChange_one_tmul (f : Fin 3 → Module.Dual k M) : + (P.baseChange S).crossDualAlternating + (fun i ↦ TauCeti.Module.Dual.baseChangeEvaluation (A := S) (1 ⊗ₜ[k] f i)) = + algebraMap k S (P.crossDualAlternating f) := by + rw [crossDualAlternating_apply, baseChange_crossDual, baseChangeCrossDual_tmul, + TauCeti.Module.Dual.baseChangeEvaluation_tmul, crossDualAlternating_apply] + ring + +end BaseChange + +/-- **The triple identity in the free case.** For a vector-product pair on a module with a basis +of size three, the volume forms of the two products multiply to the determinant of the matrix of +pairings: this is `GPR (22.14.1)` read for the pair. -/ +theorem crossAlternating_mul_crossDualAlternating_of_basis (b : Module.Basis (Fin 3) k M) + (x : Fin 3 → M) (f : Fin 3 → Module.Dual k M) : + P.crossAlternating x * P.crossDualAlternating f = Matrix.det (.of fun i j ↦ f i (x j)) := by + obtain ⟨b', rfl⟩ := VectorProductPair.exists_eq_ofBasis b P + rw [VectorProductPair.crossAlternating_ofBasis, VectorProductPair.crossDualAlternating_ofBasis] + exact b'.det_mul_det_dualBasis x f + +variable [Module.Finite k M] [Module.Projective k M] + +/-- **The triple identity**, `GPR (22.14.1)` for a vector-product pair on a constant-rank-three +finite projective module: `⟨u × v, w⟩ · ⟨φ, ψ × χ⟩ = det (⟨φᵢ, vⱼ⟩)`. It is checked at every +maximal ideal, where the module is free and the based case +`crossAlternating_mul_crossDualAlternating_of_basis` applies to the base-changed pair. -/ +theorem crossAlternating_mul_crossDualAlternating + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) (x : Fin 3 → M) (f : Fin 3 → Module.Dual k M) : + P.crossAlternating x * P.crossDualAlternating f = Matrix.det (.of fun i j ↦ f i (x j)) := by + apply sub_eq_zero.mp + apply eq_zero_of_localization + intro J hJ + let S := Localization.AtPrime J + obtain ⟨b⟩ := nonempty_basis_atPrime_of_rankAtStalk_eq hM J + have h := (P.baseChange S).crossAlternating_mul_crossDualAlternating_of_basis b + (fun i ↦ 1 ⊗ₜ[k] x i) (fun i ↦ TauCeti.Module.Dual.baseChangeEvaluation (A := S) (1 ⊗ₜ[k] f i)) + rw [crossAlternating_baseChange_one_tmul, crossDualAlternating_baseChange_one_tmul] at h + rw [map_sub, map_mul, h, RingHom.map_det, sub_eq_zero] + congr 1 + ext i j + simp only [TauCeti.Module.Dual.baseChangeEvaluation_tmul, one_mul] + rfl + +/-- The volume form of a vector-product pair on a constant-rank-three finite projective module is +surjective. At a maximal ideal `J`, the base-changed pair has a unit volume on a basis +(`isUnit_crossAlternating_basis`), which could not happen if every volume of `M` lay in `J`. -/ +theorem surjective_orientationLinearMap (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + Function.Surjective P.orientationLinearMap := by + rw [← LinearMap.range_eq_top] + by_contra hne + obtain ⟨J, hJ, hle⟩ := Ideal.exists_le_maximal _ hne + have hval (x : Fin 3 → M) : P.crossAlternating x ∈ J := + hle ⟨exteriorPower.ιMulti k 3 x, P.orientationLinearMap_ιMulti x⟩ + let S := Localization.AtPrime J + obtain ⟨b⟩ := nonempty_basis_atPrime_of_rankAtStalk_eq hM J + have hmem (y₀ y₁ y₂ : S ⊗[k] M) : + AlternatingMap.baseChangeFinThree (S := S) P.crossAlternating y₀ y₁ y₂ ∈ + Ideal.map (algebraMap k S) J := by + induction y₀ using TensorProduct.inductionOn with + | add a a' ha ha' => + rw [map_add, LinearMap.add_apply, LinearMap.add_apply] + exact add_mem ha ha' + | tmul r x => + induction y₁ using TensorProduct.inductionOn with + | add a a' ha ha' => + rw [map_add, LinearMap.add_apply] + exact add_mem ha ha' + | tmul s y => + induction y₂ using TensorProduct.inductionOn with + | add a a' ha ha' => + rw [map_add] + exact add_mem ha ha' + | tmul t z => + rw [AlternatingMap.baseChangeFinThree_tmul] + exact Ideal.mul_mem_left _ _ (Ideal.mem_map_of_mem _ (hval _)) + have hunit := (P.baseChange S).isUnit_crossAlternating_basis b + have hmax : (P.baseChange S).crossAlternating b ∈ IsLocalRing.maximalIdeal S := by + rw [← Localization.AtPrime.map_eq_maximalIdeal] + exact hmem (b 0) (b 1) (b 2) + exact (IsLocalRing.mem_maximalIdeal _).mp hmax hunit + +/-- The volume form of a vector-product pair on a constant-rank-three finite projective module is +injective. By the triple identity, every functional on `⋀³ M` — all of which come from `⋀³ M*` +by `GPR 21.7` — is a multiple of the volume form, and functionals separate the points of the +projective module `⋀³ M`. -/ +theorem injective_orientationLinearMap (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + Function.Injective P.orientationLinearMap := by + let B : ⋀[k]^3 (Module.Dual k M) →ₗ[k] k := + exteriorPower.alternatingMapLinearEquiv P.crossDualAlternating + have hpair (η : ⋀[k]^3 (Module.Dual k M)) (ω : ⋀[k]^3 M) : + exteriorPower.pairingDual k M 3 η ω = P.orientationLinearMap ω * B η := by + have h₁ (x : Fin 3 → M) : + Module.Dual.eval k _ (exteriorPower.ιMulti k 3 x) ∘ₗ exteriorPower.pairingDual k M 3 = + P.crossAlternating x • B := by + ext f + simp only [LinearMap.compAlternatingMap_apply, LinearMap.comp_apply, + Module.Dual.eval_apply, exteriorPower.pairingDual_ιMulti_ιMulti, LinearMap.smul_apply, + B, exteriorPower.alternatingMapLinearEquiv_apply_ιMulti, smul_eq_mul, + P.crossAlternating_mul_crossDualAlternating hM] + rw [show (Matrix.of fun i j ↦ f j (x i)) = + Matrix.transpose (Matrix.of fun i j ↦ f i (x j)) by rfl, Matrix.det_transpose] + have h₂ : exteriorPower.pairingDual k M 3 η = B η • P.orientationLinearMap := by + ext x + simpa [mul_comm] using LinearMap.congr_fun (h₁ x) η + rw [h₂, LinearMap.smul_apply, smul_eq_mul, mul_comm] + refine (injective_iff_map_eq_zero _).mpr fun ω hω ↦ ?_ + refine (Module.forall_dual_apply_eq_zero_iff k ω).mp fun φ ↦ ?_ + obtain ⟨η, rfl⟩ := (exteriorPower.pairingDual_bijective_of_projective (M := M) 3).2 φ + rw [hpair, hω, zero_mul] + +/-- **The orientation of a vector-product pair.** On a finite projective module of constant rank +three, the volume form `u ∧ v ∧ w ↦ ⟨u × v, w⟩` of a vector-product pair is an orientation +`⋀³ M ≃ k`; this is the converse of the construction of `GPR 22.14`. -/ +noncomputable def orientation (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + (⋀[k]^3 M) ≃ₗ[k] k := + LinearEquiv.ofBijective P.orientationLinearMap + ⟨P.injective_orientationLinearMap hM, P.surjective_orientationLinearMap hM⟩ + +@[simp] theorem orientation_ιMulti (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (x : Fin 3 → M) : P.orientation hM (exteriorPower.ιMulti k 3 x) = P.crossAlternating x := + P.orientationLinearMap_ιMulti x + +@[simp] theorem orientationAlternating_orientation + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + orientationAlternating (P.orientation hM) = P.crossAlternating := + AlternatingMap.ext fun x ↦ P.orientation_ιMulti hM x + +/-- The dual orientation `θ*⁻¹` of `GPR 22.14` induced by the orientation of a pair is the volume +form of its dual vector product. Both satisfy the determinant identity `GPR (22.14.1)` against +the same primal volume form, which takes the value `1` on some element of `⋀³ M`. -/ +theorem dualOrientationAlternating_orientation + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + dualOrientationAlternating (P.orientation hM) = P.crossDualAlternating := by + ext f + obtain ⟨ω, hω⟩ := (P.orientation hM).surjective 1 + have h : (dualOrientationAlternating (P.orientation hM) f - P.crossDualAlternating f) • + (P.orientation hM).toLinearMap = 0 := by + ext x + have h₁ : orientationAlternating (P.orientation hM) x * + dualOrientationAlternating (P.orientation hM) f = Matrix.det (.of fun i j ↦ f i (x j)) := + orientationAlternating_mul_dualOrientationAlternating_apply (P.orientation hM) x f + have h₂ := P.crossAlternating_mul_crossDualAlternating hM x f + rw [orientationAlternating_orientation] at h₁ + simp only [LinearMap.compAlternatingMap_apply, LinearMap.smul_apply, LinearEquiv.coe_coe, + orientation_ιMulti, smul_eq_mul, LinearMap.zero_compAlternatingMap, + AlternatingMap.zero_apply] + linear_combination h₁ - h₂ + have := LinearMap.congr_fun h ω + rwa [LinearMap.smul_apply, LinearEquiv.coe_coe, hω, smul_eq_mul, mul_one, LinearMap.zero_apply, + sub_eq_zero] at this + +/-- **Every vector-product pair comes from an orientation.** On a finite projective module of +constant rank three, the pair induced (`GPR 22.14`) by the orientation of a pair is the pair +itself. -/ +@[simp] theorem ofOrientation_orientation (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + VectorProductPair.ofOrientation hM (P.orientation hM) = P := by + refine VectorProductPair.ext ?_ ?_ + · ext v w x + rw [VectorProductPair.ofOrientation_cross, crossOfOrientation_apply, + orientationAlternating_orientation, crossAlternating_apply] + rfl + · ext f g + apply (Module.evalEquiv k M).injective + ext h + rw [Module.evalEquiv_apply, Module.evalEquiv_apply, Module.Dual.eval_apply, + Module.Dual.eval_apply, VectorProductPair.ofOrientation_crossDual, + apply_crossDualOfOrientation, dualOrientationAlternating_orientation, + crossDualAlternating_apply_cycle] + +/-- The orientation of the pair induced by an orientation is the orientation itself. -/ +@[simp] theorem orientation_ofOrientation (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (θ : (⋀[k]^3 M) ≃ₗ[k] k) : (VectorProductPair.ofOrientation hM θ).orientation hM = θ := by + apply LinearEquiv.toLinearMap_injective + ext x + have hx : ![x 0, x 1, x 2] = x := by + ext i + fin_cases i <;> rfl + simp [crossAlternating_apply, hx] + +/-- **Orientations are vector-product pairs** (`GPR 22.14`): on a finite projective module of +constant rank three, `VectorProductPair.ofOrientation` is a bijection from orientations to +vector-product pairs, with inverse `VectorProductPair.orientation`. -/ +noncomputable def orientationEquiv (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + ((⋀[k]^3 M) ≃ₗ[k] k) ≃ VectorProductPair k M where + toFun θ := VectorProductPair.ofOrientation hM θ + invFun P := P.orientation hM + left_inv θ := orientation_ofOrientation hM θ + right_inv P := P.ofOrientation_orientation hM + +@[simp] theorem orientationEquiv_apply (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (θ : (⋀[k]^3 M) ≃ₗ[k] k) : orientationEquiv hM θ = VectorProductPair.ofOrientation hM θ := rfl + +@[simp] theorem orientationEquiv_symm_apply (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + (orientationEquiv hM).symm P = P.orientation hM := rfl + +end VectorProductPair + +end Module diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/OrientedRankEight.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/OrientedRankEight.lean new file mode 100644 index 0000000000..ec589bec9e --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/OrientedRankEight.lean @@ -0,0 +1,207 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Orientation +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankEight + +/-! +# Reduced octonion algebras are oriented twisted Zorn algebras (`GPR 22.15`) + +`GPR 22.14` attaches to an orientation `θ : ⋀³ M ≅ k` of a finitely generated projective module +`M` of rank three its two associated vector products, and with them the algebra `Zor(M, θ)` of +twisted Zorn vector matrices. `GPR 22.15` (Petersson) says that up to isomorphism these are exactly +the reduced octonion algebras, an isomorphism `Zor(M, θ) ≅ C` matching the matrix unit `e₁₁` with +a given elementary idempotent `c`. + +The ingredients are proved elsewhere. `Composition/Reduced/Orientation.lean` builds the pair of +an orientation, `Module.VectorProductPair.ofOrientation`, and shows that on a finite projective +module of constant rank three **every** vector-product pair arises this way from exactly one +orientation, its volume form `u ∧ v ∧ w ↦ ⟨u × v, w⟩` +(`Module.VectorProductPair.ofOrientation_orientation`). `Composition/Reduced/TwistedZorn.lean` +shows that the twisted Zorn algebra of any pair is a reduced composition algebra, and +`Composition/Reduced/RankEight.lean` proves the converse with the pair *read off* from Peirce +multiplication on `M = C₂₁`, with no orientation in sight +(`IsElementaryIdempotent.isomorphic_twistedZor_of_rankAtStalk_eq_eight`). This file combines them: +for the Peirce pair the volume form is `n_C(uv, w)`, which is the orientation `GPR (22.15.3)` +writes down. + +⚠ **Not `GPR`'s proof.** `GPR 22.15` shows that `θ` is bijective using the algebra: over a field, +`θ = 0` would force `M² = 0`, which linearized right alternativity rules out, and over a local +ring one passes to the residue field. It then identifies the dual product using the Moufang +identities. The argument in `Composition/Reduced/Orientation.lean` needs only the vector-product +axioms, so it applies to every pair on a constant-rank-three module, not only to Peirce pairs. + +⚠ **Orientation** means `GPR`'s notion, a linear isomorphism `⋀³ M ≃ k` (`GPR 21.8`, `22.14`), not +mathlib's `Orientation`, which is a ray of volume forms. + +## Main results + +* `ConicAlgebra.IsElementaryIdempotent.exists_orientation_isometryEquiv_twistedZor` : + **`GPR 22.15`** for a given elementary idempotent, with the orientation `GPR (22.15.3)` and the + normalization `GPR (22.15.1)`. +* `ConicAlgebra.IsElementaryIdempotent.exists_orientation_isomorphic_twistedZor`, + `ConicAlgebra.IsElementaryIdempotent.exists_isomorphic_twistedZor_ofOrientation` : the + isomorphism alone, on the Peirce component and in `GPR`'s form "for some `M` and `θ`". +* `ConicAlgebra.exists_isomorphic_twistedZor_ofOrientation_iff` : **`GPR 22.15`**, both + directions: the algebras `Zor(M, θ)` are exactly the composition algebras of constant rank + eight with an elementary idempotent. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 21.8, 22.7, + 22.14, 22.15. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace ConicAlgebra.IsElementaryIdempotent + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] + {C : ConicAlgebra k A} {c : A} + +/-- The Peirce-coordinate equivalence sends the matrix unit `e₁₁` of `GPR (22.14.7)` to the +idempotent `c`. -/ +theorem twistedZorEquiv_matrixUnit (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + hc.twistedZorEquiv hmul hreg + (((1, 0), (0, 0)) : TwistedZor (hc.peirceVectorProductPair hmul hreg)) = c := by + change peirceElement c 1 0 ((hc.offDiagonalDuality hmul hreg).symm 0) 0 = c + simp [peirceElement] + +/-- The volume form of the Peirce vector products is `(u, v, w) ↦ n_C(uv, w)`, the trilinear form +of `GPR (22.15.3)`. -/ +theorem crossAlternating_peirceVectorProductPair (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (u v w : ZornTwistingModule (k := k) c) : + (hc.peirceVectorProductPair hmul hreg).crossAlternating ![u, v, w] = + QuadraticMap.polar C.norm ((u : A) * v) w := + rfl + +/-- **`GPR 22.15` (Petersson), oriented form.** Let `C` be a composition algebra of constant rank +eight with an elementary idempotent `c`, and let `M = C₂₁` be its lower-left Peirce component +(finite projective of constant rank three). The trilinear form `(u, v, w) ↦ n_C(uv, w)` of +`GPR (22.15.3)` is an orientation `θ` of `M`, and the Peirce coordinates are an isomorphism +`Zor(M, θ) ≅ C` sending the matrix unit `e₁₁` to `c` (`GPR (22.15.1)`, read in the inverse +direction). -/ +theorem exists_orientation_isometryEquiv_twistedZor [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + letI : Module.Finite k (ZornTwistingModule (k := k) c) := + IsAlternative.finite_peirceComponent true false + letI : Module.Projective k (ZornTwistingModule (k := k) c) := + IsAlternative.projective_peirceComponent hc.mul_self true false + ∃ θ : (⋀[k]^3 (ZornTwistingModule (k := k) c)) ≃ₗ[k] k, + (∀ u v w : ZornTwistingModule (k := k) c, + θ (exteriorPower.ιMulti k 3 ![u, v, w]) = QuadraticMap.polar C.norm ((u : A) * v) w) ∧ + ∃ e : (twistedZor (Module.VectorProductPair.ofOrientation + (hc.rankAtStalk_twistingModule_eq_three_of_isComposition hcomp hA) θ)).norm.IsometryEquiv + C.norm, + e 1 = 1 ∧ (∀ x y, e (x * y) = e x * e y) ∧ + e (((1, 0), (0, 0)) : TwistedZor (Module.VectorProductPair.ofOrientation + (hc.rankAtStalk_twistingModule_eq_three_of_isComposition hcomp hA) θ)) = c := by + let : Module.Finite k (ZornTwistingModule (k := k) c) := + IsAlternative.finite_peirceComponent true false + let : Module.Projective k (ZornTwistingModule (k := k) c) := + IsAlternative.projective_peirceComponent hc.mul_self true false + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let P := hc.peirceVectorProductPair hcomp.isMultiplicative hreg + have hM : Module.rankAtStalk (R := k) (ZornTwistingModule (k := k) c) = fun _ ↦ 3 := + hc.rankAtStalk_twistingModule_eq_three_of_isComposition hcomp hA + refine ⟨P.orientation hM, fun u v w ↦ P.orientation_ιMulti hM _, ?_⟩ + rw [P.ofOrientation_orientation hM] + exact ⟨hc.twistedZorIsometryEquiv hcomp.isMultiplicative hreg, + hc.twistedZorEquiv_one hcomp.isMultiplicative hreg, + hc.twistedZorEquiv_mul hcomp.isMultiplicative hreg, + hc.twistedZorEquiv_matrixUnit hcomp.isMultiplicative hreg⟩ + +/-- **`GPR 22.15` (Petersson), oriented form, isomorphism only.** A reduced composition algebra of +constant rank eight is isomorphic to `Zor(M, θ)` for its lower-left Peirce component `M` and some +orientation `θ` of `M`. -/ +theorem exists_orientation_isomorphic_twistedZor [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + letI : Module.Finite k (ZornTwistingModule (k := k) c) := + IsAlternative.finite_peirceComponent true false + letI : Module.Projective k (ZornTwistingModule (k := k) c) := + IsAlternative.projective_peirceComponent hc.mul_self true false + ∃ θ : (⋀[k]^3 (ZornTwistingModule (k := k) c)) ≃ₗ[k] k, + (twistedZor (Module.VectorProductPair.ofOrientation + (hc.rankAtStalk_twistingModule_eq_three_of_isComposition hcomp hA) θ)).Isomorphic C := by + obtain ⟨θ, -, e, h₁, hmul, -⟩ := hc.exists_orientation_isometryEquiv_twistedZor hcomp hA + exact ⟨θ, e, h₁, hmul⟩ + +/-- **`GPR 22.15` (Petersson), in `GPR`'s words.** Every reduced composition algebra of constant +rank eight is isomorphic to `Zor(M, θ)` for some finitely generated projective module `M` of +constant rank three and some orientation `θ` of `M`. -/ +theorem exists_isomorphic_twistedZor_ofOrientation [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + ∃ (M : Type v) (_ : AddCommGroup M) (_ : Module k M) (_ : Module.Finite k M) + (_ : Module.Projective k M) (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (θ : (⋀[k]^3 M) ≃ₗ[k] k), + (twistedZor (Module.VectorProductPair.ofOrientation hM θ)).Isomorphic C := by + let : Module.Finite k (ZornTwistingModule (k := k) c) := + IsAlternative.finite_peirceComponent true false + let : Module.Projective k (ZornTwistingModule (k := k) c) := + IsAlternative.projective_peirceComponent hc.mul_self true false + obtain ⟨θ, h⟩ := hc.exists_orientation_isomorphic_twistedZor hcomp hA + exact ⟨ZornTwistingModule (k := k) c, inferInstance, inferInstance, inferInstance, + inferInstance, _, θ, h⟩ + +end ConicAlgebra.IsElementaryIdempotent + +namespace ConicAlgebra + +variable {k : Type u} [CommRing k] + +/-- Twisted Zorn vector matrices on a finite projective module of constant rank three have +constant rank eight: `1 + 3 + 1 + 3`. -/ +theorem rankAtStalk_twistedZor {M : Type v} [AddCommGroup M] [Module k M] [Module.Finite k M] + [Module.Projective k M] (P : Module.VectorProductPair k M) + (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) : + Module.rankAtStalk (R := k) (TwistedZor P) = fun _ ↦ 8 := by + change Module.rankAtStalk (R := k) ((k × Module.Dual k M) × (k × M)) = _ + rw [Module.rankAtStalk_prod, Module.rankAtStalk_prod, Module.rankAtStalk_prod, + TauCeti.Module.rankAtStalk_dual, hM] + ext p + have := p.nontrivial + simp + +variable {A : Type v} [NonAssocRing A] [Module k A] [SMulCommClass k A A] [IsScalarTower k A A] + [IsAlternative A] [Module.Finite k A] [Module.Projective k A] + +/-- **`GPR 22.15` (Petersson).** Up to isomorphism, the reduced octonion algebras are precisely +the algebras `Zor(M, θ)` of twisted Zorn vector matrices, for `M` finitely generated projective of +constant rank three and `θ` an orientation of `M`. A reduced octonion algebra is expressed as a +composition algebra of constant rank eight with an elementary idempotent; by `GPR 22.7` these are +the idempotents `GPR 22.6` asks for (absolutely primitive ones) when `k ≠ 0`. The direction `→` is +`IsElementaryIdempotent.exists_isomorphic_twistedZor_ofOrientation`; the direction `←` is the +first half of `GPR 22.15`'s proof (`isComposition_twistedZor`, +`hasElementaryIdempotent_twistedZor`), together with the rank count `rankAtStalk_twistedZor`. -/ +theorem exists_isomorphic_twistedZor_ofOrientation_iff (C : ConicAlgebra k A) : + (∃ (M : Type v) (_ : AddCommGroup M) (_ : Module k M) (_ : Module.Finite k M) + (_ : Module.Projective k M) (hM : Module.rankAtStalk (R := k) M = fun _ ↦ 3) + (θ : (⋀[k]^3 M) ≃ₗ[k] k), + (twistedZor (Module.VectorProductPair.ofOrientation hM θ)).Isomorphic C) ↔ + C.IsComposition.{u, v, u} ∧ C.HasElementaryIdempotent ∧ + Module.rankAtStalk (R := k) A = fun _ ↦ 8 := by + constructor + · rintro ⟨M, _, _, _, _, hM, θ, h⟩ + refine ⟨h.symm.isComposition isComposition_twistedZor, ?_, ?_⟩ + · exact h.hasElementaryIdempotent_iff.mp (hasElementaryIdempotent_twistedZor _) + · obtain ⟨e, -, -⟩ := h + rw [← Module.rankAtStalk_eq_of_equiv e.toLinearEquiv] + exact rankAtStalk_twistedZor _ hM + · rintro ⟨hcomp, ⟨c, hc⟩, hA⟩ + exact hc.exists_isomorphic_twistedZor_ofOrientation hcomp hA + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Peirce.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Peirce.lean new file mode 100644 index 0000000000..4463bfacb5 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Peirce.lean @@ -0,0 +1,770 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.Alternating.Basic +public import Mathlib.Tactic.FinCases +public import Mathlib.Tactic.Module +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs +public import LeanPool.CompositionAlgebrasOverRings.Module.Invertible +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Peirce + +/-! +# Peirce decomposition at an elementary idempotent + +This file specializes the singular Peirce decomposition [GPR, Exc. 14.12] to an elementary +idempotent in a multiplicative conic alternative algebra. It proves [GPR, Exc. 19.35(1)--(6)]: the +diagonal components, existence of Peirce coordinates, and the coordinate formulas for the norm, +polar form, trace, and conjugation. Under regularity it also proves that the two off-diagonal +components are in duality under the polar form, and it constructs the alternating trace trilinear +form at the end of the exercise. `GPR 19.11` supplies regularity for a constant-rank composition +algebra of rank other than one. + +## Main results + +* `ConicAlgebra.IsElementaryIdempotent.eq_trace_smul_peirceIdempotent`: an element of a diagonal + Peirce component is its trace times the corresponding idempotent. +* `ConicAlgebra.IsElementaryIdempotent.peirceComponent_same`: `Cᵢᵢ = k cᵢ`. +* `ConicAlgebra.IsElementaryIdempotent.norm_peirceElement`: the norm formula (3). +* `ConicAlgebra.IsElementaryIdempotent.polar_peirceElement`: the polar formula (4). +* `ConicAlgebra.IsElementaryIdempotent.trace_peirceElement`: the trace formula (5). +* `ConicAlgebra.IsElementaryIdempotent.conj_peirceElement`: the conjugation formula (6). +* `ConicAlgebra.IsElementaryIdempotent.mul_add_mul_eq_zero_of_mem_peirceComponent`: + multiplication within an off-diagonal component is alternating. +* `ConicAlgebra.IsElementaryIdempotent.mul_eq_neg_polar_smul_peirceIdempotent`: the product of + opposite off-diagonal components. +* `ConicAlgebra.IsElementaryIdempotent.offDiagonalDuality`: the duality `C₁₂ ≃ C₂₁*` when + the norm is regular. +* `ConicAlgebra.IsElementaryIdempotent.isLocallyFreeRankOne_offDiagonal`: in rank four the + off-diagonal components are line bundles, the rank count in `GPR 22.13`. +* `ConicAlgebra.IsElementaryIdempotent.mul_eq_zero_of_mem_offDiagonal_of_rankAtStalk_eq_four`: + multiplication within either off-diagonal component vanishes in rank four. +* `ConicAlgebra.IsElementaryIdempotent.peirceTraceAlternating`: the alternating form + `(x, y, z) ↦ t((xy)z)` on either off-diagonal component. + +The duality theorem is stated with the regularity it consumes; its composition-algebra corollary +uses `GPR 19.11` under a constant-rank hypothesis. The hyperbolic presentation assembled from +these coordinates is in `Composition/Reduced/Hyperbolic.lean`, and the rank-four twisted-matrix +classification is in `Composition/Reduced/TwistedMatrix.lean`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 14.12, + Exc. 19.35. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra.IsElementaryIdempotent + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] + {C : ConicAlgebra k A} {c : A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] in +/-- Each member of the complementary pair attached to an elementary idempotent is elementary. -/ +theorem peirceIdempotent (hc : C.IsElementaryIdempotent c) (i : Bool) : + C.IsElementaryIdempotent (IsAlternative.peirceIdempotent c i) := by + cases i + · exact hc + · simpa [IsAlternative.peirceIdempotent, hc.conj_eq] using hc.conj + +/-- An element of a diagonal Peirce component is its trace times the corresponding elementary +idempotent [GPR, Exc. 19.35(1)]. -/ +theorem eq_trace_smul_peirceIdempotent (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {x : A} {i : Bool} + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i i) : + x = C.trace x • IsAlternative.peirceIdempotent c i := by + let d := IsAlternative.peirceIdempotent c i + have hd : C.IsElementaryIdempotent d := hc.peirceIdempotent i + have hdx : d * x = x := (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self i i).mp hx |>.1 + have hxd : x * d = x := (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self i i).mp hx |>.2 + have hnx : C.norm x = 0 := by + calc + C.norm x = C.norm (d * x) := congr_arg C.norm hdx.symm + _ = C.norm d * C.norm x := hmul.norm_mul d x + _ = 0 := by rw [hd.norm_eq_zero, zero_mul] + have hndx : C.norm (d + x) = 0 := by + have hfix : d * (d + x) = d + x := by rw [mul_add, hd.mul_self, hdx] + calc + C.norm (d + x) = C.norm (d * (d + x)) := congr_arg C.norm hfix.symm + _ = C.norm d * C.norm (d + x) := hmul.norm_mul d (d + x) + _ = 0 := by rw [hd.norm_eq_zero, zero_mul] + have hxx := C.mul_self_eq x + rw [hnx, zero_smul, sub_zero] at hxx + have hsum := C.mul_self_eq (d + x) + rw [hndx, zero_smul, sub_zero] at hsum + simp only [add_mul, mul_add, hd.mul_self, hdx, hxd, hxx, map_add, hd.trace_eq_one, + one_smul, add_smul] at hsum + have hcancel : d + x + (x + C.trace x • x) = + d + x + (C.trace x • d + C.trace x • x) := hsum.trans (by module) + have hcancel' : x + C.trace x • x = C.trace x • d + C.trace x • x := + add_left_cancel hcancel + change x = C.trace x • d + exact add_right_cancel hcancel' + +/-- The diagonal Peirce component `Cᵢᵢ` is the scalar line `k cᵢ` +[GPR, Exc. 19.35(1)]. -/ +theorem peirceComponent_same (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (i : Bool) : + IsAlternative.peirceComponent (R := k) c i i = + k ∙ IsAlternative.peirceIdempotent c i := by + apply le_antisymm + · intro x hx + rw [hc.eq_trace_smul_peirceIdempotent hmul hx] + exact Submodule.smul_mem _ _ (Submodule.mem_span_singleton_self _) + · rw [Submodule.span_le] + intro x hx + simp only [Set.mem_singleton_iff] at hx + subst x + exact (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self + (x := IsAlternative.peirceIdempotent c i) i i).mpr + ⟨IsAlternative.peirceIdempotent_mul_self hc.mul_self i, + IsAlternative.peirceIdempotent_mul_self hc.mul_self i⟩ + +/-- A diagonal Peirce component at an elementary idempotent is linearly equivalent to the base +ring, by `a ↦ a cᵢ`; the inverse is the trace [GPR, Exc. 19.35(1)]. -/ +def diagonalEquiv (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) (i : Bool) : + k ≃ₗ[k] IsAlternative.peirceComponent (R := k) c i i where + toFun a := ⟨a • IsAlternative.peirceIdempotent c i, by + rw [hc.peirceComponent_same hmul] + exact Submodule.smul_mem _ _ (Submodule.mem_span_singleton_self _)⟩ + invFun x := C.trace x + map_add' a b := by ext; exact add_smul a b _ + map_smul' a b := by ext; exact mul_smul a b _ + left_inv a := by simp [map_smul, (hc.peirceIdempotent i).trace_eq_one] + right_inv x := Subtype.ext (hc.eq_trace_smul_peirceIdempotent hmul x.property).symm + +omit [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] in +/-- Conjugation exchanges the two complementary idempotents. -/ +theorem conj_peirceIdempotent (hc : C.IsElementaryIdempotent c) (i : Bool) : + C.conj (IsAlternative.peirceIdempotent c i) = + IsAlternative.peirceIdempotent c (!i) := by + cases i + · exact hc.conj_eq + · simpa [IsAlternative.peirceIdempotent] using (hc.peirceIdempotent true).conj_eq + +/-- Every Peirce component is totally singular for the quadratic norm: each of its elements has +norm zero. -/ +theorem norm_eq_zero_of_mem_peirceComponent (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {x : A} {i j : Bool} + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) : C.norm x = 0 := by + let d := IsAlternative.peirceIdempotent c i + have hd : C.IsElementaryIdempotent d := hc.peirceIdempotent i + have hdx : d * x = x := + (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self i j).mp hx |>.1 + calc + C.norm x = C.norm (d * x) := congr_arg C.norm hdx.symm + _ = C.norm d * C.norm x := hmul.norm_mul d x + _ = 0 := by rw [hd.norm_eq_zero, zero_mul] + +/-- Peirce components with the same left index are mutually orthogonal for the polar form. -/ +theorem polar_eq_zero_of_mem_peirceComponent_of_left_eq + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {x y : A} {i j l : Bool} + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c i l) : + QuadraticMap.polar C.norm x y = 0 := by + have hix : IsAlternative.peirceIdempotent c i * x = x := + (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self i j).mp hx |>.1 + calc + QuadraticMap.polar C.norm x y = QuadraticMap.polar C.norm + (IsAlternative.peirceIdempotent c i * x) y := congr_arg (fun z ↦ + QuadraticMap.polar C.norm z y) hix.symm + _ = QuadraticMap.polar C.norm x + (C.conj (IsAlternative.peirceIdempotent c i) * y) := + hmul.polar_mul_left _ _ _ + _ = QuadraticMap.polar C.norm x + (IsAlternative.peirceIdempotent c (!i) * y) := by rw [hc.conj_peirceIdempotent] + _ = 0 := by + rw [IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self hy] + cases i <;> simp + +/-- Peirce components with the same right index are mutually orthogonal for the polar form. -/ +theorem polar_eq_zero_of_mem_peirceComponent_of_right_eq + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {x y : A} {i m j : Bool} + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c m j) : + QuadraticMap.polar C.norm x y = 0 := by + have hxj : x * IsAlternative.peirceIdempotent c j = x := + (IsAlternative.mem_peirceComponent_iff_mul_eq hc.mul_self i j).mp hx |>.2 + calc + QuadraticMap.polar C.norm x y = QuadraticMap.polar C.norm + (x * IsAlternative.peirceIdempotent c j) y := congr_arg (fun z ↦ + QuadraticMap.polar C.norm z y) hxj.symm + _ = QuadraticMap.polar C.norm x + (y * C.conj (IsAlternative.peirceIdempotent c j)) := + hmul.polar_mul_right _ _ _ + _ = QuadraticMap.polar C.norm x + (y * IsAlternative.peirceIdempotent c (!j)) := by rw [hc.conj_peirceIdempotent] + _ = 0 := by + rw [IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self hy] + cases j <;> simp + +/-- An off-diagonal Peirce component has trace zero. -/ +theorem trace_eq_zero_of_mem_peirceComponent (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {x : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) : C.trace x = 0 := by + have hi : IsAlternative.peirceIdempotent c i ∈ + IsAlternative.peirceComponent (R := k) c i i := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self i + have hj : IsAlternative.peirceIdempotent c j ∈ + IsAlternative.peirceComponent (R := k) c j j := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self j + have hsum : IsAlternative.peirceIdempotent c i + + IsAlternative.peirceIdempotent c j = 1 := by + cases i <;> cases j <;> simp_all [IsAlternative.peirceIdempotent] + rw [trace_apply, ← hsum, QuadraticMap.polar_add_left, + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul hi hx, + hc.polar_eq_zero_of_mem_peirceComponent_of_right_eq hmul hj hx, add_zero] + +/-- Every element of an off-diagonal Peirce component has square zero. -/ +theorem mul_self_eq_zero_of_mem_peirceComponent (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {x : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) : x * x = 0 := by + rw [C.mul_self_eq, hc.trace_eq_zero_of_mem_peirceComponent hmul hij hx, + hc.norm_eq_zero_of_mem_peirceComponent hmul hx, zero_smul, zero_smul, sub_zero] + +/-- Multiplication restricted to one off-diagonal Peirce component is alternating: +`x * y + y * x = 0` [GPR, Exc. 14.12]. This is the linearization of the square-zero rule and does +not divide by `2`. -/ +theorem mul_add_mul_eq_zero_of_mem_peirceComponent + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c i j) : + x * y + y * x = 0 := by + have hxy : x + y ∈ IsAlternative.peirceComponent (R := k) c i j := + (IsAlternative.peirceComponent (R := k) c i j).add_mem hx hy + have hsum := hc.mul_self_eq_zero_of_mem_peirceComponent hmul hij hxy + calc + x * y + y * x = y * x + x * y := add_comm _ _ + _ = 0 := by + simpa only [add_mul, mul_add, + hc.mul_self_eq_zero_of_mem_peirceComponent hmul hij hx, + hc.mul_self_eq_zero_of_mem_peirceComponent hmul hij hy, zero_add, add_zero] using hsum + +/-- Products in one off-diagonal Peirce component anticommute [GPR, Exc. 14.12]. This formulation is +valid in characteristic `2`, where the negation may be invisible. -/ +theorem mul_eq_neg_mul_of_mem_peirceComponent + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c i j) : + x * y = -(y * x) := by + rw [eq_neg_iff_add_eq_zero] + exact hc.mul_add_mul_eq_zero_of_mem_peirceComponent hmul hij hx hy + +/-- The product of elements in opposite off-diagonal Peirce components is their negative polar +pairing times the corresponding diagonal idempotent [GPR, Exc. 14.12, Exc. 19.35]: +`xy = -n(x, y)cᵢ` for `x ∈ Cᵢⱼ` and `y ∈ Cⱼᵢ`. -/ +theorem mul_eq_neg_polar_smul_peirceIdempotent + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c j i) : + x * y = -QuadraticMap.polar C.norm x y • IsAlternative.peirceIdempotent c i := by + have hxy : x * y ∈ IsAlternative.peirceComponent (R := k) c i i := + IsAlternative.mul_mem_peirceComponent_of_opposite hc.mul_self hij hx hy + calc + x * y = C.trace (x * y) • IsAlternative.peirceIdempotent c i := + hc.eq_trace_smul_peirceIdempotent hmul hxy + _ = -QuadraticMap.polar C.norm x y • IsAlternative.peirceIdempotent c i := by + rw [hmul.trace_mul, hc.trace_eq_zero_of_mem_peirceComponent hmul hij hx, + hc.trace_eq_zero_of_mem_peirceComponent hmul (Ne.symm hij) hy, zero_mul, zero_sub] + +/-- The Peirce trace trilinear form vanishes when its first two arguments agree. -/ +theorem trace_mul_mul_self_left (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {i j : Bool} (hij : i ≠ j) + (x y : IsAlternative.peirceComponent (R := k) c i j) : + C.trace (((x : A) * x) * y) = 0 := by + rw [hc.mul_self_eq_zero_of_mem_peirceComponent hmul hij x.property, zero_mul, map_zero] + +/-- The Peirce trace trilinear form vanishes when its last two arguments agree. -/ +theorem trace_mul_mul_self_right (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {i j : Bool} (hij : i ≠ j) + (x y : IsAlternative.peirceComponent (R := k) c i j) : + C.trace (((x : A) * y) * y) = 0 := by + rw [IsAlternative.mul_self_mul_right, hc.mul_self_eq_zero_of_mem_peirceComponent hmul hij + y.property, mul_zero, map_zero] + +/-- The Peirce trace trilinear form vanishes when its outside arguments agree. -/ +theorem trace_mul_mul_self_outer (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {i j : Bool} (hij : i ≠ j) + (x y : IsAlternative.peirceComponent (R := k) c i j) : + C.trace (((x : A) * y) * x) = 0 := by + have htrace : C.trace (x : A) = 0 := + hc.trace_eq_zero_of_mem_peirceComponent hmul hij x.property + have hnorm : C.norm (x : A) = 0 := hc.norm_eq_zero_of_mem_peirceComponent hmul x.property + have hpolar : QuadraticMap.polar C.norm ((x : A) * y) x = 0 := by + rw [hmul.polar_mul_left, C.conj_mul_self, hnorm, zero_smul, + QuadraticMap.polar_zero_right] + rw [hmul.trace_mul, htrace, mul_zero, hpolar, sub_zero] + +/-- The trilinear form `(x, y, z) ↦ t((xy)z)` on a Peirce component. -/ +def peirceTraceTrilinear (C : ConicAlgebra k A) (c : A) (i j : Bool) : + MultilinearMap k + (fun _ : Fin 3 ↦ IsAlternative.peirceComponent (R := k) c i j) k := + MultilinearMap.mk' (fun x ↦ C.trace (((x 0 : A) * x 1) * x 2)) (by + intro x m y z + fin_cases m <;> simp [Function.update, Fin.ext_iff, add_mul, mul_add]) + (by + intro x m r y + fin_cases m <;> simp [Function.update, Fin.ext_iff, smul_mul_assoc, mul_smul_comm]) + +omit [IsAlternative A] in +@[simp] theorem peirceTraceTrilinear_apply (C : ConicAlgebra k A) (c : A) (i j : Bool) + (x : Fin 3 → IsAlternative.peirceComponent (R := k) c i j) : + peirceTraceTrilinear C c i j x = C.trace (((x 0 : A) * x 1) * x 2) := rfl + +/-- The alternating trilinear form on an off-diagonal Peirce component at the end of +[GPR, Exc. 19.35]. -/ +def peirceTraceAlternating (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + {i j : Bool} (hij : i ≠ j) : + IsAlternative.peirceComponent (R := k) c i j [⋀^Fin 3]→ₗ[k] k where + __ := peirceTraceTrilinear C c i j + map_eq_zero_of_eq' x m n hmn hne := by + change C.trace (((x 0 : A) * x 1) * x 2) = 0 + fin_cases m <;> fin_cases n + · exact (hne rfl).elim + · have h : x 0 = x 1 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_left hmul hij (x 1) (x 2) + · have h : x 0 = x 2 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_outer hmul hij (x 2) (x 1) + · have h : x 1 = x 0 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_left hmul hij (x 0) (x 2) + · exact (hne rfl).elim + · have h : x 1 = x 2 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_right hmul hij (x 0) (x 2) + · have h : x 2 = x 0 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_outer hmul hij (x 0) (x 1) + · have h : x 2 = x 1 := by + convert hmn using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h] + exact hc.trace_mul_mul_self_right hmul hij (x 0) (x 1) + · exact (hne rfl).elim + +@[simp] theorem peirceTraceAlternating_apply (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) {i j : Bool} (hij : i ≠ j) + (x : Fin 3 → IsAlternative.peirceComponent (R := k) c i j) : + hc.peirceTraceAlternating hmul hij x = C.trace (((x 0 : A) * x 1) * x 2) := rfl + +/-- The element with Peirce coordinates `(a₁, x₁₂, x₂₁, a₂)` relative to an elementary +idempotent `c`; see [GPR, Exc. 19.35(2)]. -/ +def peirceElement (c : A) (a₁ a₂ : k) + (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false) : A := + a₁ • IsAlternative.peirceIdempotent c false + x₁₂ + x₂₁ + + a₂ • IsAlternative.peirceIdempotent c true + +/-- The four projections recover the corresponding Peirce coordinates. -/ +theorem peirceProjection_peirceElement (hc : C.IsElementaryIdempotent c) + (a₁ a₂ : k) (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false) (i j : Bool) : + IsAlternative.peirceProjection (R := k) c i j + (peirceElement c a₁ a₂ x₁₂ x₂₁) = + if (i, j) = (false, false) then a₁ • IsAlternative.peirceIdempotent c false + else if (i, j) = (false, true) then x₁₂ + else if (i, j) = (true, false) then x₂₁ + else a₂ • IsAlternative.peirceIdempotent c true := by + simp only [peirceElement, map_add, map_smul] + have hc₀ : IsAlternative.peirceIdempotent c false ∈ + IsAlternative.peirceComponent (R := k) c false false := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self false + have hc₁ : IsAlternative.peirceIdempotent c true ∈ + IsAlternative.peirceComponent (R := k) c true true := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self true + have hproj (a b : Bool) {x : A} + (hx : x ∈ IsAlternative.peirceComponent (R := k) c a b) : + IsAlternative.peirceProjection (R := k) c i j x = + if (i, j) = (a, b) then x else 0 := by + have h := IsAlternative.peirceProjection_apply_of_mem (R := k) hc.mul_self + (i := i) (j := j) (⟨x, hx⟩ : IsAlternative.peirceComponent (R := k) c a b) + split_ifs with hij + · simpa [hij] using h + · simpa [hij] using h + rw [hproj false false hc₀, hproj false true x₁₂.property, + hproj true false x₂₁.property, hproj true true hc₁] + cases i <;> cases j <;> simp + +/-- Every element has Peirce coordinates as in [GPR, Exc. 19.35(2)]. -/ +theorem exists_eq_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (x : A) : + ∃ (a₁ a₂ : k) (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false), + x = peirceElement c a₁ a₂ x₁₂ x₂₁ := by + let x₁₁ : IsAlternative.peirceComponent (R := k) c false false := + ⟨IsAlternative.peirceProjection (R := k) c false false x, ⟨x, rfl⟩⟩ + let x₁₂ : IsAlternative.peirceComponent (R := k) c false true := + ⟨IsAlternative.peirceProjection (R := k) c false true x, ⟨x, rfl⟩⟩ + let x₂₁ : IsAlternative.peirceComponent (R := k) c true false := + ⟨IsAlternative.peirceProjection (R := k) c true false x, ⟨x, rfl⟩⟩ + let x₂₂ : IsAlternative.peirceComponent (R := k) c true true := + ⟨IsAlternative.peirceProjection (R := k) c true true x, ⟨x, rfl⟩⟩ + refine ⟨C.trace x₁₁, C.trace x₂₂, x₁₂, x₂₁, ?_⟩ + have h₁₁ := hc.eq_trace_smul_peirceIdempotent hmul x₁₁.property + have h₂₂ := hc.eq_trace_smul_peirceIdempotent hmul x₂₂.property + have hdecomp := IsAlternative.sum_peirceProjection_apply (R := k) c x + change x = C.trace x₁₁ • IsAlternative.peirceIdempotent c false + x₁₂ + x₂₁ + + C.trace x₂₂ • IsAlternative.peirceIdempotent c true + rw [← h₁₁, ← h₂₂] + exact hdecomp.symm + +/-- The norm in Peirce coordinates [GPR, Exc. 19.35(3)]. -/ +theorem norm_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (a₁ a₂ : k) (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false) : + C.norm (peirceElement c a₁ a₂ x₁₂ x₂₁) = + a₁ * a₂ + QuadraticMap.polar C.norm x₁₂ x₂₁ := by + have hc₁ : IsAlternative.peirceIdempotent c false ∈ + IsAlternative.peirceComponent (R := k) c false false := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self false + have hc₂ : IsAlternative.peirceIdempotent c true ∈ + IsAlternative.peirceComponent (R := k) c true true := + IsAlternative.peirceIdempotent_mem_peirceComponent hc.mul_self true + have hn₁ : C.norm (IsAlternative.peirceIdempotent c false) = 0 := + (hc.peirceIdempotent false).norm_eq_zero + have hn₂ : C.norm (IsAlternative.peirceIdempotent c true) = 0 := + (hc.peirceIdempotent true).norm_eq_zero + have hn₁₂ : C.norm (x₁₂ : A) = 0 := + hc.norm_eq_zero_of_mem_peirceComponent hmul x₁₂.property + have hn₂₁ : C.norm (x₂₁ : A) = 0 := + hc.norm_eq_zero_of_mem_peirceComponent hmul x₂₁.property + have h₁₁₁₂ : QuadraticMap.polar C.norm + (IsAlternative.peirceIdempotent c false) x₁₂ = 0 := + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul hc₁ x₁₂.property + have h₁₁₂₁ : QuadraticMap.polar C.norm + (IsAlternative.peirceIdempotent c false) x₂₁ = 0 := + hc.polar_eq_zero_of_mem_peirceComponent_of_right_eq hmul hc₁ x₂₁.property + have h₁₂₂₂ : QuadraticMap.polar C.norm x₁₂ + (IsAlternative.peirceIdempotent c true) = 0 := + hc.polar_eq_zero_of_mem_peirceComponent_of_right_eq hmul x₁₂.property hc₂ + have h₂₁₂₂ : QuadraticMap.polar C.norm x₂₁ + (IsAlternative.peirceIdempotent c true) = 0 := + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul x₂₁.property hc₂ + have h₁₁₂₂ : QuadraticMap.polar C.norm + (IsAlternative.peirceIdempotent c false) + (IsAlternative.peirceIdempotent c true) = 1 := by + simpa [IsAlternative.peirceIdempotent, hc.conj_eq] using hc.polar_conj + simp only [peirceElement, C.norm_add, QuadraticMap.map_smul, + QuadraticMap.polar_add_left, + QuadraticMap.polar_smul_left, QuadraticMap.polar_smul_right, hn₁, hn₂, hn₁₂, hn₂₁, + h₁₁₁₂, h₁₁₂₁, h₁₂₂₂, h₂₁₂₂, h₁₁₂₂] + ring + +/-- The polar form in Peirce coordinates [GPR, Exc. 19.35(4)]. -/ +theorem polar_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (a₁ a₂ b₁ b₂ : k) + (x₁₂ y₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ y₂₁ : IsAlternative.peirceComponent (R := k) c true false) : + QuadraticMap.polar C.norm (peirceElement c a₁ a₂ x₁₂ x₂₁) + (peirceElement c b₁ b₂ y₁₂ y₂₁) = + a₁ * b₂ + a₂ * b₁ + QuadraticMap.polar C.norm x₁₂ y₂₁ + + QuadraticMap.polar C.norm x₂₁ y₁₂ := by + rw [QuadraticMap.polar] + have hadd : + peirceElement c a₁ a₂ x₁₂ x₂₁ + peirceElement c b₁ b₂ y₁₂ y₂₁ = + peirceElement c (a₁ + b₁) (a₂ + b₂) (x₁₂ + y₁₂) (x₂₁ + y₂₁) := by + simp only [peirceElement, add_smul, Submodule.coe_add] + module + rw [hadd, hc.norm_peirceElement hmul, hc.norm_peirceElement hmul, + hc.norm_peirceElement hmul] + simp only [Submodule.coe_add, QuadraticMap.polar_add_left, + QuadraticMap.polar_add_right] + rw [QuadraticMap.polar_comm C.norm y₁₂ x₂₁] + ring + +/-- The trace in Peirce coordinates [GPR, Exc. 19.35(5)]. -/ +theorem trace_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (a₁ a₂ : k) (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false) : + C.trace (peirceElement c a₁ a₂ x₁₂ x₂₁) = a₁ + a₂ := by + let z₁₂ : IsAlternative.peirceComponent (R := k) c false true := 0 + let z₂₁ : IsAlternative.peirceComponent (R := k) c true false := 0 + have hone : peirceElement c 1 1 z₁₂ z₂₁ = 1 := by + simp [peirceElement, z₁₂, z₂₁, IsAlternative.peirceIdempotent] + rw [trace_apply, ← hone, hc.polar_peirceElement hmul] + simp [z₁₂, z₂₁, add_comm] + +/-- Conjugation in Peirce coordinates [GPR, Exc. 19.35(6)]: it exchanges the diagonal +coefficients and negates the off-diagonal components. -/ +theorem conj_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (a₁ a₂ : k) (x₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ : IsAlternative.peirceComponent (R := k) c true false) : + C.conj (peirceElement c a₁ a₂ x₁₂ x₂₁) = + peirceElement c a₂ a₁ (-x₁₂) (-x₂₁) := by + rw [ConicAlgebra.conj_apply, hc.trace_peirceElement hmul] + simp only [peirceElement, IsAlternative.peirceIdempotent, Submodule.coe_neg] + module + +/-- The polar pairing from `C₁₂` to the dual of `C₂₁`. -/ +def offDiagonalPairing (C : ConicAlgebra k A) (c : A) : + IsAlternative.peirceComponent (R := k) c false true →ₗ[k] + Module.Dual k (IsAlternative.peirceComponent (R := k) c true false) := + (QuadraticMap.polarBilin C.norm).domRestrict₁₂ + (IsAlternative.peirceComponent (R := k) c false true) + (IsAlternative.peirceComponent (R := k) c true false) + +omit [IsAlternative A] in +@[simp] theorem offDiagonalPairing_apply (C : ConicAlgebra k A) (c : A) + (x : IsAlternative.peirceComponent (R := k) c false true) + (y : IsAlternative.peirceComponent (R := k) c true false) : + offDiagonalPairing C c x y = QuadraticMap.polar C.norm x y := rfl + +/-- Under regularity, the off-diagonal Peirce components are in duality under the polar form, +as in [GPR, Exc. 19.35]. -/ +theorem bijective_offDiagonalPairing (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + Function.Bijective (offDiagonalPairing C c) := by + constructor + · rw [← LinearMap.ker_eq_bot] + apply (Submodule.eq_bot_iff _).mpr + intro x hx + apply Subtype.ext + apply hreg.1 + ext z + simp only [Submodule.coe_zero, map_zero, LinearMap.zero_apply] + change QuadraticMap.polar C.norm x z = 0 + have hdecomp := IsAlternative.sum_peirceProjection_apply (R := k) c z + have h₀₀ : IsAlternative.peirceProjection (R := k) c false false z ∈ + IsAlternative.peirceComponent (R := k) c false false := ⟨z, rfl⟩ + have h₀₁ : IsAlternative.peirceProjection (R := k) c false true z ∈ + IsAlternative.peirceComponent (R := k) c false true := ⟨z, rfl⟩ + have h₁₁ : IsAlternative.peirceProjection (R := k) c true true z ∈ + IsAlternative.peirceComponent (R := k) c true true := ⟨z, rfl⟩ + have hpair := LinearMap.mem_ker.mp hx + have h₁₀ : offDiagonalPairing C c x + ⟨IsAlternative.peirceProjection (R := k) c true false z, ⟨z, rfl⟩⟩ = 0 := by + rw [hpair] + rfl + rw [← hdecomp, QuadraticMap.polar_add_right, QuadraticMap.polar_add_right, + QuadraticMap.polar_add_right] + rw [hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul x.property h₀₀, + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul x.property h₀₁, + show QuadraticMap.polar C.norm x + (IsAlternative.peirceProjection (R := k) c true false z) = 0 from h₁₀, + hc.polar_eq_zero_of_mem_peirceComponent_of_right_eq hmul x.property h₁₁] + simp + · intro f + let p₂₁ : A →ₗ[k] IsAlternative.peirceComponent (R := k) c true false := + (IsAlternative.peirceProjection (R := k) c true false).rangeRestrict + let F : Module.Dual k A := f.comp p₂₁ + obtain ⟨a, ha⟩ := hreg.2 F + let x₁₂ : IsAlternative.peirceComponent (R := k) c false true := + ⟨IsAlternative.peirceProjection (R := k) c false true a, ⟨a, rfl⟩⟩ + refine ⟨x₁₂, ?_⟩ + ext y + have hdecomp := IsAlternative.sum_peirceProjection_apply (R := k) c a + have h₀₀ : IsAlternative.peirceProjection (R := k) c false false a ∈ + IsAlternative.peirceComponent (R := k) c false false := ⟨a, rfl⟩ + have h₁₀ : IsAlternative.peirceProjection (R := k) c true false a ∈ + IsAlternative.peirceComponent (R := k) c true false := ⟨a, rfl⟩ + have h₁₁ : IsAlternative.peirceProjection (R := k) c true true a ∈ + IsAlternative.peirceComponent (R := k) c true true := ⟨a, rfl⟩ + have hpolar : QuadraticMap.polar C.norm a y = + QuadraticMap.polar C.norm x₁₂ y := by + rw [← hdecomp, QuadraticMap.polar_add_left, QuadraticMap.polar_add_left, + QuadraticMap.polar_add_left] + rw [hc.polar_eq_zero_of_mem_peirceComponent_of_right_eq hmul h₀₀ y.property, + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul h₁₀ y.property, + hc.polar_eq_zero_of_mem_peirceComponent_of_left_eq hmul h₁₁ y.property] + simp [x₁₂] + have hp₂₁ : p₂₁ (y : A) = y := + Subtype.ext ((IsAlternative.mem_peirceComponent_iff hc.mul_self true false).mp y.property) + have hay := LinearMap.congr_fun ha (y : A) + change QuadraticMap.polar C.norm a y = f (p₂₁ (y : A)) at hay + rw [hp₂₁] at hay + exact hpolar.symm.trans hay + +/-- The linear equivalence expressing the duality between `C₁₂` and `C₂₁` +[GPR, Exc. 19.35]. -/ +noncomputable def offDiagonalDuality (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + IsAlternative.peirceComponent (R := k) c false true ≃ₗ[k] + Module.Dual k (IsAlternative.peirceComponent (R := k) c true false) := + LinearEquiv.ofBijective (offDiagonalPairing C c) + (hc.bijective_offDiagonalPairing hmul hreg) + +/-- **The rank count in `GPR 22.13`.** At an elementary idempotent in a constant-rank-four +composition algebra with regular norm, both off-diagonal Peirce components have constant rank +one. Thus each is a line bundle. -/ +theorem rankAtStalk_offDiagonal_eq_one [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (hreg : C.norm.IsGPRRegular) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) (i : Bool) : + Module.rankAtStalk (R := k) + (IsAlternative.peirceComponent (R := k) c i (!i)) = 1 := by + let X (a b : Bool) := IsAlternative.peirceComponent (R := k) c a b + let (a b : Bool) : Module.Finite k (X a b) := + IsAlternative.finite_peirceComponent a b + let (a b : Bool) : Module.Projective k (X a b) := + IsAlternative.projective_peirceComponent hc.mul_self a b + have hdiag (a : Bool) : Module.rankAtStalk (R := k) (X a a) = + Module.rankAtStalk (R := k) k := + Module.rankAtStalk_eq_of_equiv (hc.diagonalEquiv hmul a).symm + have hoff : Module.rankAtStalk (R := k) (X false true) = + Module.rankAtStalk (R := k) (X true false) := by + calc + Module.rankAtStalk (R := k) (X false true) = + Module.rankAtStalk (R := k) (Module.Dual k (X true false)) := + Module.rankAtStalk_eq_of_equiv (hc.offDiagonalDuality hmul hreg) + _ = Module.rankAtStalk (R := k) (X true false) := TauCeti.Module.rankAtStalk_dual _ _ + change Module.rankAtStalk (R := k) (X i (!i)) = 1 + ext p + let : Nontrivial k := ⟨⟨0, 1, fun h ↦ p.2.ne_top <| + (Ideal.eq_top_iff_one p.asIdeal).mpr <| by simpa [h] using p.asIdeal.zero_mem⟩⟩ + have htotal := congrFun + (Module.rankAtStalk_eq_of_equiv + (IsAlternative.peirceDecomposition (R := k) hc.mul_self)) p + rw [hA] at htotal + simp only [Pi.one_apply] at htotal ⊢ + rw [Module.rankAtStalk_pi] at htotal + rw [finsum_eq_sum_of_fintype, Fintype.sum_prod_type] at htotal + simp only [Fintype.univ_bool, Finset.mem_singleton, Bool.true_eq_false, not_false_eq_true, + Finset.sum_insert, Finset.sum_singleton, add_assoc] at htotal + rw [congrFun (hdiag false) p, congrFun (hdiag true) p, + Module.rankAtStalk_self, congrFun hoff p] at htotal + simp only [Pi.one_apply] at htotal + dsimp [X] at htotal ⊢ + cases i + · change Module.rankAtStalk + (IsAlternative.peirceComponent (R := k) c false true) p = 1 + have heq := congrFun hoff p + dsimp [X] at heq + rw [heq] + omega + · change Module.rankAtStalk + (IsAlternative.peirceComponent (R := k) c true false) p = 1 + omega + +/-- **The line-bundle step in `GPR 22.13`.** In a rank-four composition algebra with an +elementary idempotent, each off-diagonal Peirce component is finite projective of constant rank +one. The regularity needed for the duality and rank count is supplied by `GPR 19.11`. -/ +theorem isLocallyFreeRankOne_offDiagonal [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) (i : Bool) : + Module.IsLocallyFreeRankOne k + (IsAlternative.peirceComponent (R := k) c i (!i)) := by + let : Module.Finite k + (IsAlternative.peirceComponent (R := k) c i (!i)) := + IsAlternative.finite_peirceComponent i (!i) + let : Module.Projective k + (IsAlternative.peirceComponent (R := k) c i (!i)) := + IsAlternative.projective_peirceComponent hc.mul_self i (!i) + exact ⟨inferInstance, inferInstance, + hc.rankAtStalk_offDiagonal_eq_one hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) hA i⟩ + +/-- **The vanishing product needed in `GPR 22.13`.** In a rank-four composition algebra, +multiplication of any two elements in the same off-diagonal Peirce component is zero. The +component is a line bundle, and its internal multiplication is alternating because every element +squares to zero. -/ +theorem mul_eq_zero_of_mem_offDiagonal_of_rankAtStalk_eq_four + [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ IsAlternative.peirceComponent (R := k) c i j) + (hy : y ∈ IsAlternative.peirceComponent (R := k) c i j) : x * y = 0 := by + have hji : j = !i := by cases i <;> cases j <;> simp_all + subst j + let X := IsAlternative.peirceComponent (R := k) c i (!i) + let B : LinearMap.BilinMap k X A := + (LinearMap.mul k A).compl₁₂ X.subtype X.subtype + have hline : Module.IsLocallyFreeRankOne k X := by + simpa [X] using hc.isLocallyFreeRankOne_offDiagonal hcomp hA i + have hB : B = 0 := hline.bilinMap_eq_zero_of_map_self_eq_zero B fun z ↦ + hc.mul_self_eq_zero_of_mem_peirceComponent hcomp.isMultiplicative hij z.property + have hxy := LinearMap.congr_fun₂ hB (⟨x, hx⟩ : X) (⟨y, hy⟩ : X) + simpa [B] using hxy + +/-- The complete Peirce-coordinate multiplication formula in rank four, the multiplication table +used in the converse half of `GPR 22.13`. -/ +theorem mul_peirceElement_of_rankAtStalk_eq_four [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (a₁ a₂ b₁ b₂ : k) + (x₁₂ y₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ y₂₁ : IsAlternative.peirceComponent (R := k) c true false) : + peirceElement c a₁ a₂ x₁₂ x₂₁ * peirceElement c b₁ b₂ y₁₂ y₂₁ = + peirceElement c + (a₁ * b₁ - QuadraticMap.polar C.norm x₁₂ y₂₁) + (a₂ * b₂ - QuadraticMap.polar C.norm y₁₂ x₂₁) + (a₁ • y₁₂ + b₂ • x₁₂) (b₁ • x₂₁ + a₂ • y₂₁) := by + let c₁ := IsAlternative.peirceIdempotent c false + let c₂ := IsAlternative.peirceIdempotent c true + have hc₁ := IsAlternative.peirceIdempotent_mul_self hc.mul_self false + have hc₂ := IsAlternative.peirceIdempotent_mul_self hc.mul_self true + have hc₁c₂ := + IsAlternative.peirceIdempotent_mul_eq_zero hc.mul_self (by decide : false ≠ true) + have hc₂c₁ := + IsAlternative.peirceIdempotent_mul_eq_zero hc.mul_self (by decide : true ≠ false) + have hleft (x : IsAlternative.peirceComponent (R := k) c false true) : c₁ * x = x := by + simpa [c₁] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property false + have hright (x : IsAlternative.peirceComponent (R := k) c false true) : x * c₂ = x := by + simpa [c₂] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property true + have hleft0 (x : IsAlternative.peirceComponent (R := k) c false true) : c₂ * x = 0 := by + simpa [c₂] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property true + have hright0 (x : IsAlternative.peirceComponent (R := k) c false true) : x * c₁ = 0 := by + simpa [c₁] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property false + have hleft' (x : IsAlternative.peirceComponent (R := k) c true false) : c₂ * x = x := by + simpa [c₂] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property true + have hright' (x : IsAlternative.peirceComponent (R := k) c true false) : x * c₁ = x := by + simpa [c₁] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property false + have hleft0' (x : IsAlternative.peirceComponent (R := k) c true false) : c₁ * x = 0 := by + simpa [c₁] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property false + have hright0' (x : IsAlternative.peirceComponent (R := k) c true false) : x * c₂ = 0 := by + simpa [c₂] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property true + have h₁₂₁₂ : (x₁₂ : A) * y₁₂ = 0 := + hc.mul_eq_zero_of_mem_offDiagonal_of_rankAtStalk_eq_four hcomp hA (by decide) + x₁₂.property y₁₂.property + have h₂₁₂₁ : (x₂₁ : A) * y₂₁ = 0 := + hc.mul_eq_zero_of_mem_offDiagonal_of_rankAtStalk_eq_four hcomp hA (by decide) + x₂₁.property y₂₁.property + have h₁₂₂₁ := hc.mul_eq_neg_polar_smul_peirceIdempotent hcomp.isMultiplicative + (by decide : false ≠ true) x₁₂.property y₂₁.property + have h₂₁₁₂ := hc.mul_eq_neg_polar_smul_peirceIdempotent hcomp.isMultiplicative + (by decide : true ≠ false) x₂₁.property y₁₂.property + simp only [IsAlternative.peirceIdempotent_false, + IsAlternative.peirceIdempotent_true] at h₁₂₂₁ h₂₁₁₂ + dsimp [c₁, c₂] at hc₁ hc₂ hc₁c₂ hc₂c₁ hleft hright + dsimp [c₁, c₂] at hleft0 hright0 hleft' hright' hleft0' hright0' + simp only [peirceElement, add_mul, mul_add, smul_mul_assoc, mul_smul_comm, + IsAlternative.peirceIdempotent_false, IsAlternative.peirceIdempotent_true] + rw [hc₁, hc₁c₂, hc₂c₁, hc₂, hleft y₁₂, hleft0' y₂₁, hleft0 y₁₂, + hleft' y₂₁, hright0 x₁₂, hright x₁₂, hright' x₂₁, hright0' x₂₁, + h₁₂₁₂, h₂₁₂₁, h₁₂₂₁, h₂₁₁₂] + simp only [smul_zero, add_zero, zero_add, Submodule.coe_add, + Submodule.coe_smul] + rw [QuadraticMap.polar_comm C.norm x₂₁ y₁₂] + module + +/-- For a constant-rank composition algebra of rank other than one, `C₁₂` and `C₂₁` are in +duality under the polar form [GPR, Exc. 19.35]. Regularity is supplied by `GPR 19.11`. -/ +noncomputable def offDiagonalDualityOfIsComposition [Module.Finite k A] + [Module.Projective k A] (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) {r : ℕ} + (hrank : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : r ≠ 1) : + IsAlternative.peirceComponent (R := k) c false true ≃ₗ[k] + Module.Dual k (IsAlternative.peirceComponent (R := k) c true false) := + hc.offDiagonalDuality hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hrank hr) + +end ConicAlgebra.IsElementaryIdempotent diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankEight.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankEight.lean new file mode 100644 index 0000000000..4d376b123f --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankEight.lean @@ -0,0 +1,417 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedZorn + +/-! +# Reduced composition algebras of rank eight (`GPR 22.15`) + +At an elementary idempotent `c`, put `M = C₂₁`. Regularity identifies `C₁₂` with `M*` +through the polar form. Multiplication within the two off-diagonal Peirce components then gives +the associated vector products + + `M × M → M*`, `M* × M* → M`. + +The second linearization of norm multiplicativity is exactly their Binet–Cauchy identity. Thus +the Peirce-coordinate map identifies the algebra with the twisted Zorn vector matrices attached +to this vector-product pair. In constant rank eight the rank count makes `M` projective of +constant rank three. This is Petersson's converse theorem `GPR 22.15`, in vector-product-pair +form. `GPR 22.15` states it with an **orientation** `θ` of `M`, as `C ≅ Zor(M, θ)`; that form is +`Composition/Reduced/OrientedRankEight.lean`, which builds from any vector-product pair on a +rank-three module the orientation inducing it. + +## Main definitions + +* `ConicAlgebra.IsElementaryIdempotent.peirceVectorProductPair` : the vector products read from + Peirce multiplication. +* `ConicAlgebra.IsElementaryIdempotent.twistedZorEquiv` : the Peirce-coordinate equivalence from + the resulting twisted Zorn algebra. + +## Main results + +* `ConicAlgebra.IsElementaryIdempotent.isomorphic_twistedZor` : the twisted Zorn algebra is + isomorphic to the original algebra. +* `ConicAlgebra.IsElementaryIdempotent.rankAtStalk_twistingModule_eq_three` : in rank eight the + twisting module has constant rank three. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 19.35, 22.15. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra.IsElementaryIdempotent + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] + {C : ConicAlgebra k A} {c : A} + +/-- The lower-left Peirce component used as the twisting module in `GPR 22.15`. -/ +abbrev ZornTwistingModule (c : A) := + IsAlternative.peirceComponent (R := k) c true false + +/-- Multiplication of two elements of the lower-left Peirce component `ZornTwistingModule c`, +which lands in the upper-right component. -/ +noncomputable def lowerProduct (hc : C.IsElementaryIdempotent c) : + ZornTwistingModule (k := k) c →ₗ[k] ZornTwistingModule (k := k) c →ₗ[k] + IsAlternative.peirceComponent (R := k) c false true := + LinearMap.mk₂ k (fun x y ↦ + ⟨(x : A) * y, IsAlternative.mul_mem_peirceComponent_swap hc.mul_self + (by decide) x.property y.property⟩) + (fun _ _ _ ↦ Subtype.ext (add_mul ..)) + (fun _ _ _ ↦ Subtype.ext (smul_mul_assoc ..)) + (fun _ _ _ ↦ Subtype.ext (mul_add ..)) + (fun _ _ _ ↦ Subtype.ext (mul_smul_comm ..)) + +/-- Multiplication of two elements of the upper-right Peirce component, which lands in +`ZornTwistingModule c`. -/ +noncomputable def upperProduct (hc : C.IsElementaryIdempotent c) : + IsAlternative.peirceComponent (R := k) c false true →ₗ[k] + IsAlternative.peirceComponent (R := k) c false true →ₗ[k] + ZornTwistingModule (k := k) c := + LinearMap.mk₂ k (fun x y ↦ + ⟨(x : A) * y, IsAlternative.mul_mem_peirceComponent_swap hc.mul_self + (by decide) x.property y.property⟩) + (fun _ _ _ ↦ Subtype.ext (add_mul ..)) + (fun _ _ _ ↦ Subtype.ext (smul_mul_assoc ..)) + (fun _ _ _ ↦ Subtype.ext (mul_add ..)) + (fun _ _ _ ↦ Subtype.ext (mul_smul_comm ..)) + +@[simp] theorem lowerProduct_apply (hc : C.IsElementaryIdempotent c) + (x y : ZornTwistingModule (k := k) c) : + (hc.lowerProduct x y : A) = (x : A) * y := rfl + +@[simp] theorem upperProduct_apply (hc : C.IsElementaryIdempotent c) + (x y : IsAlternative.peirceComponent (R := k) c false true) : + (hc.upperProduct x y : A) = (x : A) * y := rfl + +/-- **The vector-product pair read from Peirce multiplication.** The two products are +multiplication within `C₂₁` and `C₁₂`, transported across polar duality. Their +Binet–Cauchy identity is the second linearization of norm multiplicativity. -/ +noncomputable def peirceVectorProductPair (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + Module.VectorProductPair k (ZornTwistingModule (k := k) c) := by + let e := hc.offDiagonalDuality hmul hreg + let cross := hc.lowerProduct.compr₂ e.toLinearMap + let crossDual := hc.upperProduct.compl₁₂ e.symm.toLinearMap e.symm.toLinearMap + refine ⟨cross, crossDual, ?_, ?_, ?_, ?_, ?_⟩ + · intro x + change e (hc.lowerProduct x x) = 0 + rw [show hc.lowerProduct x x = 0 by + apply Subtype.ext + exact hc.mul_self_eq_zero_of_mem_peirceComponent hmul (by decide) x.property] + exact map_zero e + · intro φ + change hc.upperProduct (e.symm φ) (e.symm φ) = 0 + apply Subtype.ext + exact hc.mul_self_eq_zero_of_mem_peirceComponent hmul (by decide) + (e.symm φ).property + · intro x y + change e (hc.lowerProduct x y) x = 0 + change QuadraticMap.polar C.norm ((x : A) * y) x = 0 + rw [hmul.polar_mul_left, C.conj_mul_self, + hc.norm_eq_zero_of_mem_peirceComponent hmul x.property, zero_smul, + QuadraticMap.polar_zero_right] + · intro φ ψ + change φ (hc.upperProduct (e.symm φ) (e.symm ψ)) = 0 + calc + φ (hc.upperProduct (e.symm φ) (e.symm ψ)) = + e (e.symm φ) (hc.upperProduct (e.symm φ) (e.symm ψ)) := by + rw [e.apply_symm_apply] + _ = QuadraticMap.polar C.norm (e.symm φ) + ((e.symm φ : A) * e.symm ψ) := rfl + _ = 0 := by + rw [QuadraticMap.polar_comm, hmul.polar_mul_left, C.conj_mul_self, + hc.norm_eq_zero_of_mem_peirceComponent hmul (e.symm φ).property, zero_smul, + QuadraticMap.polar_zero_right] + · intro x y φ ψ + let x₁₂ := e.symm φ + let y₁₂ := e.symm ψ + have hlin := hmul.polar_mul_add_polar_mul (x : A) x₁₂ (y : A) y₁₂ + have hxy := hc.mul_eq_neg_polar_smul_peirceIdempotent hmul + (by decide : true ≠ false) x.property y₁₂.property + have hyx := hc.mul_eq_neg_polar_smul_peirceIdempotent hmul + (by decide : false ≠ true) x₁₂.property y.property + change e (hc.lowerProduct x y) + (hc.upperProduct (e.symm φ) (e.symm ψ)) = _ + change QuadraticMap.polar C.norm ((x : A) * y) ((x₁₂ : A) * y₁₂) = + φ x * ψ y - φ y * ψ x + rw [hxy, hyx, QuadraticMap.polar_smul_left, QuadraticMap.polar_smul_right, + QuadraticMap.polar_comm C.norm + (IsAlternative.peirceIdempotent c true) + (IsAlternative.peirceIdempotent c false), + show QuadraticMap.polar C.norm + (IsAlternative.peirceIdempotent c false) + (IsAlternative.peirceIdempotent c true) = 1 by + simpa [IsAlternative.peirceIdempotent, hc.conj_eq] using hc.polar_conj] at hlin + rw [← e.apply_symm_apply φ, ← e.apply_symm_apply ψ] + change _ = e x₁₂ x * e y₁₂ y - e x₁₂ y * e y₁₂ x + have he (z : IsAlternative.peirceComponent (R := k) c false true) + (m : ZornTwistingModule (k := k) c) : + e z m = QuadraticMap.polar C.norm z m := rfl + rw [he, he, he, he] + rw [QuadraticMap.polar_comm C.norm x x₁₂, + QuadraticMap.polar_comm C.norm y y₁₂] at hlin + rw [QuadraticMap.polar_comm C.norm y₁₂ x] + linear_combination hlin + +/-- The complete Peirce-coordinate multiplication formula. It is the twisted Zorn multiplication +formula before naming the two same-component products as vector products. -/ +theorem mul_peirceElement (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (a₁ a₂ b₁ b₂ : k) + (x₁₂ y₁₂ : IsAlternative.peirceComponent (R := k) c false true) + (x₂₁ y₂₁ : ZornTwistingModule (k := k) c) : + peirceElement c a₁ a₂ x₁₂ x₂₁ * peirceElement c b₁ b₂ y₁₂ y₂₁ = + peirceElement c + (a₁ * b₁ - QuadraticMap.polar C.norm x₁₂ y₂₁) + (a₂ * b₂ - QuadraticMap.polar C.norm y₁₂ x₂₁) + (a₁ • y₁₂ + b₂ • x₁₂ + hc.lowerProduct x₂₁ y₂₁) + (b₁ • x₂₁ + a₂ • y₂₁ + hc.upperProduct x₁₂ y₁₂) := by + let c₁ := IsAlternative.peirceIdempotent c false + let c₂ := IsAlternative.peirceIdempotent c true + have hc₁ := IsAlternative.peirceIdempotent_mul_self hc.mul_self false + have hc₂ := IsAlternative.peirceIdempotent_mul_self hc.mul_self true + have hc₁c₂ := + IsAlternative.peirceIdempotent_mul_eq_zero hc.mul_self (by decide : false ≠ true) + have hc₂c₁ := + IsAlternative.peirceIdempotent_mul_eq_zero hc.mul_self (by decide : true ≠ false) + have hleft (x : IsAlternative.peirceComponent (R := k) c false true) : c₁ * x = x := by + simpa [c₁] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property false + have hright (x : IsAlternative.peirceComponent (R := k) c false true) : x * c₂ = x := by + simpa [c₂] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property true + have hleft0 (x : IsAlternative.peirceComponent (R := k) c false true) : c₂ * x = 0 := by + simpa [c₂] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property true + have hright0 (x : IsAlternative.peirceComponent (R := k) c false true) : x * c₁ = 0 := by + simpa [c₁] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property false + have hleft' (x : ZornTwistingModule (k := k) c) : c₂ * x = x := by + simpa [c₂] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property true + have hright' (x : ZornTwistingModule (k := k) c) : x * c₁ = x := by + simpa [c₁] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property false + have hleft0' (x : ZornTwistingModule (k := k) c) : c₁ * x = 0 := by + simpa [c₁] using IsAlternative.peirceIdempotent_mul_of_mem hc.mul_self x.property false + have hright0' (x : ZornTwistingModule (k := k) c) : x * c₂ = 0 := by + simpa [c₂] using IsAlternative.mul_peirceIdempotent_of_mem hc.mul_self x.property true + have h₁₂₂₁ := hc.mul_eq_neg_polar_smul_peirceIdempotent hmul + (by decide : false ≠ true) x₁₂.property y₂₁.property + have h₂₁₁₂ := hc.mul_eq_neg_polar_smul_peirceIdempotent hmul + (by decide : true ≠ false) x₂₁.property y₁₂.property + simp only [IsAlternative.peirceIdempotent_false, + IsAlternative.peirceIdempotent_true] at h₁₂₂₁ h₂₁₁₂ + dsimp [c₁, c₂] at hc₁ hc₂ hc₁c₂ hc₂c₁ hleft hright + dsimp [c₁, c₂] at hleft0 hright0 hleft' hright' hleft0' hright0' + simp only [peirceElement, add_mul, mul_add, smul_mul_assoc, mul_smul_comm, + IsAlternative.peirceIdempotent_false, IsAlternative.peirceIdempotent_true] + rw [hc₁, hc₁c₂, hc₂c₁, hc₂, hleft y₁₂, hleft0' y₂₁, hleft0 y₁₂, + hleft' y₂₁, hright0 x₁₂, hright x₁₂, hright' x₂₁, hright0' x₂₁, + h₁₂₂₁, h₂₁₁₂] + simp only [smul_zero, add_zero, zero_add, Submodule.coe_add, Submodule.coe_smul, + lowerProduct_apply, upperProduct_apply] + rw [QuadraticMap.polar_comm C.norm x₂₁ y₁₂] + module + +/-- The Peirce-coordinate map from the twisted Zorn algebra obtained from multiplication back to +the original algebra. -/ +noncomputable def twistedZorToPeirce (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + TwistedZor (hc.peirceVectorProductPair hmul hreg) →ₗ[k] A := by + let e := hc.offDiagonalDuality hmul hreg + exact + { toFun := fun x ↦ peirceElement c x.1.1 x.2.1 (e.symm x.1.2) x.2.2 + map_add' := fun x y ↦ by + simp only [TwistedZor.fst_add, TwistedZor.snd_add, Prod.fst_add, Prod.snd_add, + map_add, peirceElement, add_smul, Submodule.coe_add] + module + map_smul' := fun a x ↦ by + change peirceElement c (a * x.1.1) (a * x.2.1) (e.symm (a • x.1.2)) + (a • x.2.2) = a • peirceElement c x.1.1 x.2.1 (e.symm x.1.2) x.2.2 + rw [map_smul] + simp only [peirceElement, mul_smul, Submodule.coe_smul, smul_add] } + +@[simp] theorem twistedZorToPeirce_apply (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : TwistedZor (hc.peirceVectorProductPair hmul hreg)) : + hc.twistedZorToPeirce hmul hreg x = peirceElement c x.1.1 x.2.1 + ((hc.offDiagonalDuality hmul hreg).symm x.1.2) x.2.2 := rfl + +/-- The Peirce-coordinate map from the associated twisted Zorn algebra is bijective. -/ +theorem bijective_twistedZorToPeirce (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + Function.Bijective (hc.twistedZorToPeirce hmul hreg) := by + let e := hc.offDiagonalDuality hmul hreg + constructor + · intro x y hxy + have hproj (i j : Bool) := congrArg + (IsAlternative.peirceProjection (R := k) c i j) hxy + apply TwistedZor.ext + · have h := congrArg C.trace (hproj false false) + rw [twistedZorToPeirce_apply, twistedZorToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa [hc.trace_eq_one] using h + · have h := hproj false true + rw [twistedZorToPeirce_apply, twistedZorToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + exact e.symm.injective (by simpa using h) + · have h := congrArg C.trace (hproj true true) + rw [twistedZorToPeirce_apply, twistedZorToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simp only [Prod.mk.injEq, Bool.true_eq_false, and_self, false_and, and_false, + ite_false] at h + have ht : C.trace (IsAlternative.peirceIdempotent c true) = 1 := + (hc.peirceIdempotent true).trace_eq_one + simpa only [map_smul, ht, smul_eq_mul, mul_one] using h + · have h := hproj true false + rw [twistedZorToPeirce_apply, twistedZorToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa using h + · intro a + obtain ⟨a₁, a₂, x₁₂, x₂₁, ha⟩ := hc.exists_eq_peirceElement hmul a + let x : TwistedZor (hc.peirceVectorProductPair hmul hreg) := + (((a₁, e x₁₂), (a₂, x₂₁)) : + (k × Module.Dual k (ZornTwistingModule (k := k) c)) × + (k × ZornTwistingModule (k := k) c)) + refine ⟨x, ?_⟩ + rw [ha, twistedZorToPeirce_apply] + change peirceElement c a₁ a₂ (e.symm (e x₁₂)) x₂₁ = _ + rw [e.symm_apply_apply] + +/-- The linear equivalence underlying the converse construction of `GPR 22.15`. -/ +noncomputable def twistedZorEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + TwistedZor (hc.peirceVectorProductPair hmul hreg) ≃ₗ[k] A := + LinearEquiv.ofBijective (hc.twistedZorToPeirce hmul hreg) + (hc.bijective_twistedZorToPeirce hmul hreg) + +@[simp] theorem twistedZorEquiv_apply (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : TwistedZor (hc.peirceVectorProductPair hmul hreg)) : + hc.twistedZorEquiv hmul hreg x = hc.twistedZorToPeirce hmul hreg x := rfl + +/-- The twisted Zorn equivalence preserves the norm. -/ +theorem norm_twistedZorEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x : TwistedZor (hc.peirceVectorProductPair hmul hreg)) : + C.norm (hc.twistedZorEquiv hmul hreg x) = + twistedZorNorm (hc.peirceVectorProductPair hmul hreg) x := by + let e := hc.offDiagonalDuality hmul hreg + rw [twistedZorEquiv_apply, twistedZorToPeirce_apply, hc.norm_peirceElement hmul, + twistedZorNorm_apply] + change x.1.1 * x.2.1 + e (e.symm x.1.2) x.2.2 = _ + rw [e.apply_symm_apply] + +/-- The twisted Zorn equivalence preserves the identity. -/ +theorem twistedZorEquiv_one (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + hc.twistedZorEquiv hmul hreg 1 = 1 := by + rw [twistedZorEquiv_apply, twistedZorToPeirce_apply] + simp only [TwistedZor.one_fst_fst, TwistedZor.one_fst_snd, TwistedZor.one_snd_fst, + TwistedZor.one_snd_snd, map_zero] + simp [peirceElement, IsAlternative.peirceIdempotent] + +/-- The twisted Zorn equivalence preserves multiplication. -/ +theorem twistedZorEquiv_mul (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) + (x y : TwistedZor (hc.peirceVectorProductPair hmul hreg)) : + hc.twistedZorEquiv hmul hreg (x * y) = + hc.twistedZorEquiv hmul hreg x * hc.twistedZorEquiv hmul hreg y := by + let e := hc.offDiagonalDuality hmul hreg + rw [twistedZorEquiv_apply, twistedZorEquiv_apply, twistedZorEquiv_apply, + twistedZorToPeirce_apply, twistedZorToPeirce_apply, twistedZorToPeirce_apply, + hc.mul_peirceElement hmul] + simp only [TwistedZor.mul_fst_fst, TwistedZor.mul_fst_snd, TwistedZor.mul_snd_fst, + TwistedZor.mul_snd_snd] + have hpolar (f : Module.Dual k (ZornTwistingModule (k := k) c)) + (z : ZornTwistingModule (k := k) c) : + QuadraticMap.polar C.norm (e.symm f) z = f z := by + change e (e.symm f) z = f z + rw [e.apply_symm_apply] + congr 1 + · rw [hpolar] + · rw [hpolar] + · apply e.injective + simp [peirceVectorProductPair, lowerProduct] + +/-- The norm isometry underlying the converse construction of `GPR 22.15`. -/ +noncomputable def twistedZorIsometryEquiv (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + (twistedZor (hc.peirceVectorProductPair hmul hreg)).norm.IsometryEquiv C.norm where + toLinearEquiv := hc.twistedZorEquiv hmul hreg + map_app' := hc.norm_twistedZorEquiv hmul hreg + +/-- **The converse construction of `GPR 22.15`:** a regular multiplicative conic algebra with +an elementary idempotent is a twisted Zorn algebra on its lower-left Peirce component. -/ +theorem isomorphic_twistedZor (hc : C.IsElementaryIdempotent c) + (hmul : C.IsMultiplicative) (hreg : C.norm.IsGPRRegular) : + (twistedZor (hc.peirceVectorProductPair hmul hreg)).Isomorphic C := + ⟨hc.twistedZorIsometryEquiv hmul hreg, hc.twistedZorEquiv_one hmul hreg, + hc.twistedZorEquiv_mul hmul hreg⟩ + +/-- **The rank count in `GPR 22.15`.** At an elementary idempotent in a constant-rank-eight +composition algebra with regular norm, both off-diagonal Peirce components have constant rank +three. -/ +theorem rankAtStalk_twistingModule_eq_three [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hmul : C.IsMultiplicative) + (hreg : C.norm.IsGPRRegular) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + Module.rankAtStalk (R := k) (ZornTwistingModule (k := k) c) = 3 := by + let X (a b : Bool) := IsAlternative.peirceComponent (R := k) c a b + let (a b : Bool) : Module.Finite k (X a b) := + IsAlternative.finite_peirceComponent a b + let (a b : Bool) : Module.Projective k (X a b) := + IsAlternative.projective_peirceComponent hc.mul_self a b + have hdiag (a : Bool) : Module.rankAtStalk (R := k) (X a a) = + Module.rankAtStalk (R := k) k := + Module.rankAtStalk_eq_of_equiv (hc.diagonalEquiv hmul a).symm + have hoff : Module.rankAtStalk (R := k) (X false true) = + Module.rankAtStalk (R := k) (X true false) := by + calc + Module.rankAtStalk (R := k) (X false true) = + Module.rankAtStalk (R := k) (Module.Dual k (X true false)) := + Module.rankAtStalk_eq_of_equiv (hc.offDiagonalDuality hmul hreg) + _ = Module.rankAtStalk (R := k) (X true false) := TauCeti.Module.rankAtStalk_dual _ _ + change Module.rankAtStalk (R := k) (X true false) = 3 + ext p + let : Nontrivial k := ⟨⟨0, 1, fun h ↦ p.2.ne_top <| + (Ideal.eq_top_iff_one p.asIdeal).mpr <| by simpa [h] using p.asIdeal.zero_mem⟩⟩ + have htotal := congrFun + (Module.rankAtStalk_eq_of_equiv + (IsAlternative.peirceDecomposition (R := k) hc.mul_self)) p + rw [hA] at htotal + rw [Module.rankAtStalk_pi] at htotal + rw [finsum_eq_sum_of_fintype, Fintype.sum_prod_type] at htotal + simp only [Fintype.univ_bool, Finset.mem_singleton, Bool.true_eq_false, not_false_eq_true, + Finset.sum_insert, Finset.sum_singleton, add_assoc] at htotal + rw [congrFun (hdiag false) p, congrFun (hdiag true) p, + Module.rankAtStalk_self, congrFun hoff p] at htotal + simp only [Pi.ofNat_apply] at htotal ⊢ + dsimp [X] at htotal ⊢ + omega + +/-- In a reduced composition algebra of constant rank eight, the lower-left Peirce component is +finite projective of constant rank three. The regularity is supplied by `GPR 19.11`. -/ +theorem rankAtStalk_twistingModule_eq_three_of_isComposition + [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + Module.rankAtStalk (R := k) (ZornTwistingModule (k := k) c) = 3 := + hc.rankAtStalk_twistingModule_eq_three hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) hA + +/-- **`GPR 22.15` (Petersson), converse form:** a reduced constant-rank-eight composition algebra +is the twisted Zorn algebra whose vector products are its off-diagonal Peirce multiplication. -/ +theorem isomorphic_twistedZor_of_rankAtStalk_eq_eight + [Module.Finite k A] [Module.Projective k A] + (hc : C.IsElementaryIdempotent c) (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 8) : + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + (twistedZor (hc.peirceVectorProductPair hcomp.isMultiplicative hreg)).Isomorphic C := + hc.isomorphic_twistedZor hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega)) + +end ConicAlgebra.IsElementaryIdempotent diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankTwo.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankTwo.lean new file mode 100644 index 0000000000..9794c23cd3 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/RankTwo.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs + +/-! +# Reduced algebras of rank two are split (`GPR 22.10`) + +**`GPR 22.10`.** *The reduced composition algebras of rank `2` over `k` are precisely the split +quadratic étale `k`-algebras.* + +One direction is `ConicAlgebra.hasElementaryIdempotent_splitEtale`: `k × k` has the elementary +idempotent `(1, 0)`. This file proves the other, and proves it for conic algebras, with no +regularity or multiplicativity hypothesis at all: + +> if a conic algebra of constant rank `2` has an elementary idempotent `c`, then +> `(a, b) ↦ a c + b (conj c)` is an **isomorphism** `k × k → A` of conic algebras. + +The map is injective in any conic algebra (`GPR 22.9`'s proof); what rank `2` adds is surjectivity, +and it adds it through the orthogonal splitting rather than through any counting of generators: the +plane `k c ⊕ k (conj c)` has regular restricted norm, so it is a direct summand whose complement has +rank `0`, hence is trivial. + +## Main results + +* `ConicAlgebra.IsElementaryIdempotent.bijective_elementaryIdempotentEmbedding` : **`GPR 22.10`**, + the embedding is bijective in constant rank `2`. +* `ConicAlgebra.IsElementaryIdempotent.splitEtaleEquiv` : the resulting isomorphism `k × k ≃ₗ A`, + with `map_one`, `map_mul` and `norm` lemmas — an isomorphism of conic algebras. +* `ConicAlgebra.IsComposition.hasSplitEtaleSubalgebra_iff_isGPRIsotropic_of_rankAtStalk_eq_two` : + for a composition algebra of constant rank `2`, being split is equivalent to isotropy of the + norm. This is `GPR 22.18` in rank `2`, and the regularity `GPR 22.9` consumes is supplied by + `GPR 19.11`, since the rank is not `1`. + +## Implementation notes + +Constant rank is `Module.rankAtStalk`, as everywhere else in this development, not `finrank`: over +a ring with idempotents the two differ, and it is the pointwise statement on `Spec k` that the +orthogonal-complement argument needs. + +The isomorphism is delivered as a `LinearEquiv` together with three properties rather than as a +bundled algebra isomorphism: `A` is not assumed associative, so mathlib's `AlgEquiv` does not +apply, and the norm has to be carried explicitly in any case (overview §2 — the norm is data). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.11, 21.19, + 22.9, 22.10, 22.18. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {c : A} + +namespace IsElementaryIdempotent + +variable (hc : C.IsElementaryIdempotent c) +include hc + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- The plane `k c ⊕ k (conj c)` has constant rank `2`: it is `k × k` as a module. -/ +theorem rankAtStalk_planeSubmodule : + Module.rankAtStalk (R := k) + (QuadraticMap.IsHyperbolicPair.planeSubmodule (R := k) c (C.conj c)) = fun _ ↦ 2 := by + rcases subsingleton_or_nontrivial k with hk | hk + · have := hk + exact funext fun p ↦ (IsEmpty.false p).elim + · rw [← Module.rankAtStalk_eq_of_equiv hc.isHyperbolicPair.planeEquiv, + Module.rankAtStalk_prod, Module.rankAtStalk_self] + rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 22.10`.** In a conic algebra of constant rank `2`, an elementary idempotent generates +everything: `(a, b) ↦ a c + b (conj c)` is bijective. + +Injectivity is `GPR 22.9`'s and holds always; surjectivity is the orthogonal splitting, since the +plane is regular and of full rank. No hypothesis on the norm of `C` and none on `2`. -/ +theorem bijective_elementaryIdempotentEmbedding + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + Function.Bijective (C.elementaryIdempotentEmbedding c) := by + refine ⟨hc.injective_elementaryIdempotentEmbedding, fun x ↦ ?_⟩ + have htop := QuadraticForm.eq_top_of_isGPRRegular_of_rankAtStalk_eq + hc.isHyperbolicPair.isGPRRegular_comp_planeSubmodule_subtype hA hc.rankAtStalk_planeSubmodule + have hx : x ∈ QuadraticMap.IsHyperbolicPair.planeSubmodule (R := k) c (C.conj c) := + htop ▸ Submodule.mem_top + obtain ⟨y, hy⟩ := hx + exact ⟨y, hy⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 22.10`, packaged**: a conic algebra of constant rank `2` with an elementary idempotent +*is* the split quadratic étale algebra `k × k`. -/ +noncomputable def splitEtaleEquiv (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + (k × k) ≃ₗ[k] A := + LinearEquiv.ofBijective _ (hc.bijective_elementaryIdempotentEmbedding hA) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem splitEtaleEquiv_apply (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) + (x : k × k) : hc.splitEtaleEquiv hA x = x.1 • c + x.2 • C.conj c := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The isomorphism of `GPR 22.10` is unital. -/ +theorem splitEtaleEquiv_one (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + hc.splitEtaleEquiv hA 1 = 1 := + hc.elementaryIdempotentEmbedding_one + +/-- The isomorphism of `GPR 22.10` is multiplicative. -/ +theorem splitEtaleEquiv_mul (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x y : k × k) : + hc.splitEtaleEquiv hA (x * y) = hc.splitEtaleEquiv hA x * hc.splitEtaleEquiv hA y := + hc.elementaryIdempotentEmbedding_mul x y + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The isomorphism of `GPR 22.10` carries the split quadratic étale norm `(a, b) ↦ ab` to the +norm of `C`. -/ +theorem norm_splitEtaleEquiv (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) (x : k × k) : + C.norm (hc.splitEtaleEquiv hA x) = QuadraticForm.plane k x := + hc.norm_elementaryIdempotentEmbedding x + +end IsElementaryIdempotent + +/-- **`GPR 22.10`, existence form.** A conic algebra of constant rank `2` containing a split +quadratic étale subalgebra *is* one: the subalgebra is everything. -/ +theorem exists_linearEquiv_of_hasSplitEtaleSubalgebra_of_rankAtStalk_eq_two + (hred : C.HasSplitEtaleSubalgebra) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + ∃ e : (k × k) ≃ₗ[k] A, e 1 = 1 ∧ (∀ x y : k × k, e (x * y) = e x * e y) ∧ + ∀ x : k × k, C.norm (e x) = QuadraticForm.plane k x := by + obtain ⟨c, hc⟩ := hasSplitEtaleSubalgebra_iff_hasElementaryIdempotent.mp hred + exact ⟨hc.splitEtaleEquiv hA, hc.splitEtaleEquiv_one hA, hc.splitEtaleEquiv_mul hA, + hc.norm_splitEtaleEquiv hA⟩ + +/-! ### Rank two composition algebras: split ↔ isotropic norm + +For a composition algebra the regularity that `GPR 22.9` consumes is not a hypothesis: `GPR 19.11` +gives it as soon as the constant rank is not `1`. So in rank `2` the chain +"split ↔ reduced ↔ isotropic norm" closes with no side conditions beyond the rank. -/ + +variable (C) + +/-- **`GPR 22.18` in rank two.** For a composition algebra of constant rank `2`, containing a split +quadratic étale subalgebra — equivalently, by `GPR 22.10`, *being* one — is equivalent to isotropy +of the norm in `GPR`'s sense. + +The regularity `GPR 22.9` needs comes from `GPR 19.11` +(`IsComposition.isGPRRegular_of_rankAtStalk_ne_one`), since `2 ≠ 1`. -/ +theorem IsComposition.hasSplitEtaleSubalgebra_iff_isGPRIsotropic_of_rankAtStalk_eq_two + (h : C.IsComposition.{u, v, u}) (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 2) : + C.HasSplitEtaleSubalgebra ↔ C.norm.IsGPRIsotropic := + hasSplitEtaleSubalgebra_iff_isGPRIsotropic + (h.isGPRRegular_of_rankAtStalk_ne_one hA (by norm_num)) h.isMultiplicative + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Reducedness.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Reducedness.lean new file mode 100644 index 0000000000..3d9be65b32 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Reducedness.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Splitness + +/-! +# Reduced composition algebras (`GPR 22.6–22.7`) + +`GPR 22.6` defines a composition algebra to be **reduced** when it contains an absolutely +primitive idempotent. `GPR 22.7` supplies the characterization used throughout the structure +theory: in rank greater than one, reducedness is equivalent to the existence of an elementary +idempotent, while every rank-one composition algebra is reduced. + +This file uses that equivalent characterization together with the rank decomposition of +`GPR Exc. 9.31`. Thus a composition algebra is reduced when its rank `2`, `4`, and `8` components +have elementary idempotents; the rank-one component needs no condition. + +## Main definitions + +* `ConicAlgebra.IsReduced` : reducedness, expressed on the four rank components. + +## Main results + +* `ConicAlgebra.IsReduced.isComposition` : reducedness includes the composition property. +* `ConicAlgebra.IsSplit.isReduced` : **`GPR 22.16`, split implies reduced**, over every + commutative ring. + +## Implementation notes + +⚠ **Equivalent characterization rather than absolute primitivity.** Absolute primitivity in +`GPR 22.1` quantifies over all field extensions and decompositions into orthogonal idempotents. +Nothing downstream uses that data: every application passes immediately through `GPR 22.7` to +elementary idempotents. Accordingly `IsReduced` records the rankwise elementary-idempotent +condition equivalent to `GPR 22.6`, rather than introducing an unused absolute-primitivity API. +The distinction at rank one is preserved explicitly: rank one is reduced but generally has no +elementary idempotent. + +Zero rank factors cause no exception. Their base rings are zero rings, where `0` is elementary +because `0 = 1`; retaining all three factors therefore matches the convention in `GPR 21.19`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 9.31, + 21.19, 22.1, 22.6, 22.7, 22.16. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + +/-- **Reducedness (`GPR 22.6–22.7`) through the rank decomposition.** A conic algebra is reduced +when it is a composition algebra and each of its rank `2`, `4`, and `8` components has an +elementary idempotent. The rank-one component is automatically reduced and deliberately carries +no elementary-idempotent condition. -/ +def IsReduced (C : ConicAlgebra k A) : Prop := + C.IsComposition.{u, v, u} ∧ + (C.splitRankComponent 2).HasElementaryIdempotent ∧ + (C.splitRankComponent 4).HasElementaryIdempotent ∧ + (C.splitRankComponent 8).HasElementaryIdempotent + +namespace IsReduced + +variable {C : ConicAlgebra k A} + +/-- A reduced conic algebra is a composition algebra, by definition. -/ +theorem isComposition (h : C.IsReduced) : C.IsComposition.{u, v, u} := + h.1 + +/-- The rank-two component of a reduced composition algebra has an elementary idempotent. -/ +theorem hasElementaryIdempotent_splitRankComponent_two (h : C.IsReduced) : + (C.splitRankComponent 2).HasElementaryIdempotent := + h.2.1 + +/-- The rank-four component of a reduced composition algebra has an elementary idempotent. -/ +theorem hasElementaryIdempotent_splitRankComponent_four (h : C.IsReduced) : + (C.splitRankComponent 4).HasElementaryIdempotent := + h.2.2.1 + +/-- The rank-eight component of a reduced composition algebra has an elementary idempotent. -/ +theorem hasElementaryIdempotent_splitRankComponent_eight (h : C.IsReduced) : + (C.splitRankComponent 8).HasElementaryIdempotent := + h.2.2.2 + +end IsReduced + +/-- **`GPR 22.16`, split ⇒ reduced.** Every split composition algebra over an arbitrary +commutative ring is reduced. + +On each rank greater than one, the defining isomorphism with the standard split model transports +its visible elementary idempotent back to the corresponding rank component. Rank one is reduced +without an elementary-idempotent condition. -/ +theorem IsSplit.isReduced {C : ConicAlgebra k A} (h : C.IsSplit) : C.IsReduced := by + rcases h with ⟨hcomp, -, htwo, hfour, height⟩ + exact ⟨hcomp, + htwo.hasElementaryIdempotent_of_two_or_four_or_eight (Or.inl rfl), + hfour.hasElementaryIdempotent_of_two_or_four_or_eight (Or.inr (Or.inl rfl)), + height.hasElementaryIdempotent_of_two_or_four_or_eight (Or.inr (Or.inr rfl))⟩ + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Split.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Split.lean new file mode 100644 index 0000000000..713fd68798 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Split.lean @@ -0,0 +1,244 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Zorn +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneSplitting +public import Mathlib.LinearAlgebra.Matrix.Determinant.Basic +public import Mathlib.LinearAlgebra.Dimension.Constructions + +/-! +# The split composition algebras (`GPR 21.19`) + +`GPR 21.19` lists one composition algebra in each of the ranks `1, 2, 4, 8` and calls it the +**split** algebra of that rank: + +| rank | algebra | norm | trace | conjugation | +|---|---|---|---|---| +| `1` | `k` | `x ↦ x²` | `2x` | `x` | +| `2` | `k × k` | `(a, b) ↦ ab` | `a + b` | `(a, b) ↦ (b, a)` | +| `4` | `Mat₂(k)` | `det` | `trace` | `adjugate` | +| `8` | `Zor(k)` | `ρ₁ρ₂ + u₁ᵀu₂` | `ρ₁ + ρ₂` | diagonal swap | + +Ranks `1` and `8` are already available — `ConicAlgebra.baseRing` and `ConicAlgebra.zor` — and this +file supplies the two in between: the **split quadratic étale algebra** `k × k` and the **split +quaternion algebra** `Mat₂(k)`. As with `Zor(k)`, and in contrast with the Cayley–Dickson tower of +`Composition/Octonion.lean`, each is a composition algebra over an *arbitrary* commutative ring, +with no hypothesis on `2`: their norms are hyperbolic, and hyperbolic forms are regular in every +characteristic. + +## Main definitions + +* `ConicAlgebra.splitEtale k` : `k × k` with norm the hyperbolic plane `(a, b) ↦ ab` + (`GPR 21.19(b)`). The norm is mathlib-free but not new — it is `QuadraticForm.plane k`. +* `ConicAlgebra.splitQuaternionNorm k`, `ConicAlgebra.splitQuaternion k` : `Mat₂(k)` with norm the + determinant (`GPR 21.19(c)`). + +## Main results + +* `ConicAlgebra.isComposition_splitEtale`, `ConicAlgebra.isComposition_splitQuaternion` : both are + composition algebras over every commutative ring. +* `ConicAlgebra.finrank_splitEtale`, `ConicAlgebra.finrank_splitQuaternion` : of ranks `2` and `4`. +* `ConicAlgebra.conj_splitEtale_apply` : the conjugation of `k × k` is the exchange involution. +* `ConicAlgebra.conj_splitQuaternion_apply` : the conjugation of `Mat₂(k)` is the adjugate, so the + conic identity `x (conj x) = n(x) 1` is the classical `A · adj A = det A · 1`. + +## Implementation notes + +Neither algebra needs a type synonym: unlike the Cayley–Dickson double and `Zor(k)`, the +multiplication is the one mathlib already puts on `k × k` and on `Matrix (Fin 2) (Fin 2) k`, so the +conic structure is extra data on an existing algebra and nothing has to be redefined. Both are +associative, so the four typeclasses a conic algebra needs come from their `Algebra k` instances. + +The degree-two identity is, in the two cases, the componentwise identity `a² = (a + b)a - ab` and +the **Cayley–Hamilton theorem for `2 × 2` matrices**; the latter is proved here entrywise rather +than by invoking mathlib's general `Matrix.aeval_self_charpoly`, since at size `2` the entrywise +computation is four applications of `ring` and needs no characteristic-polynomial API. + +Non-singularity is, in both cases, the observation that the norm is a sum of hyperbolic planes: +`(a, b) ↦ ab` is the pairing of `k` against `k`, and `det = a₀₀a₁₁ - a₀₁a₁₀` is the pairing of +`(a₀₀, a₀₁)` against `(a₁₁, -a₁₀)`. `QuadraticForm.isGPRNonsingular_of_basis_pairing` and its +equivalence-composed form read these off; no determinant criterion and no hypothesis on `2` enters. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 21.18, 21.19. +-/ + +@[expose] public section + +universe u w + +namespace ConicAlgebra + +variable (k : Type u) [CommRing k] + +/-! ### Rank two: the split quadratic étale algebra `k × k` -/ + +/-! The norm of `k × k` is mathlib-free but not new: it is the hyperbolic plane +`QuadraticForm.plane k` of `QuadraticForm/HyperbolicPair.lean`, `(a, b) ↦ ab`. Nothing is +redefined here. -/ + +variable {k} + +variable (k) + +/-- **`GPR 21.19(b)`: `k × k` is a conic algebra** with norm `(a, b) ↦ ab` and trace `a + b`. -/ +def splitEtale : ConicAlgebra k (k × k) where + norm := QuadraticForm.plane k + norm_one := one_mul 1 + mul_self x := by + refine Prod.ext ?_ ?_ <;> simp [Prod.smul_fst, Prod.smul_snd] <;> ring + +variable {k} + +@[simp] theorem splitEtale_norm : (splitEtale k).norm = QuadraticForm.plane k := rfl + +/-- The trace of `k × k` is the sum of the two coordinates. -/ +@[simp] theorem trace_splitEtale_apply (x : k × k) : (splitEtale k).trace x = x.1 + x.2 := by + rw [ConicAlgebra.trace_apply, splitEtale_norm, QuadraticForm.polar_plane_one] + +/-- **The conjugation of `k × k` is the exchange involution** `(a, b) ↦ (b, a)`, as `GPR 21.18` +requires of the split quadratic étale algebra. -/ +@[simp] theorem conj_splitEtale_apply (x : k × k) : (splitEtale k).conj x = (x.2, x.1) := by + refine Prod.ext ?_ ?_ <;> simp [ConicAlgebra.conj_apply] + +/-- The norm of `k × k` permits composition: it is multiplicative because multiplication is +componentwise. -/ +theorem isMultiplicative_splitEtale : (splitEtale k).IsMultiplicative := by + intro x y + simp only [splitEtale_norm, QuadraticForm.plane_apply, Prod.fst_mul, Prod.snd_mul] + ring + +variable (k) + +/-- **`GPR 21.19(b)`: `k × k` is a composition algebra over every commutative ring**, the split +one of rank two. -/ +theorem isComposition_splitEtale : (splitEtale k).IsComposition.{u, u, w} where + isGPRNonsingular := QuadraticForm.isGPRNonsingular_plane.{u, w} k + isMultiplicative := isMultiplicative_splitEtale + +/-- `k × k` has rank `2`. (Not a `simp` lemma: mathlib's `Module.finrank_prod` already reduces the +left-hand side, to `1 + 1`.) -/ +theorem finrank_splitEtale [Nontrivial k] : Module.finrank k (k × k) = 2 := by + simp + +/-! ### Rank four: the split quaternion algebra `Mat₂(k)` -/ + +/-- The bilinear form `(A, B) ↦ a₀₀b₁₁ - a₀₁b₁₀` on `Mat₂(k)`, whose associated quadratic form is +the determinant. -/ +def splitQuaternionBilin : LinearMap.BilinForm k (Matrix (Fin 2) (Fin 2) k) := + LinearMap.mk₂ k (fun A B ↦ A 0 0 * B 1 1 - A 0 1 * B 1 0) + (fun _ _ _ ↦ by simp; ring) (fun _ _ _ ↦ by simp; ring) + (fun _ _ _ ↦ by simp; ring) (fun _ _ _ ↦ by simp; ring) + +/-- The **norm of the split quaternion algebra** `Mat₂(k)` (`GPR 21.19(c)`): the determinant. -/ +def splitQuaternionNorm : QuadraticForm k (Matrix (Fin 2) (Fin 2) k) := + (splitQuaternionBilin k).toQuadraticMap + +variable {k} + +theorem splitQuaternionNorm_apply' (A : Matrix (Fin 2) (Fin 2) k) : + splitQuaternionNorm k A = A 0 0 * A 1 1 - A 0 1 * A 1 0 := rfl + +/-- **The norm of `Mat₂(k)` is the determinant.** -/ +@[simp] theorem splitQuaternionNorm_apply (A : Matrix (Fin 2) (Fin 2) k) : + splitQuaternionNorm k A = A.det := by + rw [splitQuaternionNorm_apply', Matrix.det_fin_two] + +theorem polar_splitQuaternionNorm (A B : Matrix (Fin 2) (Fin 2) k) : + QuadraticMap.polar (splitQuaternionNorm k) A B = + A 0 0 * B 1 1 + B 0 0 * A 1 1 - A 0 1 * B 1 0 - B 0 1 * A 1 0 := by + simp only [QuadraticMap.polar, splitQuaternionNorm_apply', Matrix.add_apply] + ring + +@[simp] theorem polar_splitQuaternionNorm_one (A : Matrix (Fin 2) (Fin 2) k) : + QuadraticMap.polar (splitQuaternionNorm k) 1 A = A.trace := by + rw [polar_splitQuaternionNorm, Matrix.trace_fin_two] + simp + ring + +/-- **Cayley–Hamilton at size two**: `A² = tr(A)·A - det(A)·1`. Proved entrywise; this is the +degree-two identity that makes `Mat₂(k)` a conic algebra. -/ +theorem mul_self_eq_trace_smul_sub_det_smul (A : Matrix (Fin 2) (Fin 2) k) : + A * A = A.trace • A - A.det • (1 : Matrix (Fin 2) (Fin 2) k) := by + ext i j + fin_cases i <;> fin_cases j <;> + simp [Matrix.mul_apply, Fin.sum_univ_two, Matrix.trace_fin_two, Matrix.det_fin_two] <;> ring + +variable (k) + +/-- **`GPR 21.19(c)`: `Mat₂(k)` is a conic algebra** with norm the determinant and trace the matrix +trace. The degree-two identity is Cayley–Hamilton at size two. -/ +def splitQuaternion : ConicAlgebra k (Matrix (Fin 2) (Fin 2) k) where + norm := splitQuaternionNorm k + norm_one := by simp + mul_self A := by + rw [polar_splitQuaternionNorm_one, splitQuaternionNorm_apply] + exact mul_self_eq_trace_smul_sub_det_smul A + +variable {k} + +@[simp] theorem splitQuaternion_norm : (splitQuaternion k).norm = splitQuaternionNorm k := rfl + +/-- The trace of the conic algebra `Mat₂(k)` is the trace of the matrix. -/ +@[simp] theorem trace_splitQuaternion_apply (A : Matrix (Fin 2) (Fin 2) k) : + (splitQuaternion k).trace A = A.trace := by + rw [ConicAlgebra.trace_apply, splitQuaternion_norm, polar_splitQuaternionNorm_one] + +/-- **The conjugation of `Mat₂(k)` is the adjugate.** Consequently the conic identity +`x (conj x) = n(x) 1` specializes to `A · adj A = det A · 1`. -/ +@[simp] theorem conj_splitQuaternion_apply (A : Matrix (Fin 2) (Fin 2) k) : + (splitQuaternion k).conj A = A.adjugate := by + rw [ConicAlgebra.conj_apply, trace_splitQuaternion_apply] + ext i j + fin_cases i <;> fin_cases j <;> simp [Matrix.adjugate_fin_two, Matrix.trace_fin_two] + +/-- The norm of `Mat₂(k)` permits composition: this is multiplicativity of the determinant. -/ +theorem isMultiplicative_splitQuaternion : (splitQuaternion k).IsMultiplicative := by + intro A B + simp [Matrix.det_mul] + +variable (k) + +/-- `Mat₂(k)` presented as `k² ⊕ k²`, by reading off the pair `(a₀₀, a₀₁)` and the pair +`(a₁₁, -a₁₀)`. Under this equivalence the determinant becomes the standard pairing of the two +factors, which is what exhibits it as two hyperbolic planes. -/ +def splitQuaternionEquiv : + Matrix (Fin 2) (Fin 2) k ≃ₗ[k] ((Fin 2 → k) × (Fin 2 → k)) where + toFun A := (![A 0 0, A 0 1], ![A 1 1, -A 1 0]) + map_add' A B := by + refine Prod.ext (funext fun i ↦ ?_) (funext fun i ↦ ?_) <;> fin_cases i <;> simp [add_comm] + map_smul' c A := by + refine Prod.ext (funext fun i ↦ ?_) (funext fun i ↦ ?_) <;> fin_cases i <;> simp + invFun p := Matrix.of ![![p.1 0, p.1 1], ![-p.2 1, p.2 0]] + left_inv A := by ext i j; fin_cases i <;> fin_cases j <;> simp + right_inv p := by + refine Prod.ext (funext fun i ↦ ?_) (funext fun i ↦ ?_) <;> fin_cases i <;> simp + +/-- **The norm of `Mat₂(k)` is non-singular**: the determinant is two hyperbolic planes, pairing +`(a₀₀, a₀₁)` against `(a₁₁, -a₁₀)`. No hypothesis on `2`, and no determinant criterion — the +determinant here is the form, not the tool. -/ +theorem isGPRNonsingular_splitQuaternionNorm : + QuadraticForm.IsGPRNonsingular.{u, u, w} (splitQuaternionNorm k) := + QuadraticForm.isGPRNonsingular_of_linearEquiv_basis_pairing (Pi.basisFun k (Fin 2)) + (splitQuaternionEquiv k) fun A ↦ by + simp [splitQuaternionEquiv, Fin.sum_univ_two, Matrix.det_fin_two] + ring + +/-- **`GPR 21.19(c)`: `Mat₂(k)` is a composition algebra over every commutative ring**, the split +one of rank four. -/ +theorem isComposition_splitQuaternion : (splitQuaternion k).IsComposition.{u, u, w} where + isGPRNonsingular := isGPRNonsingular_splitQuaternionNorm k + isMultiplicative := isMultiplicative_splitQuaternion + +/-- `Mat₂(k)` has rank `4`. -/ +@[simp] theorem finrank_splitQuaternion [Nontrivial k] : + Module.finrank k (Matrix (Fin 2) (Fin 2) k) = 4 := by + rw [Module.finrank_matrix] + simp + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Splitness.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Splitness.lean new file mode 100644 index 0000000000..16fd322cb3 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Splitness.lean @@ -0,0 +1,273 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormClassification +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition + +/-! +# Split composition algebras (`GPR 21.19`) + +`GPR 21.19` first defines a composition algebra of constant rank `1`, `2`, `4`, or `8` to be +**split** when it is isomorphic to the corresponding standard model: `k`, `k × k`, `Mat₂(k)`, +or `Zor(k)`. For a composition algebra whose rank varies across `Spec k`, it then applies this +condition to the four factors of the rank decomposition (`GPR Exc. 9.31`). + +This file formalizes both levels. Since mathlib's `AlgEquiv` requires associative multiplication, +an isomorphism of conic algebras is expressed by a norm isometry which preserves `1` and +multiplication. This is the same representation used by `Composition/NormClassification.lean`. + +## Main definitions + +* `ConicAlgebra.Isomorphic` : existence of a unital multiplicative norm isometry. +* `ConicAlgebra.IsSplitOfRank` : the four constant-rank clauses of `GPR 21.19`. +* `ConicAlgebra.SplitRankFactor`, `ConicAlgebra.splitRankComponent` : the factor ring and + base-changed conic algebra cut out by a rank idempotent. +* `ConicAlgebra.IsSplit` : the composition property together with splitness on all four rank + components. + +## Main results + +* `ConicAlgebra.Isomorphic.refl`, `.symm`, `.trans` : conic-algebra isomorphism is an equivalence + relation. +* `ConicAlgebra.Isomorphic.of_subsingleton` : over the zero ring, any two conic algebras are + isomorphic. +* `ConicAlgebra.Isomorphic.isComposition` : composition transports across an isomorphism. +* `ConicAlgebra.isSplitOfRank_baseRing`, `.isSplitOfRank_splitEtale`, + `.isSplitOfRank_splitQuaternion`, `.isSplitOfRank_zor` : the four standard models are split. +* `ConicAlgebra.IsSplitOfRank.hasElementaryIdempotent_of_two_or_four_or_eight` : the + constant-rank form of the easy direction of `GPR 22.16`. + +## Implementation notes + +`IsSplitOfRank C r` does not separately store the assertion that `C` has rank `r`: an isomorphism +to the standard model already forces that equality. The general predicate uses the quotients + +`k ⧸ (1 - rankIdempotent k A r)` + +for `r = 1, 2, 4, 8`, exactly as in the rank decomposition. Zero factors are retained, as in +`GPR 21.19`; this also handles the zero base ring without a separate definition. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 9.31, + 21.19, 22.16. +-/ + +@[expose] public section + +universe u v w t + +open scoped TensorProduct + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} {B : Type w} [CommRing k] + [NonAssocRing A] [Module k A] [SMulCommClass k A A] [IsScalarTower k A A] + [NonAssocRing B] [Module k B] [SMulCommClass k B B] [IsScalarTower k B B] + +/-- Two conic algebras are **isomorphic** when there is a norm isometry preserving `1` and +multiplication. + +⚠ Mathlib's `AlgEquiv` is not used because the algebras need not be associative. -/ +def Isomorphic (C : ConicAlgebra k A) (D : ConicAlgebra k B) : Prop := + ∃ e : C.norm.IsometryEquiv D.norm, + e (1 : A) = 1 ∧ ∀ x y, e (x * y) = e x * e y + +namespace Isomorphic + +variable {C : ConicAlgebra k A} {D : ConicAlgebra k B} + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- Over a subsingleton base ring, any two conic algebras are isomorphic. Their underlying +modules, the norm values, and all algebra elements are subsingletons. -/ +theorem of_subsingleton [Subsingleton k] : C.Isomorphic D := by + let : Subsingleton A := Module.subsingleton k A + let : Subsingleton B := Module.subsingleton k B + exact ⟨⟨LinearEquiv.ofSubsingleton A B, fun _ ↦ Subsingleton.elim _ _⟩, + Subsingleton.elim _ _, fun _ _ ↦ Subsingleton.elim _ _⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- A conic algebra is isomorphic to itself. -/ +@[refl] theorem refl (C : ConicAlgebra k A) : C.Isomorphic C := + ⟨QuadraticMap.IsometryEquiv.refl C.norm, rfl, fun _ _ ↦ rfl⟩ + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- The inverse of an isomorphism of conic algebras. -/ +@[symm] theorem symm (h : C.Isomorphic D) : D.Isomorphic C := by + obtain ⟨e, he1, hmul⟩ := h + refine ⟨e.symm, ?_, fun x y ↦ ?_⟩ + · apply e.injective + simp [he1] + · apply e.injective + change e (e.symm (x * y)) = e (e.symm x * e.symm y) + rw [e.apply_symm_apply, hmul, e.apply_symm_apply, e.apply_symm_apply] + +variable {E : Type t} [NonAssocRing E] [Module k E] [SMulCommClass k E E] + [IsScalarTower k E E] {G : ConicAlgebra k E} + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] [SMulCommClass k E E] [IsScalarTower k E E] in +/-- The composite of two isomorphisms of conic algebras. -/ +@[trans] theorem trans (hCD : C.Isomorphic D) (hDG : D.Isomorphic G) : C.Isomorphic G := by + obtain ⟨e, he1, hemul⟩ := hCD + obtain ⟨f, hf1, hfmul⟩ := hDG + refine ⟨e.trans f, ?_, fun x y ↦ ?_⟩ + · change f (e (1 : A)) = 1 + rw [he1, hf1] + · change f (e (x * y)) = f (e x) * f (e y) + rw [hemul, hfmul] + +variable [Module.Finite k A] [Module.Projective k A] + [Module.Finite k B] [Module.Projective k B] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- Composition transports backwards across an isomorphism of conic algebras. -/ +theorem isComposition (h : C.Isomorphic D) (hD : D.IsComposition.{u, w, t}) : + C.IsComposition.{u, v, t} := by + obtain ⟨e, -, hmul⟩ := h + refine ⟨?_, fun x y ↦ ?_⟩ + · have hnorm : C.norm = D.norm.comp e.toLinearEquiv.toLinearMap := + QuadraticMap.ext fun x ↦ (e.map_app x).symm + rw [hnorm] + exact hD.isGPRNonsingular.comp_linearEquiv e.toLinearEquiv + · calc + C.norm (x * y) = D.norm (e (x * y)) := (e.map_app (x * y)).symm + _ = D.norm (e x * e y) := congrArg D.norm (hmul x y) + _ = D.norm (e x) * D.norm (e y) := hD.norm_mul (e x) (e y) + _ = C.norm x * C.norm y := by rw [e.map_app, e.map_app] + +end Isomorphic + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- A unital norm isometry carries elementary idempotents to elementary idempotents. -/ +theorem IsElementaryIdempotent.map_isometryEquiv {C : ConicAlgebra k A} + {D : ConicAlgebra k B} {c : A} (hc : C.IsElementaryIdempotent c) + (e : C.norm.IsometryEquiv D.norm) (he1 : e (1 : A) = 1) : + D.IsElementaryIdempotent (e c) where + norm_eq_zero := by rw [e.map_app, hc.norm_eq_zero] + trace_eq_one := by rw [trace_map_of_isometryEquiv_map_one C D e he1, hc.trace_eq_one] + +omit [SMulCommClass k A A] [IsScalarTower k A A] [SMulCommClass k B B] + [IsScalarTower k B B] in +/-- Having an elementary idempotent is invariant under conic-algebra isomorphism. -/ +theorem Isomorphic.hasElementaryIdempotent_iff {C : ConicAlgebra k A} + {D : ConicAlgebra k B} (h : C.Isomorphic D) : + C.HasElementaryIdempotent ↔ D.HasElementaryIdempotent := by + obtain ⟨e, he1, -⟩ := h + have he1' : e.symm (1 : B) = 1 := by + apply e.injective + simp [he1] + exact ⟨fun ⟨c, hc⟩ ↦ ⟨e c, hc.map_isometryEquiv e he1⟩, + fun ⟨d, hd⟩ ↦ ⟨e.symm d, hd.map_isometryEquiv e.symm he1'⟩⟩ + +/-! ### Constant-rank splitness -/ + +variable (C : ConicAlgebra k A) + +/-- **`GPR 21.19(a)–(d)`.** A conic algebra is split of rank `r` if it is isomorphic to the +standard model of rank `r`. The predicate is false for ranks other than `1`, `2`, `4`, and `8`. + +This definition is intended for composition algebras; `Isomorphic.isComposition` shows that being +isomorphic to one of the standard models supplies the composition laws. -/ +def IsSplitOfRank : ℕ → Prop + | 1 => C.Isomorphic (baseRing k) + | 2 => C.Isomorphic (splitEtale k) + | 4 => C.Isomorphic (splitQuaternion k) + | 8 => C.Isomorphic (zor k) + | _ => False + +variable {C} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem isSplitOfRank_one_iff : C.IsSplitOfRank 1 ↔ C.Isomorphic (baseRing k) := + Iff.rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem isSplitOfRank_two_iff : C.IsSplitOfRank 2 ↔ C.Isomorphic (splitEtale k) := + Iff.rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem isSplitOfRank_four_iff : + C.IsSplitOfRank 4 ↔ C.Isomorphic (splitQuaternion k) := + Iff.rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem isSplitOfRank_eight_iff : C.IsSplitOfRank 8 ↔ C.Isomorphic (zor k) := + Iff.rfl + +section StandardModels + +variable (k : Type u) [CommRing k] + +/-- The standard rank-one composition algebra is split of rank one. -/ +theorem isSplitOfRank_baseRing : (baseRing k).IsSplitOfRank 1 := + Isomorphic.refl _ + +/-- The split quadratic étale algebra is split of rank two. -/ +theorem isSplitOfRank_splitEtale : (splitEtale k).IsSplitOfRank 2 := + Isomorphic.refl _ + +/-- The split quaternion algebra is split of rank four. -/ +theorem isSplitOfRank_splitQuaternion : (splitQuaternion k).IsSplitOfRank 4 := + Isomorphic.refl _ + +/-- The Zorn vector matrix algebra is split of rank eight. -/ +theorem isSplitOfRank_zor : (zor k).IsSplitOfRank 8 := + Isomorphic.refl _ + +end StandardModels + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **`GPR 22.16`, constant-rank easy direction.** A split algebra of rank `2`, `4`, or `8` has +an elementary idempotent. The three standard models have visible elementary idempotents, and the +property is transported back across the defining isomorphism. -/ +theorem IsSplitOfRank.hasElementaryIdempotent_of_two_or_four_or_eight {r : ℕ} + (h : C.IsSplitOfRank r) (hr : r = 2 ∨ r = 4 ∨ r = 8) : + C.HasElementaryIdempotent := by + rcases hr with rfl | rfl | rfl + · exact h.hasElementaryIdempotent_iff.mpr (hasElementaryIdempotent_splitEtale k) + · exact h.hasElementaryIdempotent_iff.mpr (hasElementaryIdempotent_splitQuaternion k) + · exact h.hasElementaryIdempotent_iff.mpr (hasElementaryIdempotent_zor k) + +/-! ### Splitness through the rank decomposition -/ + +variable [Module.Finite k A] [Module.Projective k A] + +/-- The factor of the base ring on which `A` has constant rank `r` (`GPR Exc. 9.31`). -/ +abbrev SplitRankFactor (k : Type u) (A : Type v) [CommRing k] [AddCommGroup A] [Module k A] + [Module.Finite k A] [Module.Projective k A] (r : ℕ) := + k ⧸ Ideal.span {1 - Module.rankIdempotent k A r} + +/-- The conic algebra on the rank-`r` factor of the rank decomposition. -/ +noncomputable def splitRankComponent (C : ConicAlgebra k A) (r : ℕ) : + ConicAlgebra (SplitRankFactor k A r) ((SplitRankFactor k A r) ⊗[k] A) := + C.baseChangeOfProjective (SplitRankFactor k A r) + +/-- **`GPR 21.19`, general splitness.** A conic algebra is split when each of its rank `1`, `2`, +`4`, and `8` components is isomorphic to the corresponding standard split composition algebra. + +The composition hypothesis is included because `GPR 21.19` defines splitness only for +composition algebras; it also ensures through `GPR 19.18` that these four idempotent factors +exhaust the base. -/ +def IsSplit (C : ConicAlgebra k A) : Prop := + C.IsComposition.{u, v, u} ∧ (C.splitRankComponent 1).IsSplitOfRank 1 ∧ + (C.splitRankComponent 2).IsSplitOfRank 2 ∧ + (C.splitRankComponent 4).IsSplitOfRank 4 ∧ + (C.splitRankComponent 8).IsSplitOfRank 8 + +/-- A split conic algebra is a composition algebra, by definition. -/ +theorem IsSplit.isComposition {C : ConicAlgebra k A} (h : C.IsSplit) : + C.IsComposition.{u, v, u} := + h.1 + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedMatrix.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedMatrix.lean new file mode 100644 index 0000000000..8dac5fb346 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedMatrix.lean @@ -0,0 +1,609 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Splitness +public import LeanPool.CompositionAlgebrasOverRings.Module.Invertible + +/-! +# `L`-twisted 2-by-2 matrices (`GPR 22.12`, `22.13`) + +For `L` a `k`-module, the **`L`-twisted 2-by-2 matrices** are the formal matrices + + `[ρ₁ u*]` + `[v ρ₂]`, `ρᵢ ∈ k`, `u* ∈ L*`, `v ∈ L`, + +multiplied as matrices, using the canonical pairing `L* × L → k` wherever a product of an entry +of `L*` with an entry of `L` occurs (`GPR 22.12`): + + `[ρ₁ u*] [σ₁ w*] [ ρ₁σ₁ + ⟨u*, z⟩ ρ₁w* + σ₂u* ]` + `[v ρ₂] [z σ₂] = [ σ₁v + ρ₂z ρ₂σ₂ + ⟨w*, v⟩ ]`, + +with norm `ρ₁ρ₂ - ⟨u*, v⟩`, trace `ρ₁ + ρ₂` and conjugation exchanging the diagonal +and negating the off-diagonal entries — `GPR (22.12.1)`, `(22.12.2)`, `(22.12.3)`. When `L` is a +line bundle this is `GPR`'s presentation of `Endₖ(k ⊕ L)`, the quaternion algebra of `L`-twisted +matrices, and by `GPR 22.13` **every** reduced quaternion algebra is one of these. + +## What is proved here + +Both directions of `GPR 22.13`: + +* the conic structure, its norm, trace and conjugation — for **any** `k`-module `L`; +* **non-singularity of the norm** for `L` finitely generated projective — and not by a + computation: the norm is the hyperbolic form of `k ⊕ L`, pairing `(ρ₁, u*)` against + `(ρ₂, -v)`, so `QuadraticForm.isGPRNonsingular_dualProd` applies with no basis, no rank + hypothesis and no hypothesis on `2`; +* **multiplicativity of the norm** exactly under the identity `Module.IsRankOnePairing`, + `⟨φ, x⟩⟨ψ, y⟩ = ⟨φ, y⟩⟨ψ, x⟩` — what the algebra needs `L` to have rank one for, + and the only place the rank enters; +* hence that it is a **composition algebra**, and a **reduced** one: the matrix unit `e₁₁` is an + elementary idempotent (`GPR (22.12.4)`), so `GPR 22.9` applies to it. +* conversely, a reduced composition algebra of constant rank four is isomorphic to the twisted + matrices for its lower-left Peirce component. The Peirce rank count makes that component a line + bundle, and the regular polar pairing identifies the upper-right component with its dual. + +The general-purpose equivalence `Module.invertible_iff_isLocallyFreeRankOne` proves that a line +bundle satisfies `Module.IsRankOnePairing`. Thus the construction gives a composition algebra for +every invertible `L`, with no freeness assumption. + +## Main definitions + +* `Module.IsRankOnePairing k L` : the identity `⟨φ, x⟩⟨ψ, y⟩ = ⟨φ, y⟩⟨ψ, x⟩`. +* `ConicAlgebra.TwistedMat k L` : the module of `L`-twisted matrices, with its multiplication. +* `ConicAlgebra.twistedMatNorm k L`, `ConicAlgebra.twistedMat k L` : the norm and the conic + structure. + +## Main results + +* `ConicAlgebra.isGPRNonsingular_twistedMatNorm` : the norm is hyperbolic, hence non-singular. +* `ConicAlgebra.isMultiplicative_twistedMat` : the norm permits composition, given the rank-one + pairing identity. +* `ConicAlgebra.isComposition_twistedMat` : it is a composition algebra. +* `ConicAlgebra.isComposition_twistedMat_of_invertible` : the line-bundle form of `GPR 22.12`. +* `ConicAlgebra.hasElementaryIdempotent_twistedMat` : it is reduced — `GPR 22.13`'s easy half. +* `ConicAlgebra.IsElementaryIdempotent.isomorphic_twistedMat` : every reduced constant-rank-four + composition algebra is a twisted-matrix algebra, the converse half of `GPR 22.13`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 22.9, 22.12, 22.13. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable (k : Type u) [CommRing k] (L : Type v) [AddCommGroup L] [Module k L] + +/-- The `k`-module of **`L`-twisted 2-by-2 matrices** (`GPR 22.12`), as a type synonym for +`(k × L*) × (k × L)`: the element `x` is the matrix + + `[x.1.1 x.1.2]` + `[x.2.2 x.2.1]` + +whose top row is `x.1 = (ρ₁, u*)` and whose bottom row is `(x.2.2, x.2.1) = (v, ρ₂)`. The +synonym +is needed because the multiplication is not the componentwise one; the grouping puts the two +diagonal entries first in their pairs, so that the norm is visibly the pairing of `x.1` against +`x.2`. -/ +def TwistedMat : Type max u v := (k × Module.Dual k L) × (k × L) + +namespace TwistedMat + +instance : AddCommGroup (TwistedMat k L) := + inferInstanceAs (AddCommGroup ((k × Module.Dual k L) × (k × L))) + +instance : Module k (TwistedMat k L) := + inferInstanceAs (Module k ((k × Module.Dual k L) × (k × L))) + +instance [Module.Finite k L] [Module.Projective k L] : Module.Finite k (TwistedMat k L) := + inferInstanceAs (Module.Finite k ((k × Module.Dual k L) × (k × L))) + +instance [Module.Finite k L] [Module.Projective k L] : Module.Projective k (TwistedMat k L) := + inferInstanceAs (Module.Projective k ((k × Module.Dual k L) × (k × L))) + +variable {k L} + +/-- Two twisted matrices agree as soon as their four entries do. -/ +theorem ext {x y : TwistedMat k L} (h₁ : x.1.1 = y.1.1) (h₂ : x.1.2 = y.1.2) + (h₃ : x.2.1 = y.2.1) + (h₄ : x.2.2 = y.2.2) : x = y := + Prod.ext (Prod.ext h₁ h₂) (Prod.ext h₃ h₄) + +@[simp] theorem fst_zero : (0 : TwistedMat k L).1 = 0 := rfl +@[simp] theorem fst_neg (x : TwistedMat k L) : (-x).1 = -x.1 := rfl +@[simp] theorem snd_neg (x : TwistedMat k L) : (-x).2 = -x.2 := rfl +@[simp] theorem fst_sub (x y : TwistedMat k L) : (x - y).1 = x.1 - y.1 := rfl +@[simp] theorem snd_sub (x y : TwistedMat k L) : (x - y).2 = x.2 - y.2 := rfl +@[simp] theorem snd_zero : (0 : TwistedMat k L).2 = 0 := rfl +@[simp] theorem fst_add (x y : TwistedMat k L) : (x + y).1 = x.1 + y.1 := rfl +@[simp] theorem snd_add (x y : TwistedMat k L) : (x + y).2 = x.2 + y.2 := rfl +@[simp] theorem fst_smul (c : k) (x : TwistedMat k L) : (c • x).1 = c • x.1 := rfl +@[simp] theorem snd_smul (c : k) (x : TwistedMat k L) : (c • x).2 = c • x.2 := rfl + +variable (k L) + +/-- **Matrix multiplication of twisted matrices**, `GPR 22.12`: the entries of `L*` and of `L` +multiply through the canonical pairing. -/ +instance : Mul (TwistedMat k L) := + ⟨fun x y ↦ + (((x.1.1 * y.1.1 + x.1.2 y.2.2, x.1.1 • y.1.2 + y.2.1 • x.1.2), + (x.2.1 * y.2.1 + y.1.2 x.2.2, y.1.1 • x.2.2 + x.2.1 • y.2.2)) : + (k × Module.Dual k L) × (k × L))⟩ + +/-- The identity matrix. -/ +instance : One (TwistedMat k L) := + ⟨(((1, 0), (1, 0)) : (k × Module.Dual k L) × (k × L))⟩ + +variable {k L} + +@[simp] theorem mul_fst_fst (x y : TwistedMat k L) : + (x * y).1.1 = x.1.1 * y.1.1 + x.1.2 y.2.2 := rfl +@[simp] theorem mul_fst_snd (x y : TwistedMat k L) : + (x * y).1.2 = x.1.1 • y.1.2 + y.2.1 • x.1.2 := rfl +@[simp] theorem mul_snd_fst (x y : TwistedMat k L) : + (x * y).2.1 = x.2.1 * y.2.1 + y.1.2 x.2.2 := rfl +@[simp] theorem mul_snd_snd (x y : TwistedMat k L) : + (x * y).2.2 = y.1.1 • x.2.2 + x.2.1 • y.2.2 := rfl +@[simp] theorem one_fst_fst : (1 : TwistedMat k L).1.1 = 1 := rfl +@[simp] theorem one_fst_snd : (1 : TwistedMat k L).1.2 = 0 := rfl +@[simp] theorem one_snd_fst : (1 : TwistedMat k L).2.1 = 1 := rfl +@[simp] theorem one_snd_snd : (1 : TwistedMat k L).2.2 = 0 := rfl + +variable (k L) + +instance : NonAssocRing (TwistedMat k L) := + { (inferInstance : AddCommGroup (TwistedMat k L)), (inferInstance : Mul (TwistedMat k L)), + (inferInstance : One (TwistedMat k L)) with + left_distrib := fun x y z ↦ TwistedMat.ext (by simp; ring) (by simp; module) + (by simp; ring) (by simp; module) + right_distrib := fun x y z ↦ TwistedMat.ext (by simp; ring) (by simp; module) + (by simp; ring) (by simp; module) + zero_mul := fun x ↦ TwistedMat.ext (by simp) (by simp) (by simp) (by simp) + mul_zero := fun x ↦ TwistedMat.ext (by simp) (by simp) (by simp) (by simp) + one_mul := fun x ↦ TwistedMat.ext (by simp) (by simp) (by simp) (by simp) + mul_one := fun x ↦ TwistedMat.ext (by simp) (by simp) (by simp) (by simp) } + +instance : SMulCommClass k (TwistedMat k L) (TwistedMat k L) := + ⟨fun c x y ↦ TwistedMat.ext (by simp; ring) (by simp; module) (by simp; ring) + (by simp; module)⟩ + +instance : IsScalarTower k (TwistedMat k L) (TwistedMat k L) := + ⟨fun c x y ↦ TwistedMat.ext (by simp; ring) (by simp; module) (by simp; ring) + (by simp; module)⟩ + +end TwistedMat + +/-! ### The norm + +`n = ρ₁ρ₂ - ⟨u*, v⟩` is the pairing of the top row against the bottom row, once the +bottom row is +read in `k ⊕ L` and the top row in its dual. That is what makes it hyperbolic. -/ + +/-- The identification `k × L* ≃ (k ⊕ L)*` sending `(ρ, u*)` to +`(a, w) ↦ ρa - ⟨u*, w⟩`. The sign +is what turns the norm below into the hyperbolic pairing. -/ +def dualProdEquiv : (k × Module.Dual k L) ≃ₗ[k] Module.Dual k (k × L) where + toFun p := p.1 • (LinearMap.fst k k L) - p.2 ∘ₗ (LinearMap.snd k k L) + map_add' p q := by + ext w + · simp + · simp + ring + map_smul' c p := by ext w <;> simp + invFun f := (f (1, 0), -(f ∘ₗ LinearMap.inr k k L)) + left_inv p := by + refine Prod.ext ?_ ?_ + · simp + · ext w; simp + right_inv f := by + refine LinearMap.ext fun w ↦ ?_ + have hw : f w = f (w.1, 0) + f (0, w.2) := by + rw [← map_add] + congr 1 + simp + have h1 : f ((w.1 : k), (0 : L)) = w.1 * f (1, 0) := by + rw [show ((w.1, (0 : L)) : k × L) = w.1 • (1, 0) by simp, map_smul, smul_eq_mul] + simp [hw, h1] + ring + +variable {k L} + +@[simp] theorem dualProdEquiv_apply (p : k × Module.Dual k L) (w : k × L) : + dualProdEquiv k L p w = p.1 * w.1 - p.2 w.2 := by + simp [dualProdEquiv] + +variable (k L) + +/-- The linear equivalence presenting a twisted matrix as an element of `(k ⊕ L)* ⊕ (k ⊕ L)`, +under which the norm becomes the hyperbolic form `QuadraticForm.dualProd k (k × L)`. -/ +def twistedMatDualProdEquiv : + TwistedMat k L ≃ₗ[k] (Module.Dual k (k × L) × (k × L)) := + (dualProdEquiv k L).prodCongr (LinearEquiv.refl k (k × L)) + +@[simp] theorem twistedMatDualProdEquiv_apply (x : TwistedMat k L) : + twistedMatDualProdEquiv k L x = (dualProdEquiv k L x.1, x.2) := rfl + +/-- The **norm of a twisted matrix**, `GPR (22.12.1)`: +`n = ρ₁ρ₂ - ⟨u*, v⟩`, the determinant. -/ +def twistedMatNorm : QuadraticForm k (TwistedMat k L) := + (QuadraticForm.dualProd k (k × L)).comp (twistedMatDualProdEquiv k L).toLinearMap + +variable {k L} + +@[simp] theorem twistedMatNorm_apply (x : TwistedMat k L) : + twistedMatNorm k L x = x.1.1 * x.2.1 - x.1.2 x.2.2 := by + rw [twistedMatNorm, QuadraticMap.comp_apply, LinearEquiv.coe_coe, + twistedMatDualProdEquiv_apply, QuadraticForm.dualProd_apply, dualProdEquiv_apply] + +theorem polar_twistedMatNorm (x y : TwistedMat k L) : + QuadraticMap.polar (twistedMatNorm k L) x y = + x.1.1 * y.2.1 + y.1.1 * x.2.1 - x.1.2 y.2.2 - y.1.2 x.2.2 := by + simp only [QuadraticMap.polar, twistedMatNorm_apply, TwistedMat.fst_add, TwistedMat.snd_add, + Prod.fst_add, Prod.snd_add, LinearMap.add_apply, map_add] + ring + +@[simp] theorem polar_twistedMatNorm_one (x : TwistedMat k L) : + QuadraticMap.polar (twistedMatNorm k L) 1 x = x.1.1 + x.2.1 := by + rw [polar_twistedMatNorm] + simp [add_comm] + +variable (k L) + +/-- **`GPR 22.12`: the twisted matrices form a conic algebra**, with norm +`ρ₁ρ₂ - ⟨u*, v⟩` and +trace `ρ₁ + ρ₂`. No hypothesis on `L` at all, and none on `2`. -/ +def twistedMat : ConicAlgebra k (TwistedMat k L) where + norm := twistedMatNorm k L + norm_one := by simp + mul_self x := by + refine TwistedMat.ext ?_ ?_ ?_ ?_ + · simp; ring + · simp [add_smul] + · simp; ring + · simp [add_smul] + +variable {k L} + +@[simp] theorem twistedMat_norm : (twistedMat k L).norm = twistedMatNorm k L := rfl + +/-- **The trace of a twisted matrix is the sum of its diagonal entries**, `GPR (22.12.2)`. -/ +@[simp] theorem trace_twistedMat_apply (x : TwistedMat k L) : + (twistedMat k L).trace x = x.1.1 + x.2.1 := by + rw [ConicAlgebra.trace_apply, twistedMat_norm, polar_twistedMatNorm_one] + +/-- **The conjugation exchanges the diagonal entries and negates the off-diagonal ones**, +`GPR (22.12.3)`. -/ +@[simp] theorem conj_twistedMat_apply (x : TwistedMat k L) : + (twistedMat k L).conj x = (((x.2.1, -x.1.2), (x.1.1, -x.2.2)) : + (k × Module.Dual k L) × (k × L)) := by + refine TwistedMat.ext ?_ ?_ ?_ ?_ <;> simp [ConicAlgebra.conj_apply] + +/-! ### Non-singularity, multiplicativity, and the composition algebra -/ + +variable (k L) + +/-- **The norm of the twisted matrices is non-singular** for `L` finitely generated projective: it +*is* the hyperbolic form of `k ⊕ L`. No rank hypothesis and no hypothesis on `2`. -/ +theorem isGPRNonsingular_twistedMatNorm [Module.Finite k L] [Module.Projective k L] : + QuadraticForm.IsGPRNonsingular.{u, max u v, w} (twistedMatNorm k L) := + (QuadraticForm.isGPRNonsingular_dualProd k (k × L)).comp_linearEquiv _ + +variable {k L} + +/-- **The norm of the twisted matrices permits composition** exactly when `L` has the rank-one +pairing identity: expanding `n(xy)` and `n(x)n(y)` leaves precisely the difference +`⟨u*, z⟩⟨w*, v⟩ - ⟨u*, v⟩⟨w*, z⟩`. -/ +theorem isMultiplicative_twistedMat (h : Module.IsRankOnePairing k L) : + (twistedMat k L).IsMultiplicative := by + intro x y + simp only [twistedMat_norm, twistedMatNorm_apply, TwistedMat.mul_fst_fst, + TwistedMat.mul_fst_snd, TwistedMat.mul_snd_fst, TwistedMat.mul_snd_snd, LinearMap.add_apply, + LinearMap.smul_apply, map_add, map_smul, smul_eq_mul] + have hxy := h x.1.2 y.1.2 y.2.2 x.2.2 + linear_combination hxy + +/-- **The twisted matrices form a composition algebra**, for `L` finitely generated projective with +the rank-one pairing identity — that is, for `L` a line bundle. This is the object of +`GPR 22.12`. -/ +theorem isComposition_twistedMat [Module.Finite k L] [Module.Projective k L] + (h : Module.IsRankOnePairing k L) : (twistedMat k L).IsComposition.{u, max u v, w} where + isGPRNonsingular := isGPRNonsingular_twistedMatNorm.{u, v, w} k L + isMultiplicative := isMultiplicative_twistedMat h + +/-- **`GPR 22.12`.** Twisted matrices attached to an invertible module form a composition +algebra. The required rank-one pairing identity follows from +`Module.invertible_iff_isLocallyFreeRankOne`. -/ +theorem isComposition_twistedMat_of_invertible [Module.Invertible k L] : + (twistedMat k L).IsComposition.{u, max u v, w} := + isComposition_twistedMat Module.isRankOnePairing_of_invertible + +variable (k L) + +/-- **`GPR 22.13`, the easy half**: the algebra of `L`-twisted matrices is *reduced*. The matrix +unit `e₁₁` of `GPR (22.12.4)` has norm `0` and trace `1`, so it is an elementary idempotent and +`GPR 22.9` applies: the norm is isotropic and the algebra contains a split quadratic étale +subalgebra. No hypothesis on `L`. -/ +theorem hasElementaryIdempotent_twistedMat : (twistedMat k L).HasElementaryIdempotent := + ⟨(((1, 0), (0, 0)) : (k × Module.Dual k L) × (k × L)), + (twistedMatNorm_apply (((1, 0), (0, 0)) : TwistedMat k L)).trans (by simp), + (trace_twistedMat_apply (((1, 0), (0, 0)) : TwistedMat k L)).trans (by simp)⟩ + +/-! ### `GPR 22.13`: every reduced quaternion algebra is twisted matrices -/ + +namespace IsElementaryIdempotent + +variable {A : Type v} [NonAssocRing A] [Module k A] [SMulCommClass k A A] + [IsScalarTower k A A] [IsAlternative A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {c : A} + +/-- The lower-left Peirce component used as the twisting line bundle in `GPR 22.13`. -/ +abbrev TwistingModule (c : A) := + IsAlternative.peirceComponent (R := k) c true false + +/-- The Peirce-coordinate map from twisted matrices to a reduced rank-four composition algebra. +The upper-right coordinate uses the **negative** polar duality, matching the convention +`n([[a,φ],[v,b]]) = ab - φ(v)` in `GPR (22.12.1)`. -/ +noncomputable def twistedMatToPeirce (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + TwistedMat k (TwistingModule (k := k) c) →ₗ[k] A := by + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let e := hc.offDiagonalDuality hcomp.isMultiplicative hreg + exact + { toFun := fun x ↦ peirceElement c x.1.1 x.2.1 (e.symm (-x.1.2)) x.2.2 + map_add' := fun x y ↦ by + simp only [TwistedMat.fst_add, TwistedMat.snd_add, Prod.fst_add, Prod.snd_add, + map_add, map_neg, neg_add_rev, peirceElement, add_smul, Submodule.coe_add] + module + map_smul' := fun a x ↦ by + change peirceElement c (a * x.1.1) (a * x.2.1) + (e.symm (-(a • x.1.2))) (a • x.2.2) = + a • peirceElement c x.1.1 x.2.1 (e.symm (-x.1.2)) x.2.2 + rw [show -(a • x.1.2) = a • (-x.1.2) by module, map_smul] + simp only [peirceElement, mul_smul, Submodule.coe_smul, smul_add] } + +@[simp] theorem twistedMatToPeirce_apply (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (x : TwistedMat k (TwistingModule (k := k) c)) : + twistedMatToPeirce (k := k) hc hcomp hA x = peirceElement c x.1.1 x.2.1 + ((hc.offDiagonalDuality hcomp.isMultiplicative + (hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega))).symm (-x.1.2)) x.2.2 := rfl + +/-- The Peirce-coordinate map is bijective. This is the additive decomposition and the regular +off-diagonal duality assembled into one map. -/ +theorem bijective_twistedMatToPeirce (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + Function.Bijective (twistedMatToPeirce (k := k) hc hcomp hA) := by + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let e := hc.offDiagonalDuality hcomp.isMultiplicative hreg + constructor + · intro x y hxy + have hproj (i j : Bool) := congrArg + (IsAlternative.peirceProjection (R := k) c i j) hxy + apply TwistedMat.ext + · have h := congrArg C.trace (hproj false false) + rw [twistedMatToPeirce_apply, twistedMatToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa [hc.trace_eq_one] using h + · have h := hproj false true + rw [twistedMatToPeirce_apply, twistedMatToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa using h + · have h := congrArg C.trace (hproj true true) + rw [twistedMatToPeirce_apply, twistedMatToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simp only [Prod.mk.injEq, Bool.true_eq_false, and_self, false_and, and_false, + ite_false] at h + have ht : C.trace (IsAlternative.peirceIdempotent c true) = 1 := + (hc.peirceIdempotent true).trace_eq_one + simpa only [map_smul, ht, smul_eq_mul, mul_one] using h + · have h := hproj true false + rw [twistedMatToPeirce_apply, twistedMatToPeirce_apply, + hc.peirceProjection_peirceElement, hc.peirceProjection_peirceElement] at h + simpa using h + · intro a + obtain ⟨a₁, a₂, x₁₂, x₂₁, ha⟩ := + hc.exists_eq_peirceElement hcomp.isMultiplicative a + let x : TwistedMat k (TwistingModule (k := k) c) := + (((a₁, -(e x₁₂)), (a₂, x₂₁)) : + (k × Module.Dual k (TwistingModule (k := k) c)) × + (k × TwistingModule (k := k) c)) + refine ⟨x, ?_⟩ + rw [ha, twistedMatToPeirce_apply] + change peirceElement c a₁ a₂ (e.symm (-(-(e x₁₂)))) x₂₁ = _ + rw [neg_neg, e.symm_apply_apply] + +/-- The linear equivalence underlying the converse half of `GPR 22.13`. -/ +noncomputable def twistedMatEquiv (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + TwistedMat k (TwistingModule (k := k) c) ≃ₗ[k] A := + LinearEquiv.ofBijective (twistedMatToPeirce (k := k) hc hcomp hA) + (bijective_twistedMatToPeirce (k := k) hc hcomp hA) + +@[simp] theorem twistedMatEquiv_apply (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (x : TwistedMat k (TwistingModule (k := k) c)) : + twistedMatEquiv (k := k) hc hcomp hA x = + twistedMatToPeirce (k := k) hc hcomp hA x := rfl + +/-- The equivalence of `GPR 22.13` preserves the norm. -/ +theorem norm_twistedMatEquiv (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (x : TwistedMat k (TwistingModule (k := k) c)) : + C.norm (twistedMatEquiv (k := k) hc hcomp hA x) = + twistedMatNorm k (TwistingModule (k := k) c) x := by + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let e := hc.offDiagonalDuality hcomp.isMultiplicative hreg + rw [twistedMatEquiv_apply, twistedMatToPeirce_apply, + hc.norm_peirceElement hcomp.isMultiplicative, twistedMatNorm_apply] + change x.1.1 * x.2.1 + e (e.symm (-x.1.2)) x.2.2 = _ + rw [e.apply_symm_apply] + rw [sub_eq_add_neg] + rfl + +/-- The equivalence of `GPR 22.13` is unital. -/ +theorem twistedMatEquiv_one (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + twistedMatEquiv (k := k) hc hcomp hA 1 = 1 := by + rw [twistedMatEquiv_apply, twistedMatToPeirce_apply] + simp only [TwistedMat.one_fst_fst, TwistedMat.one_fst_snd, TwistedMat.one_snd_fst, + TwistedMat.one_snd_snd, neg_zero, map_zero] + simp [peirceElement, IsAlternative.peirceIdempotent] + +/-- The equivalence of `GPR 22.13` is multiplicative. -/ +theorem twistedMatEquiv_mul (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) + (x y : TwistedMat k (TwistingModule (k := k) c)) : + twistedMatEquiv (k := k) hc hcomp hA (x * y) = + twistedMatEquiv (k := k) hc hcomp hA x * + twistedMatEquiv (k := k) hc hcomp hA y := by + let hreg := hcomp.isGPRRegular_of_rankAtStalk_ne_one hA (by omega) + let e := hc.offDiagonalDuality hcomp.isMultiplicative hreg + rw [twistedMatEquiv_apply, twistedMatEquiv_apply, twistedMatEquiv_apply, + twistedMatToPeirce_apply, twistedMatToPeirce_apply, twistedMatToPeirce_apply, + hc.mul_peirceElement_of_rankAtStalk_eq_four hcomp hA] + simp only [TwistedMat.mul_fst_fst, TwistedMat.mul_fst_snd, TwistedMat.mul_snd_fst, + TwistedMat.mul_snd_snd] + have hpolar (f : Module.Dual k (TwistingModule (k := k) c)) + (z : TwistingModule (k := k) c) : + QuadraticMap.polar C.norm (e.symm (-f)) z = -f z := by + change e (e.symm (-f)) z = -f z + rw [e.apply_symm_apply] + rfl + congr 1 + · rw [hpolar] + ring + · rw [hpolar] + ring + · apply e.injective + simp only [map_add, map_smul] + ext z + simp + abel + +/-- The lower-left Peirce component of a reduced rank-four composition algebra is a line bundle, +as required in `GPR 22.13`. -/ +theorem invertible_twistingModule (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + Module.Invertible k (TwistingModule (k := k) c) := + Module.invertible_iff_isLocallyFreeRankOne.2 + (hc.isLocallyFreeRankOne_offDiagonal hcomp hA true) + +/-- The norm isometry underlying the converse half of `GPR 22.13`. -/ +noncomputable def twistedMatIsometryEquiv (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + (twistedMat k (TwistingModule (k := k) c)).norm.IsometryEquiv C.norm where + toLinearEquiv := twistedMatEquiv (k := k) hc hcomp hA + map_app' := norm_twistedMatEquiv (k := k) hc hcomp hA + +/-- **`GPR 22.13`, the converse half**: a reduced composition algebra of constant rank four is +isomorphic to the twisted matrices attached to the line bundle `C₂₁`. -/ +theorem isomorphic_twistedMat (hc : C.IsElementaryIdempotent c) + (hcomp : C.IsComposition.{u, v, u}) + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ 4) : + (twistedMat k (TwistingModule (k := k) c)).Isomorphic C := + ⟨twistedMatIsometryEquiv (k := k) hc hcomp hA, + twistedMatEquiv_one (k := k) hc hcomp hA, + twistedMatEquiv_mul (k := k) hc hcomp hA⟩ + +end IsElementaryIdempotent + +/-! ### A twisted matrix algebra on a free line is split -/ + +variable {L : Type v} [AddCommGroup L] [Module k L] + +/-- Coordinates from twisted matrices on a based line to ordinary two-by-two matrices. -/ +noncomputable def twistedMatOfBasisEquiv (b : Module.Basis Unit k L) : + TwistedMat k L ≃ₗ[k] Matrix (Fin 2) (Fin 2) k where + toFun x := !![x.1.1, x.1.2 (b ()); b.repr x.2.2 (), x.2.1] + invFun A := ((A 0 0, A 0 1 • b.dualBasis ()), (A 1 1, A 1 0 • b ())) + map_add' x y := by ext i j; fin_cases i <;> fin_cases j <;> simp + map_smul' a x := by ext i j; fin_cases i <;> fin_cases j <;> simp + left_inv x := by + apply TwistedMat.ext + · rfl + · ext z + rw [← b.sum_repr z] + simp + · rfl + · rw [← b.sum_repr x.2.2] + simp + right_inv A := by + ext i j + fin_cases i <;> fin_cases j <;> simp + +@[simp] theorem twistedMatOfBasisEquiv_apply (b : Module.Basis Unit k L) + (x : TwistedMat k L) : + twistedMatOfBasisEquiv k b x = !![x.1.1, x.1.2 (b ()); b.repr x.2.2 (), x.2.1] := rfl + +/-- The coordinate equivalence from twisted matrices on a based line preserves the norm. -/ +theorem det_twistedMatOfBasisEquiv (b : Module.Basis Unit k L) (x : TwistedMat k L) : + Matrix.det (twistedMatOfBasisEquiv k b x) = twistedMatNorm k L x := by + rw [twistedMatOfBasisEquiv_apply, Matrix.det_fin_two, twistedMatNorm_apply] + have hv := b.sum_repr x.2.2 + simp only [Fintype.sum_unique] at hv + rw [← hv] + simp + ring + +/-- The coordinate equivalence from twisted matrices on a based line preserves the identity. -/ +theorem twistedMatOfBasisEquiv_one (b : Module.Basis Unit k L) : + twistedMatOfBasisEquiv k b (1 : TwistedMat k L) = 1 := by + rw [twistedMatOfBasisEquiv_apply] + ext i j + fin_cases i <;> fin_cases j <;> simp + +/-- The coordinate equivalence from twisted matrices on a based line preserves multiplication. -/ +theorem twistedMatOfBasisEquiv_mul (b : Module.Basis Unit k L) (x y : TwistedMat k L) : + twistedMatOfBasisEquiv k b (x * y) = + twistedMatOfBasisEquiv k b x * twistedMatOfBasisEquiv k b y := by + have hx := b.sum_repr x.2.2 + have hy := b.sum_repr y.2.2 + simp only [Fintype.sum_unique] at hx hy + have hx_eval (f : Module.Dual k L) : f x.2.2 = b.repr x.2.2 () * f (b ()) := by + rw [← hx] + simp + have hy_eval (f : Module.Dual k L) : f y.2.2 = b.repr y.2.2 () * f (b ()) := by + rw [← hy] + simp + rw [twistedMatOfBasisEquiv_apply, twistedMatOfBasisEquiv_apply, + twistedMatOfBasisEquiv_apply] + ext i j + fin_cases i <;> fin_cases j + · simp [Matrix.mul_apply, Fin.sum_univ_two, hy_eval] + ring + · simp [Matrix.mul_apply, Fin.sum_univ_two] + ring + · simp [Matrix.mul_apply, Fin.sum_univ_two] + ring + · simp [Matrix.mul_apply, Fin.sum_univ_two, hx_eval] + ring + +/-- **The splitness assertion in `GPR 22.13`:** twisted matrices on a free line are the split +quaternion algebra. -/ +theorem isomorphic_twistedMat_ofBasis (b : Module.Basis Unit k L) : + (twistedMat k L).Isomorphic (splitQuaternion k) := + ⟨⟨twistedMatOfBasisEquiv k b, by + intro x + rw [splitQuaternion_norm, twistedMat_norm, splitQuaternionNorm_apply] + exact det_twistedMatOfBasisEquiv k b x⟩, + twistedMatOfBasisEquiv_one k b, twistedMatOfBasisEquiv_mul k b⟩ + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedZorn.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedZorn.lean new file mode 100644 index 0000000000..3991566fbc --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/TwistedZorn.lean @@ -0,0 +1,503 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedMatrix +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Zorn +public import LeanPool.CompositionAlgebrasOverRings.Conic.Kirmse +public import LeanPool.CompositionAlgebrasOverRings.Module.VectorProduct + +/-! +# Twisted Zorn vector matrices (`GPR 22.14`) + +For `M` a `k`-module equipped with a pair of associated vector products +(`Module.VectorProductPair`), the **twisted Zorn vector matrices** are the formal matrices + + `[ρ₁ u*]` + `[v ρ₂]`, `ρᵢ ∈ k`, `u* ∈ M*`, `v ∈ M`, + +multiplied by `GPR (22.14.3)` + + `[ρ₁ v*] [σ₁ w*] [ρ₁σ₁ - ⟨v*, w⟩ ρ₁w* + σ₂v* + v × w]` + `[v ρ₂] [w σ₂] = [σ₁v + ρ₂w + v* × w* ρ₂σ₂ - ⟨w*, v⟩ ]`, + +Its norm is `ρ₁ρ₂ + ⟨u*, v⟩` and its trace is `ρ₁ + ρ₂`. +With the usual conjugation, it is the octonion analogue of +`Conic/../TwistedMatrix.lean`: +there the off-diagonal entries multiply through the canonical pairing alone, here they also +multiply through the two vector products. + +`GPR 22.14` builds the pair of vector products from an orientation `θ : ⋀³ M ≅ k` of a +projective module of rank three, and calls the result `Zor(M, θ)`. By `GPR 22.15` (Petersson) +**every** reduced octonion algebra is one of these, and `Zor(M, θ)` is split when `M` is free +(`GPR` asserts only this implication). + +## What is proved here + +* the conic structure, its norm, trace and conjugation — for **any** `k`-module `M` with a vector + product pair, and with no hypothesis on `2`; +* **regularity and non-singularity of the norm** for `M` finitely generated projective, and again + not by a computation: the norm is the hyperbolic form of `k ⊕ M`, pairing `(ρ₁, u*)` against + `(ρ₂, v)`, so the hyperbolic-form API applies with no basis and no rank hypothesis; +* **multiplicativity of the norm**, which consumes the vector-product axioms exactly: the four + orthogonality identities kill four of the nine cross terms and Binet–Cauchy converts the ninth, + after which `n(xy) - n(x)n(y)` is identically zero; +* hence that it is a **composition algebra**, and a **reduced** one: the matrix unit `e₁₁` of + `GPR (22.14.7)` is an elementary idempotent, so `GPR 22.9` applies to it. +* **alternativity** for `M` finitely generated projective: regularity makes the radical zero, so + Kirmse's theorem applies to the multiplicative conic algebra, without a hypothesis on `2`. + +Combined with `Module.VectorProductPair.ofBasis`, this produces a composition algebra of rank +eight over any commutative ring out of any free module of rank three — the split case, and the +case `GPR 22.14`'s localization argument reduces to. The coordinate isomorphism +`isomorphic_twistedZor_ofBasis` proves that this free case is exactly `Zor(k)` from `GPR 21.18`. + +## Main definitions + +* `ConicAlgebra.TwistedZor P` : the module of twisted Zorn vector matrices, with its + multiplication. +* `ConicAlgebra.twistedZorNorm P`, `ConicAlgebra.twistedZor P` : the norm and the conic structure. + +## Main results + +* `ConicAlgebra.isGPRNonsingular_twistedZorNorm` : the norm is hyperbolic, hence non-singular. +* `ConicAlgebra.isMultiplicative_twistedZor` : the norm permits composition. +* `ConicAlgebra.isAlternative_twistedZor` : the algebra is alternative for `M` finitely + generated projective. +* `ConicAlgebra.isComposition_twistedZor` : it is a composition algebra. +* `ConicAlgebra.hasElementaryIdempotent_twistedZor` : it is reduced. +* `ConicAlgebra.isomorphic_twistedZor_ofBasis` : a pair built from a basis gives the split Zorn + algebra. +* `ConicAlgebra.instIsAlternativeTwistedZorOfBasis` : the basis-built algebra is alternative. +* `ConicAlgebra.isSplitOfRank_twistedZor_ofBasis` : the basis-built algebra is split of rank eight. + +## Implementation notes + +⚠ **The sign of the norm.** `GPR (22.14.4)` prints `n = ρ₁ρ₂ - ⟨u*, v⟩`, but the norm of +these algebras is `ρ₁ρ₂ + ⟨u*, v⟩`, which is used here. The two cannot both be right: +the +multiplication `GPR (22.14.3)` specializes, for `M = k³` with the standard orientation, to the +multiplication `GPR (21.18.4)` of ordinary Zorn vector matrices, whose norm is +`ρ₁ρ₂ + u₁ᵀu₂` by `GPR (21.18.6)` — the sign difference from the quaternion case +`GPR (22.12.1)` is already present +in `GPR`, and comes from the diagonal entries of `(22.14.3)` carrying a minus sign where those of +`(22.12.1)` carry a plus. The `+` sign is also what the Peirce norm formula +`ConicAlgebra.IsElementaryIdempotent.norm_peirceElement` gives, under the identification of +`C₁₂` with `M*` by the *positive* polar duality that `GPR 22.15`'s own proof uses. + +The multiplication is not the componentwise one, so `TwistedZor` is a type synonym; it is indexed +by the vector product pair `P`, not merely by `M`, because the multiplication depends on `P`. This +is the same device as `ConicAlgebra.Cay`, which is indexed by the conic structure and the scalar. + +## Orientation and converse + +`Composition/Reduced/Orientation.lean` constructs the pair from an orientation of a +constant-rank-three finite projective module over any commutative ring, by the unbased local +exterior-power duality argument in `GPR 21.7`. The converse `GPR 22.15` is proved in +`Composition/Reduced/RankEight.lean`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 21.18, 22.9, 22.12, + 22.14, 22.15. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {M : Type v} [CommRing k] [AddCommGroup M] [Module k M] + +/-- The `k`-module of **twisted Zorn vector matrices** attached to a vector product pair +(`GPR 22.14`), as a type synonym for `(k × M*) × (k × M)`: the element `x` is the matrix + + `[x.1.1 x.1.2]` + `[x.2.2 x.2.1]` + +whose top row is `x.1 = (ρ₁, u*)` and whose bottom row is +`(x.2.2, x.2.1) = (v, ρ₂)`. The grouping puts the two diagonal entries first in their pairs, so +that the norm is visibly the pairing of `x.1` against `x.2`. -/ +def TwistedZor (_P : Module.VectorProductPair k M) : Type max u v := + (k × Module.Dual k M) × (k × M) + +namespace TwistedZor + +variable (P : Module.VectorProductPair k M) + +instance : AddCommGroup (TwistedZor P) := + inferInstanceAs (AddCommGroup ((k × Module.Dual k M) × (k × M))) + +instance : Module k (TwistedZor P) := + inferInstanceAs (Module k ((k × Module.Dual k M) × (k × M))) + +instance [Module.Finite k M] [Module.Projective k M] : Module.Finite k (TwistedZor P) := + inferInstanceAs (Module.Finite k ((k × Module.Dual k M) × (k × M))) + +instance [Module.Finite k M] [Module.Projective k M] : Module.Projective k (TwistedZor P) := + inferInstanceAs (Module.Projective k ((k × Module.Dual k M) × (k × M))) + +variable {P} + +/-- Two twisted Zorn vector matrices agree as soon as their four entries do. -/ +theorem ext {x y : TwistedZor P} (h₁ : x.1.1 = y.1.1) (h₂ : x.1.2 = y.1.2) + (h₃ : x.2.1 = y.2.1) (h₄ : x.2.2 = y.2.2) : x = y := + Prod.ext (Prod.ext h₁ h₂) (Prod.ext h₃ h₄) + +@[simp] theorem fst_zero : (0 : TwistedZor P).1 = 0 := rfl +@[simp] theorem snd_zero : (0 : TwistedZor P).2 = 0 := rfl +@[simp] theorem fst_add (x y : TwistedZor P) : (x + y).1 = x.1 + y.1 := rfl +@[simp] theorem snd_add (x y : TwistedZor P) : (x + y).2 = x.2 + y.2 := rfl +@[simp] theorem fst_neg (x : TwistedZor P) : (-x).1 = -x.1 := rfl +@[simp] theorem snd_neg (x : TwistedZor P) : (-x).2 = -x.2 := rfl +@[simp] theorem fst_sub (x y : TwistedZor P) : (x - y).1 = x.1 - y.1 := rfl +@[simp] theorem snd_sub (x y : TwistedZor P) : (x - y).2 = x.2 - y.2 := rfl +@[simp] theorem fst_smul (c : k) (x : TwistedZor P) : (c • x).1 = c • x.1 := rfl +@[simp] theorem snd_smul (c : k) (x : TwistedZor P) : (c • x).2 = c • x.2 := rfl + +variable (P) + +/-- **Multiplication of twisted Zorn vector matrices**, `GPR (22.14.3)`: the entries of `M*` and of +`M` multiply through the canonical pairing on the diagonal and through the two vector products off +it. -/ +instance : Mul (TwistedZor P) := + ⟨fun x y ↦ + (((x.1.1 * y.1.1 - x.1.2 y.2.2, x.1.1 • y.1.2 + y.2.1 • x.1.2 + P.cross x.2.2 y.2.2), + (x.2.1 * y.2.1 - y.1.2 x.2.2, y.1.1 • x.2.2 + x.2.1 • y.2.2 + P.crossDual x.1.2 y.1.2)) : + (k × Module.Dual k M) × (k × M))⟩ + +/-- The identity matrix. -/ +instance : One (TwistedZor P) := + ⟨(((1, 0), (1, 0)) : (k × Module.Dual k M) × (k × M))⟩ + +variable {P} + +@[simp] theorem mul_fst_fst (x y : TwistedZor P) : + (x * y).1.1 = x.1.1 * y.1.1 - x.1.2 y.2.2 := rfl +@[simp] theorem mul_fst_snd (x y : TwistedZor P) : + (x * y).1.2 = x.1.1 • y.1.2 + y.2.1 • x.1.2 + P.cross x.2.2 y.2.2 := rfl +@[simp] theorem mul_snd_fst (x y : TwistedZor P) : + (x * y).2.1 = x.2.1 * y.2.1 - y.1.2 x.2.2 := rfl +@[simp] theorem mul_snd_snd (x y : TwistedZor P) : + (x * y).2.2 = y.1.1 • x.2.2 + x.2.1 • y.2.2 + P.crossDual x.1.2 y.1.2 := rfl +@[simp] theorem one_fst_fst : (1 : TwistedZor P).1.1 = 1 := rfl +@[simp] theorem one_fst_snd : (1 : TwistedZor P).1.2 = 0 := rfl +@[simp] theorem one_snd_fst : (1 : TwistedZor P).2.1 = 1 := rfl +@[simp] theorem one_snd_snd : (1 : TwistedZor P).2.2 = 0 := rfl + +variable (P) + +instance : NonAssocRing (TwistedZor P) := + { (inferInstance : AddCommGroup (TwistedZor P)), (inferInstance : Mul (TwistedZor P)), + (inferInstance : One (TwistedZor P)) with + left_distrib := fun x y z ↦ TwistedZor.ext (by simp; ring) (by simp; module) + (by simp; ring) (by simp; module) + right_distrib := fun x y z ↦ TwistedZor.ext (by simp; ring) (by simp; module) + (by simp; ring) (by simp; module) + zero_mul := fun x ↦ TwistedZor.ext (by simp) (by simp) (by simp) (by simp) + mul_zero := fun x ↦ TwistedZor.ext (by simp) (by simp) (by simp) (by simp) + one_mul := fun x ↦ TwistedZor.ext (by simp) (by simp) (by simp) (by simp) + mul_one := fun x ↦ TwistedZor.ext (by simp) (by simp) (by simp) (by simp) } + +instance : SMulCommClass k (TwistedZor P) (TwistedZor P) := + ⟨fun c x y ↦ TwistedZor.ext (by simp; ring) (by simp; module) (by simp; ring) + (by simp; module)⟩ + +instance : IsScalarTower k (TwistedZor P) (TwistedZor P) := + ⟨fun c x y ↦ TwistedZor.ext (by simp; ring) (by simp; module) (by simp; ring) + (by simp; module)⟩ + +end TwistedZor + +/-! ### The norm + +`n = ρ₁ρ₂ + ⟨u*, v⟩` pairs the top row against the bottom row, with the bottom row read in +`k ⊕ M` and the top row in its dual. That is what makes it hyperbolic, and it is why +no rank hypothesis and no basis is needed for non-singularity. -/ + +variable (P : Module.VectorProductPair k M) + +/-- The linear equivalence presenting a twisted Zorn vector matrix as an element of +`(k ⊕ M)* ⊕ (k ⊕ M)`, under which the norm becomes the hyperbolic form +`QuadraticForm.dualProd k (k × M)`. The sign on the dual coordinate compensates the one built into +`ConicAlgebra.dualProdEquiv`, which was chosen for the quaternion norm `ρ₁ρ₂ - ⟨u*, v⟩` of +`GPR (22.12.1)`. -/ +def twistedZorDualProdEquiv : TwistedZor P ≃ₗ[k] (Module.Dual k (k × M) × (k × M)) := + (((LinearEquiv.refl k k).prodCongr (LinearEquiv.neg k)).trans (dualProdEquiv k M)).prodCongr + (LinearEquiv.refl k (k × M)) + +@[simp] theorem twistedZorDualProdEquiv_apply (x : TwistedZor P) : + twistedZorDualProdEquiv P x = (dualProdEquiv k M (x.1.1, -x.1.2), x.2) := rfl + +/-- The **norm of a twisted Zorn vector matrix**, `GPR (22.14.4)`: `n = ρ₁ρ₂ + ⟨u*, v⟩`. + +⚠ `GPR (22.14.4)` prints a minus sign; see the module docstring for why it must be a plus. -/ +def twistedZorNorm : QuadraticForm k (TwistedZor P) := + (QuadraticForm.dualProd k (k × M)).comp (twistedZorDualProdEquiv P).toLinearMap + +variable {P} + +@[simp] theorem twistedZorNorm_apply (x : TwistedZor P) : + twistedZorNorm P x = x.1.1 * x.2.1 + x.1.2 x.2.2 := by + rw [twistedZorNorm, QuadraticMap.comp_apply, LinearEquiv.coe_coe, + twistedZorDualProdEquiv_apply, QuadraticForm.dualProd_apply, dualProdEquiv_apply] + simp + +theorem polar_twistedZorNorm (x y : TwistedZor P) : + QuadraticMap.polar (twistedZorNorm P) x y = + x.1.1 * y.2.1 + y.1.1 * x.2.1 + x.1.2 y.2.2 + y.1.2 x.2.2 := by + simp only [QuadraticMap.polar, twistedZorNorm_apply, TwistedZor.fst_add, TwistedZor.snd_add, + Prod.fst_add, Prod.snd_add, LinearMap.add_apply, map_add] + ring + +@[simp] theorem polar_twistedZorNorm_one (x : TwistedZor P) : + QuadraticMap.polar (twistedZorNorm P) 1 x = x.1.1 + x.2.1 := by + rw [polar_twistedZorNorm] + simp [add_comm] + +variable (P) + +/-- **`GPR 22.14`: the twisted Zorn vector matrices form a conic algebra**, with norm +`ρ₁ρ₂ + ⟨u*, v⟩` and trace `ρ₁ + ρ₂`. The degree-two identity uses only that the two +products are alternating; no other axiom, no hypothesis on `M`, and none on `2`. -/ +def twistedZor : ConicAlgebra k (TwistedZor P) where + norm := twistedZorNorm P + norm_one := by simp + mul_self x := by + refine TwistedZor.ext ?_ ?_ ?_ ?_ + · simp; ring + · simp [P.cross_self, add_smul] + · simp; ring + · simp [P.crossDual_self, add_smul] + +variable {P} + +@[simp] theorem twistedZor_norm : (twistedZor P).norm = twistedZorNorm P := rfl + +/-- **The trace of a twisted Zorn vector matrix is the trace of the matrix**, `GPR (22.14.5)`. -/ +@[simp] theorem trace_twistedZor_apply (x : TwistedZor P) : + (twistedZor P).trace x = x.1.1 + x.2.1 := by + rw [ConicAlgebra.trace_apply, twistedZor_norm, polar_twistedZorNorm_one] + +/-- **The conjugation exchanges the diagonal entries and negates the off-diagonal ones**, +`GPR (22.14.6)`. -/ +@[simp] theorem conj_twistedZor_apply (x : TwistedZor P) : + (twistedZor P).conj x = (((x.2.1, -x.1.2), (x.1.1, -x.2.2)) : + (k × Module.Dual k M) × (k × M)) := by + refine TwistedZor.ext ?_ ?_ ?_ ?_ <;> simp [ConicAlgebra.conj_apply] + +/-! ### Non-singularity, multiplicativity, and the composition algebra -/ + +variable (P) + +/-- **The norm of the twisted Zorn vector matrices is non-singular** for `M` finitely generated +projective: it *is* the hyperbolic form of `k ⊕ M`. No rank hypothesis and no hypothesis on +`2`. -/ +theorem isGPRNonsingular_twistedZorNorm [Module.Finite k M] [Module.Projective k M] : + QuadraticForm.IsGPRNonsingular.{u, max u v, w} (twistedZorNorm P) := + (QuadraticForm.isGPRNonsingular_dualProd k (k × M)).comp_linearEquiv _ + +/-- **The norm of the twisted Zorn vector matrices is regular** for `M` finitely generated +projective: it is the hyperbolic form of `k ⊕ M`, transported along a linear equivalence. This is +stronger than the non-singularity needed for composition and requires no hypothesis on `2`. -/ +theorem isGPRRegular_twistedZorNorm [Module.Finite k M] [Module.Projective k M] : + QuadraticForm.IsGPRRegular (twistedZorNorm P) := + (QuadraticForm.isGPRRegular_dualProd k (k × M)).comp_linearEquiv _ + +/-- The twisted Zorn norm has zero radical when `M` is finitely generated projective. -/ +theorem isGPRNondegenerate_twistedZorNorm [Module.Finite k M] [Module.Projective k M] : + QuadraticForm.IsGPRNondegenerate (twistedZorNorm P) := by + rw [QuadraticForm.IsGPRNondegenerate] + exact le_antisymm (QuadraticMap.radical_le_ker_polarBilin.trans + (((LinearMap.ker_eq_bot).2 (isGPRRegular_twistedZorNorm P).1).le)) bot_le + +variable {P} + +/-- **The norm of the twisted Zorn vector matrices permits composition**, `n(xy) = n(x)n(y)`. + +This is where the vector-product axioms are consumed, and they are consumed exactly: of the nine +terms of the off-diagonal pairing, four vanish by orthogonality of a product to its own arguments +and one is `⟨v × w, v* × w*⟩`, which Binet–Cauchy turns into the two remaining products of +pairings; what is left cancels identically. No hypothesis on `M`. -/ +theorem isMultiplicative_twistedZor : (twistedZor P).IsMultiplicative := by + intro x y + simp only [twistedZor_norm, twistedZorNorm_apply, TwistedZor.mul_fst_fst, + TwistedZor.mul_fst_snd, TwistedZor.mul_snd_fst, TwistedZor.mul_snd_snd, LinearMap.add_apply, + LinearMap.smul_apply, map_add, map_smul, smul_eq_mul, P.cross_apply_left, P.cross_apply_right, + P.apply_crossDual_left, P.apply_crossDual_right, P.cross_apply_crossDual] + ring + +/-- **`GPR 22.14`: twisted Zorn vector matrices are alternative** when `M` is finitely generated +projective. The hyperbolic norm is regular, hence has zero radical, so Kirmse's theorem applies to +the multiplicative conic structure. No hypothesis on `2` and no direct Grassmann-identity +calculation is needed. -/ +theorem isAlternative_twistedZor [Module.Finite k M] [Module.Projective k M] : + IsAlternative (TwistedZor P) := + isMultiplicative_twistedZor.isAlternative (isGPRNondegenerate_twistedZorNorm P) + +/-- **The twisted Zorn vector matrices form a composition algebra**, for `M` finitely generated +projective carrying a vector product pair. With `Module.VectorProductPair.ofBasis` this gives a +composition algebra of rank eight over any commutative ring, with no hypothesis on `2`; by +`GPR 22.14` it is `Zor(M, θ)` whenever the pair comes from an orientation of a rank-three +module. -/ +theorem isComposition_twistedZor [Module.Finite k M] [Module.Projective k M] : + (twistedZor P).IsComposition.{u, max u v, w} where + isGPRNonsingular := isGPRNonsingular_twistedZorNorm.{u, v, w} P + isMultiplicative := isMultiplicative_twistedZor + +variable (P) + +/-- **The twisted Zorn vector matrices are reduced.** The matrix unit `e₁₁` of +`GPR (22.14.7)` has norm `0` and trace `1`, so it is an elementary idempotent and `GPR 22.9` +applies: the norm is +isotropic and the algebra contains a split quadratic étale subalgebra. No hypothesis on `M`. -/ +theorem hasElementaryIdempotent_twistedZor : (twistedZor P).HasElementaryIdempotent := + ⟨(((1, 0), (0, 0)) : (k × Module.Dual k M) × (k × M)), + (twistedZorNorm_apply (((1, 0), (0, 0)) : TwistedZor P)).trans (by simp), + (trace_twistedZor_apply (((1, 0), (0, 0)) : TwistedZor P)).trans (by simp)⟩ + +/-! ### The free case + +When the vector product pair comes from a basis of `M`, reading the two off-diagonal entries in +the coordinates of that basis and its dual identifies the twisted construction with `Zor(k)`. +Thus `Module.VectorProductPair.ofBasis` produces exactly the split octonion algebra, independently +of the chosen basis. -/ + +variable (b : Module.Basis (Fin 3) k M) + +/-- The coordinate equivalence from the twisted Zorn algebra attached to a basis to the split Zorn +algebra. The lower-left entry uses the coordinates of `b`, while the upper-right entry uses the +coordinates of the dual basis. -/ +noncomputable def twistedZorOfBasisEquiv : + TwistedZor (Module.VectorProductPair.ofBasis b) ≃ₗ[k] Zor k where + toFun x := ((x.1.1, b.equivFun x.2.2), (x.2.1, b.dualCoord x.1.2)) + invFun x := + ((x.1.1, b.dualCoord.symm x.2.2), (x.2.1, b.equivFun.symm x.1.2)) + map_add' x y := by + change + ((x.1.1 + y.1.1, b.equivFun (x.2.2 + y.2.2)), + (x.2.1 + y.2.1, b.dualCoord (x.1.2 + y.1.2))) = + ((x.1.1 + y.1.1, b.equivFun x.2.2 + b.equivFun y.2.2), + (x.2.1 + y.2.1, b.dualCoord x.1.2 + b.dualCoord y.1.2)) + rw [map_add, map_add] + map_smul' c x := by + change + ((c • x.1.1, b.equivFun (c • x.2.2)), + (c • x.2.1, b.dualCoord (c • x.1.2))) = + ((c • x.1.1, c • b.equivFun x.2.2), + (c • x.2.1, c • b.dualCoord x.1.2)) + rw [map_smul, map_smul] + left_inv x := by + refine TwistedZor.ext rfl ?_ rfl ?_ + · exact b.dualCoord.symm_apply_apply x.1.2 + · exact b.equivFun.symm_apply_apply x.2.2 + right_inv x := by + refine Zor.ext rfl ?_ rfl ?_ + · exact b.equivFun.apply_symm_apply x.1.2 + · exact b.dualCoord.apply_symm_apply x.2.2 + +@[simp] theorem twistedZorOfBasisEquiv_apply + (x : TwistedZor (Module.VectorProductPair.ofBasis b)) : + twistedZorOfBasisEquiv b x = + ((x.1.1, b.equivFun x.2.2), (x.2.1, b.dualCoord x.1.2)) := + rfl + +/-- The coordinate equivalence preserves the norm. -/ +theorem zorNorm_twistedZorOfBasisEquiv + (x : TwistedZor (Module.VectorProductPair.ofBasis b)) : + zorNorm k (twistedZorOfBasisEquiv b x) = + twistedZorNorm (Module.VectorProductPair.ofBasis b) x := by + rw [zorNorm_apply, twistedZorOfBasisEquiv_apply, twistedZorNorm_apply, + b.apply_eq_dotProduct x.1.2 x.2.2] + exact congrArg (x.1.1 * x.2.1 + ·) + (dotProduct_comm (m := Fin 3) (b.equivFun x.2.2) (b.dualCoord x.1.2)) + +/-- The coordinate equivalence preserves the identity matrix. -/ +theorem twistedZorOfBasisEquiv_one : + twistedZorOfBasisEquiv b (1 : TwistedZor (Module.VectorProductPair.ofBasis b)) = 1 := by + refine Zor.ext rfl ?_ rfl ?_ + · exact map_zero b.equivFun + · exact map_zero b.dualCoord + +/-- The coordinate equivalence preserves multiplication. -/ +theorem twistedZorOfBasisEquiv_mul + (x y : TwistedZor (Module.VectorProductPair.ofBasis b)) : + twistedZorOfBasisEquiv b (x * y) = + twistedZorOfBasisEquiv b x * twistedZorOfBasisEquiv b y := by + refine Zor.ext ?_ ?_ ?_ ?_ + · change x.1.1 * y.1.1 - x.1.2 y.2.2 = + x.1.1 * y.1.1 - b.dualCoord x.1.2 ⬝ᵥ b.equivFun y.2.2 + rw [b.apply_eq_dotProduct x.1.2 y.2.2] + · change b.equivFun + (y.1.1 • x.2.2 + x.2.1 • y.2.2 + Module.crossDualOfBasis b x.1.2 y.1.2) = + y.1.1 • b.equivFun x.2.2 + x.2.1 • b.equivFun y.2.2 + + crossProduct (b.dualCoord x.1.2) (b.dualCoord y.1.2) + rw [map_add, map_add, map_smul, map_smul, Module.crossDualOfBasis_apply, + LinearEquiv.apply_symm_apply] + · change x.2.1 * y.2.1 - y.1.2 x.2.2 = + x.2.1 * y.2.1 - b.equivFun x.2.2 ⬝ᵥ b.dualCoord y.1.2 + rw [b.apply_eq_dotProduct y.1.2 x.2.2, + dotProduct_comm (m := Fin 3) (b.dualCoord y.1.2) (b.equivFun x.2.2)] + · change b.dualCoord + (x.1.1 • y.1.2 + y.2.1 • x.1.2 + Module.crossOfBasis b x.2.2 y.2.2) = + x.1.1 • b.dualCoord y.1.2 + y.2.1 • b.dualCoord x.1.2 + + crossProduct (b.equivFun x.2.2) (b.equivFun y.2.2) + rw [map_add, map_add, map_smul, map_smul, Module.crossOfBasis_apply, + LinearEquiv.apply_symm_apply] + +/-- The norm isometry from the basis-built twisted Zorn algebra to the split Zorn algebra. -/ +noncomputable def twistedZorOfBasisIsometryEquiv : + (twistedZor (Module.VectorProductPair.ofBasis b)).norm.IsometryEquiv (zor k).norm where + toLinearEquiv := twistedZorOfBasisEquiv b + map_app' := zorNorm_twistedZorOfBasisEquiv b + +/-- **The free case of `GPR 22.14`: a twisted Zorn algebra whose vector products come from a +basis is isomorphic to the split Zorn algebra `Zor(k)` of `GPR 21.18`.** -/ +theorem isomorphic_twistedZor_ofBasis : + (twistedZor (Module.VectorProductPair.ofBasis b)).Isomorphic (zor k) := + ⟨twistedZorOfBasisIsometryEquiv b, twistedZorOfBasisEquiv_one b, + twistedZorOfBasisEquiv_mul b⟩ + +/-- Any twisted Zorn algebra on a module admitting a basis of size three is split. Binet–Cauchy +forces its vector-product pair to be the pair attached to a suitably rescaled basis. -/ +theorem isomorphic_twistedZor_of_exists_basis (P : Module.VectorProductPair k M) + (b : Module.Basis (Fin 3) k M) : (twistedZor P).Isomorphic (zor k) := by + obtain ⟨b', rfl⟩ := P.exists_eq_ofBasis b + exact isomorphic_twistedZor_ofBasis b' + +/-- Any twisted Zorn algebra on a module admitting a basis of size three satisfies the +rank-eight splitness clause of `GPR 21.19(d)`. -/ +theorem isSplitOfRank_twistedZor_of_exists_basis (P : Module.VectorProductPair k M) + (b : Module.Basis (Fin 3) k M) : (twistedZor P).IsSplitOfRank 8 := + isomorphic_twistedZor_of_exists_basis P b + +/-- A basis-built twisted Zorn algebra is alternative, because its coordinate equivalence +identifies its multiplication with that of the alternative algebra `Zor(k)`. This proves the free +case of the alternativity assertion in `GPR 22.14` without any hypothesis on `2`. -/ +noncomputable instance instIsAlternativeTwistedZorOfBasis : + IsAlternative (TwistedZor (Module.VectorProductPair.ofBasis b)) where + left_alt x y := by + apply (twistedZorOfBasisEquiv b).injective + simpa only [twistedZorOfBasisEquiv_mul] using + (IsAlternative.left_alt (twistedZorOfBasisEquiv b x) (twistedZorOfBasisEquiv b y)) + right_alt x y := by + apply (twistedZorOfBasisEquiv b).injective + simpa only [twistedZorOfBasisEquiv_mul] using + (IsAlternative.right_alt (twistedZorOfBasisEquiv b x) (twistedZorOfBasisEquiv b y)) + +/-- A basis-built twisted Zorn algebra has rank eight. -/ +@[simp] theorem finrank_twistedZor_ofBasis [Nontrivial k] : + Module.finrank k (TwistedZor (Module.VectorProductPair.ofBasis b)) = 8 := + (twistedZorOfBasisEquiv b).finrank_eq.trans (finrank_zor (k := k)) + +/-- The basis-built twisted Zorn algebra satisfies the rank-eight splitness clause of +`GPR 21.19(d)`. -/ +theorem isSplitOfRank_twistedZor_ofBasis : + (twistedZor (Module.VectorProductPair.ofBasis b)).IsSplitOfRank 8 := + isomorphic_twistedZor_ofBasis b + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Zorn.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Zorn.lean new file mode 100644 index 0000000000..adaed2d84c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Zorn.lean @@ -0,0 +1,334 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import Mathlib.LinearAlgebra.CrossProduct + +/-! +# Zorn vector matrices (`GPR 21.18`) + +The **algebra of Zorn vector matrices** `Zor(k)` is the `k`-module of formal matrices + + `[ρ₁ u₂]` + `[u₁ ρ₂]`, `ρᵢ ∈ k`, `uᵢ ∈ k³`, + +with the multiplication built from the dot and cross products of `k³` (`GPR (21.18.4)`) + + `[ρ₁ u₂] [σ₁ v₂] [ ρ₁σ₁ - u₂ᵀv₁ ρ₁v₂ + σ₂u₂ + u₁ ⨯ v₁ ]` + `[u₁ ρ₂] [v₁ σ₂] = [ σ₁u₁ + ρ₂v₁ + u₂ ⨯ v₂ ρ₂σ₂ - u₁ᵀv₂ ]`, + +the norm `n = ρ₁ρ₂ + u₁ᵀu₂`, the trace `t = ρ₁ + ρ₂` and the conjugation exchanging the diagonal +and negating the off-diagonal entries. + +**This is the split octonion algebra, and it exists over every commutative ring.** That is the +point of the file: the Cayley–Dickson tower of `Composition/Octonion.lean` produces composition +algebras only when `2` is invertible — in characteristic `2` its very first rung `Cay(k, μ)` has +identically zero polar form, so its norm becomes degenerate over some extension field and is never +non-singular in the sense of `GPR 19.5` (`GPR 19.4`) — whereas `Zor(k)` is a composition +algebra of rank `8` over an arbitrary base, in every characteristic, with no unit scalars to +choose. It is therefore the first octonion algebra in this development available over, say, `𝔽₂`, +and it is the object the classification of *reduced* composition algebras (`GPR 22.15`) is stated +in terms of. + +## Coordinates + +`Zor k` is a type synonym for `(k × k³) × (k × k³)`, with `x.1 = (ρ₁, u₁)` the first column of the +matrix above and `x.2 = (ρ₂, u₂)` the second. The grouping is chosen so that the norm is literally +the pairing of `x.1` against `x.2`, which is what makes it visibly hyperbolic — the norm form of +`Zor(k)` is four hyperbolic planes, and that is the whole content of its non-singularity. + +## Main definitions + +* `ConicAlgebra.Zor k` : the underlying `k`-module of the algebra of Zorn vector matrices, with + its multiplication. +* `ConicAlgebra.zorNorm k` : the norm `ρ₁ρ₂ + u₁ᵀu₂` (`GPR (21.18.6)`). +* `ConicAlgebra.zor k` : the conic structure (`GPR 21.18`). + +## Main results + +* `ConicAlgebra.isMultiplicative_zor` : the norm permits composition, `n(xy) = n(x) n(y)`. +* `ConicAlgebra.isGPRNonsingular_zorNorm` : the norm is non-singular, because it is hyperbolic. +* `ConicAlgebra.isComposition_zor` : **`Zor(k)` is a composition algebra over every commutative + ring**, with no hypothesis on `2`. +* `ConicAlgebra.finrank_zor` : it has rank `8`, so it is an octonion algebra. +* `ConicAlgebra.instIsAlternativeZor` : it is alternative. +* `ConicAlgebra.trace_zor_apply`, `ConicAlgebra.conj_zor_apply` : `GPR (21.18.7)`, `(21.18.8)`. + +## Implementation notes + +The multiplication is *not* obtained from `GPR`'s ternary hermitian construction +`Ter(D; D³, h, Δ)`, of which `GPR 21.18` computes it to be a special case; it is taken as the +definition, and the identities `GPR 21.18` derives are proved here directly. Everything reduces to +polynomial identities in the sixteen coordinates of a pair of vector matrices, and the only two +facts about `k³` that are used are `u ⬝ᵥ (u ⨯₃ v) = 0` and the Binet–Cauchy identity +`(a ⨯₃ b) ⬝ᵥ (c ⨯₃ d) = (a ⬝ᵥ c) (b ⬝ᵥ d) - (a ⬝ᵥ d) (b ⬝ᵥ c)` — both of which `ring` supplies +after `Fin 3` is expanded. + +⚠ **No hypothesis on `2` anywhere in this file**, and none is available: the whole reason for +constructing `Zor(k)` by hand rather than as `Cay(Cay(Cay(k, 1), 1), 1)` is that the +Cayley–Dickson double `Cay(k, 1)` is *not* the split quadratic étale algebra `k × k` when `2 = 0` +— it is `k[ε]`, whose norm has a radical. Splitting the hyperbolic plane `⟨1⟩ ⊥ ⟨-1⟩` off as +`xy` needs `2` invertible, and `Zor(k)` is precisely the object that does not. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 21.18, 21.19, + 22.15. +-/ + +@[expose] public section + +universe u w + +open Matrix + +namespace ConicAlgebra + +variable (k : Type u) [CommRing k] + +/-- The `k`-module underlying the algebra of **Zorn vector matrices** `Zor(k)` (`GPR (21.18.5)`), +as a type synonym for `(k × k³) × (k × k³)`: the element `x` is the matrix + + `[x.1.1 x.2.2]` + `[x.1.2 x.2.1]` + +whose first column is `x.1 = (ρ₁, u₁)` and whose second column is `x.2 = (ρ₂, u₂)`. The synonym is +needed because the multiplication below is not the componentwise one. -/ +def Zor : Type u := (k × (Fin 3 → k)) × (k × (Fin 3 → k)) + +namespace Zor + +instance : AddCommGroup (Zor k) := + inferInstanceAs (AddCommGroup ((k × (Fin 3 → k)) × (k × (Fin 3 → k)))) + +instance : Module k (Zor k) := + inferInstanceAs (Module k ((k × (Fin 3 → k)) × (k × (Fin 3 → k)))) + +instance : Module.Finite k (Zor k) := + inferInstanceAs (Module.Finite k ((k × (Fin 3 → k)) × (k × (Fin 3 → k)))) + +instance : Module.Projective k (Zor k) := + inferInstanceAs (Module.Projective k ((k × (Fin 3 → k)) × (k × (Fin 3 → k)))) + +instance : Module.Free k (Zor k) := + inferInstanceAs (Module.Free k ((k × (Fin 3 → k)) × (k × (Fin 3 → k)))) + +variable {k} + +omit [CommRing k] in +/-- Two Zorn vector matrices agree as soon as their four entries do. -/ +theorem ext {x y : Zor k} (h₁ : x.1.1 = y.1.1) (h₂ : x.1.2 = y.1.2) (h₃ : x.2.1 = y.2.1) + (h₄ : x.2.2 = y.2.2) : x = y := + Prod.ext (Prod.ext h₁ h₂) (Prod.ext h₃ h₄) + +@[simp] theorem fst_add (x y : Zor k) : (x + y).1 = x.1 + y.1 := rfl +@[simp] theorem snd_add (x y : Zor k) : (x + y).2 = x.2 + y.2 := rfl +@[simp] theorem fst_zero : (0 : Zor k).1 = 0 := rfl +@[simp] theorem snd_zero : (0 : Zor k).2 = 0 := rfl +@[simp] theorem fst_neg (x : Zor k) : (-x).1 = -x.1 := rfl +@[simp] theorem snd_neg (x : Zor k) : (-x).2 = -x.2 := rfl +@[simp] theorem fst_sub (x y : Zor k) : (x - y).1 = x.1 - y.1 := rfl +@[simp] theorem snd_sub (x y : Zor k) : (x - y).2 = x.2 - y.2 := rfl +@[simp] theorem fst_smul (c : k) (x : Zor k) : (c • x).1 = c • x.1 := rfl +@[simp] theorem snd_smul (c : k) (x : Zor k) : (c • x).2 = c • x.2 := rfl + +variable (k) + +/-- The **multiplication of Zorn vector matrices**, `GPR (21.18.4)`. -/ +instance : Mul (Zor k) := + ⟨fun x y ↦ + (((x.1.1 * y.1.1 - x.2.2 ⬝ᵥ y.1.2, y.1.1 • x.1.2 + x.2.1 • y.1.2 + x.2.2 ⨯₃ y.2.2), + (x.2.1 * y.2.1 - x.1.2 ⬝ᵥ y.2.2, + x.1.1 • y.2.2 + y.2.1 • x.2.2 + x.1.2 ⨯₃ y.1.2)) : + (k × (Fin 3 → k)) × (k × (Fin 3 → k)))⟩ + +/-- The identity matrix `diag(1, 1)`. -/ +instance : One (Zor k) := ⟨(((1, 0), (1, 0)) : (k × (Fin 3 → k)) × (k × (Fin 3 → k)))⟩ + +variable {k} + +@[simp] theorem mul_fst_fst (x y : Zor k) : (x * y).1.1 = x.1.1 * y.1.1 - x.2.2 ⬝ᵥ y.1.2 := rfl +@[simp] theorem mul_fst_snd (x y : Zor k) : + (x * y).1.2 = y.1.1 • x.1.2 + x.2.1 • y.1.2 + x.2.2 ⨯₃ y.2.2 := rfl +@[simp] theorem mul_snd_fst (x y : Zor k) : (x * y).2.1 = x.2.1 * y.2.1 - x.1.2 ⬝ᵥ y.2.2 := rfl +@[simp] theorem mul_snd_snd (x y : Zor k) : + (x * y).2.2 = x.1.1 • y.2.2 + y.2.1 • x.2.2 + x.1.2 ⨯₃ y.1.2 := rfl +@[simp] theorem one_fst_fst : (1 : Zor k).1.1 = 1 := rfl +@[simp] theorem one_fst_snd : (1 : Zor k).1.2 = 0 := rfl +@[simp] theorem one_snd_fst : (1 : Zor k).2.1 = 1 := rfl +@[simp] theorem one_snd_snd : (1 : Zor k).2.2 = 0 := rfl + +variable (k) + +instance : NonAssocRing (Zor k) := + { (inferInstance : AddCommGroup (Zor k)), (inferInstance : Mul (Zor k)), + (inferInstance : One (Zor k)) with + left_distrib := fun x y z ↦ Zor.ext (by simp [dotProduct_add]; ring) + (by simp [smul_add, add_smul]; abel) (by simp [dotProduct_add]; ring) + (by simp [smul_add, add_smul]; abel) + right_distrib := fun x y z ↦ Zor.ext (by simp [add_dotProduct]; ring) + (by simp [smul_add, add_smul]; abel) (by simp [add_dotProduct]; ring) + (by simp [smul_add, add_smul]; abel) + zero_mul := fun x ↦ Zor.ext (by simp) (by simp) (by simp) (by simp) + mul_zero := fun x ↦ Zor.ext (by simp) (by simp) (by simp) (by simp) + one_mul := fun x ↦ Zor.ext (by simp) (by simp) (by simp) (by simp) + mul_one := fun x ↦ Zor.ext (by simp) (by simp) (by simp) (by simp) } + +instance : SMulCommClass k (Zor k) (Zor k) := + ⟨fun c x y ↦ Zor.ext (by simp [dotProduct_smul]; ring) (by simp; module) + (by simp [dotProduct_smul]; ring) (by simp; module)⟩ + +instance : IsScalarTower k (Zor k) (Zor k) := + ⟨fun c x y ↦ Zor.ext (by simp [smul_dotProduct]; ring) (by simp; module) + (by simp [smul_dotProduct]; ring) (by simp; module)⟩ + +end Zor + +/-- **`Zor(k)` has rank `8`**: it is an octonion algebra. -/ +@[simp] theorem finrank_zor [Nontrivial k] : Module.finrank k (Zor k) = 8 := by + change Module.finrank k ((k × (Fin 3 → k)) × (k × (Fin 3 → k))) = 8 + simp + +/-! ### The norm + +The norm `n(x) = ρ₁ρ₂ + u₁ᵀu₂` (`GPR (21.18.6)`) is the pairing of the two columns of the matrix +against each other, so it is built here from that pairing rather than written out as a polynomial: +this is what `QuadraticForm.isGPRNonsingular_of_basis_pairing` consumes, and it is why the norm is +hyperbolic. -/ + +/-- The **coordinate pairing** `⟪(ρ, u), (σ, v)⟫ = ρσ + uᵀv` on `k × k³`. -/ +def zorPairing : LinearMap.BilinForm k (k × (Fin 3 → k)) := + LinearMap.mk₂ k (fun m n ↦ m.1 * n.1 + m.2 ⬝ᵥ n.2) + (fun _ _ _ ↦ by simp [add_dotProduct]; ring) + (fun _ _ _ ↦ by simp [smul_dotProduct]; ring) + (fun _ _ _ ↦ by simp [dotProduct_add]; ring) + (fun _ _ _ ↦ by simp [dotProduct_smul]; ring) + +/-- The bilinear form pairing the first column of a Zorn vector matrix against its second. -/ +def zorBilin : LinearMap.BilinForm k (Zor k) := + (zorPairing k).compl₁₂ + (LinearMap.fst k (k × (Fin 3 → k)) (k × (Fin 3 → k))) + (LinearMap.snd k (k × (Fin 3 → k)) (k × (Fin 3 → k))) + +/-- The **norm of a Zorn vector matrix**, `n(x) = ρ₁ρ₂ + u₁ᵀu₂` (`GPR (21.18.6)`): the +determinant-like pairing of the two columns. -/ +def zorNorm : QuadraticForm k (Zor k) := (zorBilin k).toQuadraticMap + +variable {k} + +@[simp] theorem zorNorm_apply (x : Zor k) : zorNorm k x = x.1.1 * x.2.1 + x.1.2 ⬝ᵥ x.2.2 := rfl + +theorem polar_zorNorm (x y : Zor k) : + QuadraticMap.polar (zorNorm k) x y = + x.1.1 * y.2.1 + y.1.1 * x.2.1 + x.1.2 ⬝ᵥ y.2.2 + y.1.2 ⬝ᵥ x.2.2 := by + simp only [QuadraticMap.polar, zorNorm_apply, Zor.fst_add, Zor.snd_add, Prod.fst_add, + Prod.snd_add, add_dotProduct, dotProduct_add] + ring + +@[simp] theorem polar_zorNorm_one (x : Zor k) : + QuadraticMap.polar (zorNorm k) 1 x = x.1.1 + x.2.1 := by + simp [polar_zorNorm, add_comm] + +variable (k) + +/-- **`GPR 21.18`: the Zorn vector matrices form a conic algebra**, with norm `ρ₁ρ₂ + u₁ᵀu₂` and +trace `ρ₁ + ρ₂`. Over an arbitrary commutative ring, with no hypothesis on `2`. -/ +def zor : ConicAlgebra k (Zor k) where + norm := zorNorm k + norm_one := by simp + mul_self x := by + refine Zor.ext ?_ ?_ ?_ ?_ + · simp [dotProduct_comm x.2.2 x.1.2]; ring + · simp [add_smul] + · simp; ring + · simp [add_smul] + +variable {k} + +@[simp] theorem zor_norm : (zor k).norm = zorNorm k := rfl + +/-- **The trace of a Zorn vector matrix is the trace of the matrix**, `GPR (21.18.7)`. -/ +@[simp] theorem trace_zor_apply (x : Zor k) : (zor k).trace x = x.1.1 + x.2.1 := by + rw [ConicAlgebra.trace_apply, zor_norm, polar_zorNorm_one] + +/-- **The conjugation exchanges the diagonal entries and negates the off-diagonal ones**, +`GPR (21.18.8)`. -/ +@[simp] theorem conj_zor_apply (x : Zor k) : + (zor k).conj x = (((x.2.1, -x.1.2), (x.1.1, -x.2.2)) : + (k × (Fin 3 → k)) × (k × (Fin 3 → k))) := by + refine Zor.ext ?_ ?_ ?_ ?_ <;> simp [ConicAlgebra.conj_apply] + +/-! ### Multiplicativity of the norm + +`n(xy) = n(x) n(y)` is a polynomial identity in the sixteen coordinates; after `Fin 3` is expanded +it is exactly the Binet–Cauchy identity plus the vanishing of `u ⬝ᵥ (u ⨯₃ v)`, and `ring` finds +both. -/ + +/-- **The norm of `Zor(k)` permits composition** (`GPR 19.1` for this algebra): `n(xy) = n(x) n(y)` +over any commutative ring. -/ +theorem isMultiplicative_zor : (zor k).IsMultiplicative := by + intro x y + simp only [zor_norm, zorNorm_apply, Zor.mul_fst_fst, Zor.mul_fst_snd, Zor.mul_snd_fst, + Zor.mul_snd_snd, dotProduct, cross_apply, Fin.sum_univ_three, Pi.add_apply, Pi.smul_apply, + smul_eq_mul, Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.head_cons, Matrix.cons_val_two, + Matrix.tail_cons] + ring + +/-! ### Alternativity -/ + +/-- **`Zor(k)` is alternative.** Both alternative laws are polynomial identities in the sixteen +coordinates of two vector matrices; no regularity and no hypothesis on `2` is used, so this is +independent of `GPR 19.3`. -/ +instance : IsAlternative (Zor k) where + left_alt x y := by + refine Zor.ext ?_ (funext fun i ↦ ?_) ?_ (funext fun i ↦ ?_) + · simp [dotProduct, cross_apply, Fin.sum_univ_three]; ring + · fin_cases i <;> + (simp [dotProduct, cross_apply, Fin.sum_univ_three, vecHead, vecTail]; ring) + · simp [dotProduct, cross_apply, Fin.sum_univ_three]; ring + · fin_cases i <;> + (simp [dotProduct, cross_apply, Fin.sum_univ_three, vecHead, vecTail]; ring) + right_alt x y := by + refine Zor.ext ?_ (funext fun i ↦ ?_) ?_ (funext fun i ↦ ?_) + · simp [dotProduct, cross_apply, Fin.sum_univ_three]; ring + · fin_cases i <;> + (simp [dotProduct, cross_apply, Fin.sum_univ_three, vecHead, vecTail]; ring) + · simp [dotProduct, cross_apply, Fin.sum_univ_three]; ring + · fin_cases i <;> + (simp [dotProduct, cross_apply, Fin.sum_univ_three, vecHead, vecTail]; ring) + +/-! ### Non-singularity, and the composition algebra + +The norm pairs the two columns of the matrix against each other in the coordinates of the standard +basis of `k × k³`, so it is a sum of four hyperbolic planes; that is all +`QuadraticForm.isGPRNonsingular_of_basis_pairing` needs. -/ + +variable (k) + +/-- The standard basis of `k × k³`, indexed by `Unit ⊕ Fin 3`. -/ +noncomputable def zorColumnBasis : Module.Basis (Unit ⊕ Fin 3) k (k × (Fin 3 → k)) := + (Module.Basis.singleton Unit k).prod (Pi.basisFun k (Fin 3)) + +/-- **The norm of `Zor(k)` is non-singular** — indeed hyperbolic, being the pairing of the first +column of the matrix against the second. No hypothesis on `2`. -/ +theorem isGPRNonsingular_zorNorm : + QuadraticForm.IsGPRNonsingular.{u, u, w} (zorNorm k) := by + have h : ∀ x : Zor k, zorNorm k x = + ∑ i, (zorColumnBasis k).repr x.1 i * (zorColumnBasis k).repr x.2 i := fun x ↦ by + simp [zorColumnBasis, Fintype.sum_sum_type, dotProduct] + exact QuadraticForm.isGPRNonsingular_of_basis_pairing (zorColumnBasis k) h + +/-- **`Zor(k)` is a composition algebra over every commutative ring** (`GPR 21.18`, `21.19(d)`): +the split octonion algebra. Unlike `ConicAlgebra.isComposition_cay₈` this needs no hypothesis on +`2` and no choice of unit scalars. -/ +theorem isComposition_zor : (zor k).IsComposition.{u, u, w} where + isGPRNonsingular := isGPRNonsingular_zorNorm k + isMultiplicative := isMultiplicative_zor + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Sedenion.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Sedenion.lean new file mode 100644 index 0000000000..a50bd13de3 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Sedenion.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Examples +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankOneTwoFourEight + +/-! +# The sedenions: a conic algebra that is not a composition algebra (`GPR 19.23`) + +The fourth rung of the Cayley–Dickson tower, `Cay(𝕆, μ)` of rank `16`, is a conic algebra — the +doubling construction has no hypotheses at all — but it is not a composition algebra. This is the +example that shows the tower really does stop, rather than merely resisting the theorems that +built it. + +Three separate statements are proved, in increasing strength: + +* the sedenions are **not alternative**, the converse half of `GPR 18.14(c)` applied to the + non-associativity of `𝕆`; +* their norm is **non-singular but not multiplicative** — so the failure is in the composition law + itself, not in a degeneracy of the norm; +* **no** conic structure on a sixteen-dimensional space is a composition algebra, by the rank + dichotomy `GPR 19.18`. This last one does not look at the multiplication at all. + +## Two independent routes + +The first two statements go through alternativity: `𝕆` is not associative +(`ConicAlgebra.exists_mul_mul_ne_mul_mul_realOctonion`), so `Cay(𝕆, μ)` is not alternative +(`ConicAlgebra.not_isAlternative_cay_of_mul_mul_ne`), and over a field every composition algebra is +alternative (`GPR 19.3`). This is the route `GPR` takes. + +The third goes through the rank: `16 ∉ {1, 2, 4, 8}`. It is strictly stronger — it rules out every +conic norm on the underlying module at once, rather than the one that doubling produces — and it +needs no witness and no computation with associators. + +## Inverses without division + +Separately, the sedenions are the example of `GPR Exc. 19.29(e)`: their norm is positive definite, +so every nonzero sedenion has a two-sided inverse, yet they have explicit zero divisors and so are +not a division algebra in the sense of `GPR 8.6`. This separates `ConicAlgebra.HasTwoSidedInverses` +from `IsDivision`, and shows that the alternativity hypothesis of `GPR 13.8` cannot be dropped. + +That the norm is non-singular is what makes the second statement sharp. A conic algebra can fail to +be a composition algebra because its norm is degenerate (`GPR 19.4` in characteristic two is that +example, with an identically zero polar form); the sedenions fail for the opposite reason. Their +norm is the sixteen-fold orthogonal sum of `⟨1⟩` over `ℝ`, as non-singular as a form can be, and +what fails is `n(xy) = n(x)n(y)`. This is the converse half of `GPR Exc. 18.18` in this one +instance, obtained without proving that converse in general. + +## Main results + +* `ConicAlgebra.RealSedenion`, `ConicAlgebra.realSedenion` : the algebra and its conic structure. +* `ConicAlgebra.not_isAlternative_realSedenion` : **not alternative**. +* `ConicAlgebra.not_isMultiplicative_realSedenion` : **the norm does not permit composition**. +* `ConicAlgebra.not_isComposition_conicAlgebra_realSedenion` : no conic structure on the sedenions + is a composition algebra. +* `ConicAlgebra.IsComposition.not_cay_of_mul_mul_ne` : the general statement over a field, of which + the sedenions are the instance. +* `ConicAlgebra.posDef_realSedenion`, `ConicAlgebra.hasTwoSidedInverses_realSedenion` : the norm is + positive definite, so every nonzero sedenion has a two-sided inverse. +* `ConicAlgebra.exists_mul_eq_zero_realSedenion`, `ConicAlgebra.not_isDivision_realSedenion` : + **`GPR Exc. 19.29(e)`** — the sedenions have zero divisors, so they are not a division algebra in + the sense of `GPR 8.6`, despite their two-sided inverses. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6, 13.8, + 18.14(c), Exc. 18.18, 19.3, 19.18, 19.23, Exc. 19.29. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +/-! ### The general statement over a field -/ + +section Field + +variable {F : Type u} {B : Type v} [Field F] [NonAssocRing B] [Module F B] + [SMulCommClass F B B] [IsScalarTower F B B] [Module.Finite F B] [Module.Projective F B] + +/-- **The double of a non-associative conic algebra over a field is not a composition algebra.** + +`ConicAlgebra.not_isAlternative_cay_of_mul_mul_ne` — the converse half of `GPR 18.14(c)` — says the +double is not alternative, and over a field every composition algebra is alternative +(`GPR 19.3`, `ConicAlgebra.IsComposition.isAlternative`). No hypothesis on `μ`. -/ +theorem IsComposition.not_cay_of_mul_mul_ne (C : ConicAlgebra F B) (μ : F) {a b c : B} + (hne : a * b * c ≠ a * (b * c)) : ¬ (C.cay μ).IsComposition.{u, v, u} := fun h ↦ + not_isAlternative_cay_of_mul_mul_ne C μ hne h.isAlternative + +end Field + +/-! ### The sedenions over `ℝ` -/ + +/-- **The real sedenions**, `Cay(𝕆, -1)`: the fourth rung of the Cayley–Dickson tower over `ℝ`, +of dimension `16`. -/ +abbrev RealSedenion : Type := Cay realOctonion (-1) + +/-- The conic structure on the sedenions. Doubling needs no hypotheses, so this exists exactly as +the earlier rungs do; what fails is everything *after* `GPR 18.4`. -/ +noncomputable abbrev realSedenion : ConicAlgebra ℝ RealSedenion := realOctonion.cay (-1) + +/-- **The sedenions have dimension 16.** -/ +theorem finrank_realSedenion : Module.finrank ℝ RealSedenion = 16 := by + rw [Cay.finrank_cay, finrank_realOctonion] + +/-- **The sedenions are not alternative.** `𝕆` is not associative, and by the converse half of +`GPR 18.14(c)` that is exactly the obstruction. -/ +theorem not_isAlternative_realSedenion : ¬ IsAlternative RealSedenion := + let ⟨_, _, _, h⟩ := exists_mul_mul_ne_mul_mul_realOctonion + not_isAlternative_cay_of_mul_mul_ne realOctonion (-1) h + +/-- **The sedenion norm is non-singular.** It is `n_𝕆 ⊥ ⟨1⟩ n_𝕆`, and `GN (C.8.3)` builds +non-singularity of an orthogonal sum out of *regularity* of the first summand — which the octonion +norm has, since `2` is invertible in `ℝ`. + +This is what makes `ConicAlgebra.not_isMultiplicative_realSedenion` sharp: the sedenions are not a +composition algebra because composition fails, not because the norm degenerates. -/ +theorem isGPRNonsingular_realSedenion : + QuadraticForm.IsGPRNonsingular.{0, 0, 0} realSedenion.norm := by + let : Invertible (2 : ℝ) := invertibleOfNonzero (by norm_num) + have hreg : realOctonion.norm.IsGPRRegular := + isComposition_realOctonion.isGPRNonsingular.isGPRRegular + exact hreg.prod_isGPRNonsingular + (hreg.isGPRNonsingular.smul_of_isUnit (by norm_num : IsUnit (-(-1 : ℝ)))) + +/-- **`GPR 19.23`.** The sedenion norm does not permit composition: `n(xy) = n(x)n(y)` fails. + +Its norm is non-singular, so were it multiplicative the sedenions would be a composition algebra of +dimension `16`, which `GPR 19.18` forbids. This is the converse half of `GPR Exc. 18.18` in this +instance, obtained without proving that converse in general. -/ +theorem not_isMultiplicative_realSedenion : ¬ realSedenion.IsMultiplicative := fun hmul ↦ + not_isComposition_of_finrank_notMem realSedenion + (by rw [finrank_realSedenion]; norm_num) (by rw [finrank_realSedenion]; norm_num) + (by rw [finrank_realSedenion]; norm_num) (by rw [finrank_realSedenion]; norm_num) + ⟨isGPRNonsingular_realSedenion, hmul⟩ + +/-- **The sedenions are not a composition algebra**, for the conic structure the Cayley–Dickson +process gives them. -/ +theorem not_isComposition_realSedenion : ¬ realSedenion.IsComposition.{0, 0, 0} := fun h ↦ + not_isMultiplicative_realSedenion h.isMultiplicative + +/-- **No conic structure on the sedenions is a composition algebra.** The rank dichotomy +`GPR 19.18` rules out dimension `16` outright, for every choice of conic norm at once — this looks +at the underlying module only, never at the multiplication. -/ +theorem not_isComposition_conicAlgebra_realSedenion (C : ConicAlgebra ℝ RealSedenion) : + ¬ C.IsComposition.{0, 0, 0} := + not_isComposition_of_finrank_notMem C + (by rw [finrank_realSedenion]; norm_num) (by rw [finrank_realSedenion]; norm_num) + (by rw [finrank_realSedenion]; norm_num) (by rw [finrank_realSedenion]; norm_num) + +/-! ### `GPR Exc. 19.29(e)`: inverses without division + +The sedenion norm is positive definite, so every nonzero sedenion `x` has the two-sided inverse +`n(x)⁻¹ (conj x)`; yet the sedenions have zero divisors, so they are not a division algebra in the +sense of `GPR 8.6`. This is the example separating `ConicAlgebra.HasTwoSidedInverses` from +`IsDivision`, and it is why `GPR 13.8` needs alternativity. + +The zero divisors are explicit. Write `e₀, …, e₁₅` for the coordinate basis of +`Cay(Cay(Cay(Cay(ℝ, -1), -1), -1), -1)`, numbering the two components `u, v` of `u + v j` at each +level as the lower and upper half; then `(e₄ + e₉)(e₇ + e₁₀) = 0`. -/ + +/-- **The norm of the real sedenions is positive definite** — the sum of sixteen squares. Doubling +at a negative scalar preserves positive definiteness (`ConicAlgebra.PosDef.cay`). -/ +theorem posDef_realSedenion : realSedenion.norm.PosDef := + PosDef.cay realOctonion (by norm_num) posDef_realOctonion + +/-- **Every nonzero sedenion has a two-sided inverse**, `n(x)⁻¹ (conj x)`, since the norm is +anisotropic. -/ +theorem hasTwoSidedInverses_realSedenion : realSedenion.HasTwoSidedInverses := + realSedenion.hasTwoSidedInverses_of_anisotropic posDef_realSedenion.anisotropic + +/-- **The real sedenions have zero divisors**: `(e₄ + e₉)(e₇ + e₁₀) = 0`, in the coordinates +described above. The product is checked coordinate by coordinate. -/ +theorem exists_mul_eq_zero_realSedenion : + ∃ x y : RealSedenion, x ≠ 0 ∧ y ≠ 0 ∧ x * y = 0 := by + refine ⟨Cay.mk (Cay.mk 0 (Cay.mk (Cay.mk 1 0) (Cay.mk 0 0))) + (Cay.mk (Cay.mk (Cay.mk 0 1) (Cay.mk 0 0)) 0), + Cay.mk (Cay.mk 0 (Cay.mk (Cay.mk 0 0) (Cay.mk 0 1))) + (Cay.mk (Cay.mk (Cay.mk 0 0) (Cay.mk 1 0)) 0), fun h ↦ ?_, fun h ↦ ?_, ?_⟩ + · have := congrArg (fun z : RealSedenion ↦ z.1.2.1.1) h + simp only [Cay.fst_mk, Cay.snd_mk, Cay.fst_zero, Cay.snd_zero] at this + exact one_ne_zero this + · have := congrArg (fun z : RealSedenion ↦ z.1.2.2.2) h + simp only [Cay.fst_mk, Cay.snd_mk, Cay.fst_zero, Cay.snd_zero] at this + exact one_ne_zero this + · refine Cay.ext ?_ ?_ <;> refine Cay.ext ?_ ?_ <;> refine Cay.ext ?_ ?_ <;> + refine Cay.ext ?_ ?_ <;> + simp only [Cay.fst_mul, Cay.snd_mul, Cay.fst_mk, Cay.snd_mk, cay_conj_mk, + baseRing_conj_apply, Cay.fst_add, Cay.snd_add, Cay.fst_smul, Cay.snd_smul, Cay.fst_neg, + Cay.snd_neg, Cay.fst_zero, Cay.snd_zero, mul_zero, zero_mul, add_zero, zero_add, + neg_zero, smul_zero, map_zero] <;> + norm_num + +/-- **`GPR Exc. 19.29(e)`: the real sedenions are not a division algebra** in the sense of +`GPR 8.6`, although their norm is anisotropic and every nonzero sedenion has a two-sided inverse +(`ConicAlgebra.hasTwoSidedInverses_realSedenion`). So `HasTwoSidedInverses` is strictly weaker than +`IsDivision`, and the alternativity hypothesis of `GPR 13.8` +(`ConicAlgebra.isDivision_iff_hasTwoSidedInverses`) cannot be dropped. -/ +theorem not_isDivision_realSedenion : ¬ IsDivision RealSedenion := + let ⟨_, _, hx, hy, hxy⟩ := exists_mul_eq_zero_realSedenion + not_isDivision_of_mul_eq_zero hx hy hxy + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean new file mode 100644 index 0000000000..a2a79c7911 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean @@ -0,0 +1,544 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Composition.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra + +/-! +# The Cayley–Dickson tower exhausts a composition algebra (`GPR 19.17`) + +Over an **LG ring**, a composition algebra `C` of constant rank `r > 1` is obtained from a +rank-two composition algebra by iterated Cayley–Dickson doubling. At every noninitial rung there +are a unital subalgebra `B` with regular restricted norm, of constant rank `r / 2`, and a +`v ⊥ B` with `n(v) ∈ kˣ`, such that + + `Cay(B, -n(v)) → C`, `u + wj ↦ u + wv`, + +is **bijective**, unital, multiplicative and an isometry. `B` is then again a composition algebra, +of half the rank, so the statement applies to it in turn and the whole tower descends to the +rank-two subalgebra of `GPR 19.16(b)`. If `2` is a unit, the rank-one scalar subalgebra may be +used as the initial rung instead. These are the two clauses of `GPR 19.17`. + +## The three ingredients, and where each comes from + +1. **Start** (`GPR 19.16(b)`, `Composition/RankTwoSubalgebra.lean`): rank `> 1` produces a regular + rank-two subalgebra `k[u]`. The tower starts here and not at `k · 1`, whose restricted norm + `⟨1⟩` is regular only when `2 ∈ kˣ`; under that extra hypothesis the tower starts at `k`. +2. **Step** (`GPR 19.16(a)`, `Composition/Doubling.lean`): a regular subalgebra whose orthogonal + complement has full support is doubled inside `C`. +3. **Regularity of the new rung** (`GPR 19.11`, `Composition/RankDichotomy.lean`): the image is a + composition algebra of constant rank `2s`, and `2s ≠ 1` because it is even, so its norm is + regular and step 2 applies again. Without this the induction could not feed its own output back + in — regularity of `q₁ ⊥ q₂` does not follow from regularity of `q₁`, only non-singularity + does (`GN (C.8.3)`). + +## The rank bookkeeping + +This is what the file supplies, and it is what "`C` is exhausted" turns into: + +* `ConicAlgebra.rankAtStalk_cay` : the rank doubles, pointwise on `Spec k` — the projective + version of `ConicAlgebra.Cay.finrank_cay`, which needs a basis. +* `ConicAlgebra.rankAtStalk_add_polarOrthogonal` : a regular subalgebra is a direct summand, so + `rk C = rk B + rk Bᗮ`. Its two consequences are the two ends of the induction — + `ConicAlgebra.rankAtStalk_le_of_isGPRRegular` bounds each rung by `r`, so doubling terminates, + and `ConicAlgebra.mem_of_isGPRRegular_of_rankAtStalk_eq` says a regular subalgebra of full rank + is everything, which is what turns the last doubling into a *surjection*. +* `ConicAlgebra.hasFullSupport_polarOrthogonal_of_rankAtStalk_lt` : constant rank `s < r` gives + the full-support hypothesis that `GPR 19.16(a)` consumes, via + `Module.finrank_baseChange_of_rankAtStalk_eq`. + +⚠ `[Nontrivial k]` is a genuine hypothesis of the induction, not decoration: over the zero ring +`Spec k` is empty, every rank statement is vacuous, and the bound `2s ≤ r` that makes the tower +terminate cannot be read off from any prime. (The conclusion still holds there, since every module +is trivial, but by a different argument.) + +⚠ The subalgebra produced at each step is the **image** of `ConicAlgebra.cayToAlgebra`, packaged +existentially by `ConicAlgebra.exists_subalgebra_equiv_cay` rather than as a definition: its +closure under multiplication needs the orthogonality and invertibility hypotheses, and +overview §2 keeps hypotheses off definitions. + +## Main results + +* `ConicAlgebra.IsComposition.rank_eq_two_or_exists_bijective_cayToAlgebra` : the full + rank-`> 1` clause of **`GPR 19.17`**, with rank two as the initial rung. +* `ConicAlgebra.IsComposition.exists_bijective_cayToAlgebra_of_invertible_two` : the clause of + **`GPR 19.17`** starting the tower at the base ring when `2` is invertible. +* `ConicAlgebra.IsComposition.exists_bijective_cayToAlgebra` : the noninitial doubling step. +* `ConicAlgebra.IsComposition.exists_isGPRRegular_rankAtStalk_two_mul` : one rung of the tower. +* `ConicAlgebra.exists_subalgebra_equiv_cay` : the image `B + Bv` as a unital subalgebra. +* `ConicAlgebra.isGPRRegular_restrict_and_rankAtStalk_of_equiv_cay` : every internal doubled image + of a regular constant-rank subalgebra is regular and has twice the rank. +* `ConicAlgebra.mem_of_isGPRRegular_of_rankAtStalk_eq` : the exhaustion criterion. +* `ConicAlgebra.rankAtStalk_cay`, `ConicAlgebra.rankAtStalk_add_polarOrthogonal` : the rank + bookkeeping. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.11, 19.16, + 19.17. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European J. Math. **11** (2025), art. 42, + C.8.3. +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) +open scoped TensorProduct + +namespace Module + +variable {k : Type u} [CommRing k] {M : Type v} [AddCommGroup M] [Module k M] + +/-- **Constant rank is dimension after base change to any field.** `Module.rankAtStalk` is +computed at primes of `k`; base change to a field `F ∈ k`-alg reads it off at the prime `⊥` of +`F`, where the module is free. -/ +theorem finrank_baseChange_of_rankAtStalk_eq [Module.Finite k M] [Module.Projective k M] {r : ℕ} + (hr : Module.rankAtStalk (R := k) M = fun _ ↦ r) (F : Type u) [Field F] [Algebra k F] : + Module.finrank F (F ⊗[k] M) = r := by + have hbase := Module.rankAtStalk_baseChange (R := k) (M := M) (S := F) ⊥ + rwa [Module.rankAtStalk_eq_finrank_of_free, hr] at hbase + +end Module + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] + {C : ConicAlgebra k A} {B : NonAssocSubalgebra k A} + +/-- A unital subalgebra and its underlying submodule are the same module. The two coercions are +definitionally equal but not syntactically so, and `Module.rankAtStalk` statements have to be +moved between them: the orthogonal-complement API is stated for submodules, the conic API for +subalgebras. -/ +def toSubmoduleEquiv (B : NonAssocSubalgebra k A) : + B.toNonUnitalSubalgebra.toSubmodule ≃ₗ[k] B where + toFun x := ⟨(x : A), x.2⟩ + invFun x := ⟨(x : A), x.2⟩ + map_add' _ _ := rfl + map_smul' _ _ := rfl + left_inv _ := rfl + right_inv _ := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +/-- `Module.rankAtStalk` does not see the difference between a subalgebra and its submodule. -/ +theorem rankAtStalk_toSubmodule (B : NonAssocSubalgebra k A) : + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = + Module.rankAtStalk (R := k) B := + Module.rankAtStalk_eq_of_equiv (toSubmoduleEquiv B) + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **The rank criterion for properness.** A regular subalgebra whose constant rank is smaller +than the constant rank of the ambient algebra has a complement of full support, which is the +hypothesis `GPR 19.16(a)` consumes. -/ +theorem hasFullSupport_polarOrthogonal_of_rankAtStalk_lt + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) {r s : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ s) + (hlt : s < r) : + Module.HasFullSupport k + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule) := + haveI := QuadraticForm.finite_of_comp_isGPRRegular (Q := C.norm) hreg + haveI := QuadraticForm.projective_of_comp_isGPRRegular (Q := C.norm) hreg + hasFullSupport_polarOrthogonal_of_finrank_lt hreg fun F _ _ ↦ by + rw [Module.finrank_baseChange_of_rankAtStalk_eq hB F, + Module.finrank_baseChange_of_rankAtStalk_eq hA F] + exact hlt + +/-! ### The image of the doubling map as a subalgebra -/ + +variable {v : A} + +/-- **`B + Bv` is a unital subalgebra, isomorphic to `Cay(B, -n(v))`.** + +The image of `ConicAlgebra.cayToAlgebra` is closed under multiplication precisely because that map +is multiplicative (`GPR 18.1`), and it contains `1` because the map is unital. Packaged with the +linear equivalence onto it, which is what carries the norm, the rank and the composition structure +across. + +Existential rather than a definition: the subalgebra structure needs the orthogonality and +invertibility hypotheses, and overview §2 keeps hypotheses off definitions. -/ +theorem exists_subalgebra_equiv_cay [IsAlternative A] (hBv : ∀ b ∈ B, polar C.norm b v = 0) + (hu : IsUnit (C.norm v)) (hinj : Function.Injective (cayToAlgebra C B v)) : + ∃ (D : NonAssocSubalgebra k A) (e : Cay (C.restrict B) (-C.norm v) ≃ₗ[k] D), + ∀ p, ((e p : A)) = cayToAlgebra C B v p := by + have hconj := C.conjIsInvolution_of_projective + set S : Set A := Set.range (cayToAlgebra C B v) with hS + have hadd : ∀ x ∈ S, ∀ y ∈ S, x + y ∈ S := by + rintro _ ⟨p, rfl⟩ _ ⟨q, rfl⟩ + exact ⟨p + q, map_add _ _ _⟩ + have hsmul : ∀ (c : k), ∀ x ∈ S, c • x ∈ S := by + rintro c _ ⟨p, rfl⟩ + exact ⟨c • p, map_smul _ _ _⟩ + have hmul : ∀ x ∈ S, ∀ y ∈ S, x * y ∈ S := by + rintro _ ⟨p, rfl⟩ _ ⟨q, rfl⟩ + exact ⟨p * q, cayToAlgebra_mul hBv hconj hu p q⟩ + let D : NonAssocSubalgebra k A := + { carrier := S + add_mem' := fun ha hb ↦ hadd _ ha _ hb + zero_mem' := ⟨0, map_zero _⟩ + mul_mem' := fun ha hb ↦ hmul _ ha _ hb + smul_mem' := fun c _ ha ↦ hsmul c _ ha + one_mem := ⟨1, cayToAlgebra_one⟩ } + let g : Cay (C.restrict B) (-C.norm v) →ₗ[k] D := + { toFun := fun p ↦ ⟨cayToAlgebra C B v p, ⟨p, rfl⟩⟩ + map_add' := fun p q ↦ Subtype.ext (map_add _ _ _) + map_smul' := fun c p ↦ Subtype.ext (map_smul _ _ _) } + refine ⟨D, LinearEquiv.ofBijective g ⟨?_, ?_⟩, fun _ ↦ rfl⟩ + · exact fun p q hpq ↦ hinj (congrArg Subtype.val hpq) + · rintro ⟨_, p, rfl⟩ + exact ⟨p, rfl⟩ + +/-! ### The rank doubles + +`ConicAlgebra.Cay.finrank_cay` says this for free modules; the tower needs it pointwise on +`Spec k`, since that is the form in which the rank of a subalgebra is controlled. -/ + +/-- **The rank of the double is twice the rank.** The pointwise form of +`ConicAlgebra.Cay.finrank_cay`, with no freeness hypothesis. -/ +theorem rankAtStalk_cay {B' : Type v} [NonAssocRing B'] [Module k B'] [Module.Finite k B'] + [Module.Projective k B'] (C' : ConicAlgebra k B') (μ : k) : + Module.rankAtStalk (R := k) (Cay C' μ) = 2 * Module.rankAtStalk (R := k) B' := by + have e : Cay C' μ ≃ₗ[k] B' × B' := + { toFun := fun p ↦ (p.1, p.2) + invFun := fun p ↦ ((p.1, p.2) : Cay C' μ) + map_add' := fun _ _ ↦ rfl + map_smul' := fun _ _ ↦ rfl + left_inv := fun _ ↦ rfl + right_inv := fun _ ↦ rfl } + rw [Module.rankAtStalk_eq_of_equiv e, Module.rankAtStalk_prod] + ext p + simp [two_mul] + +/-- **Regularity and rank of an internal doubled image.** Suppose `D` is the image of the internal +doubling map on a regular subalgebra `B` of constant rank `s`. Then the restricted norm on `D` is +regular and `D` has constant rank `2s`. + +The norm pulled back to the external double is the Cayley–Dickson norm. It is non-singular by +`GN (C.8.3)`, so the image is a composition algebra; its even rank then rules out the exceptional +rank-one case in `GPR 19.11`. -/ +theorem isGPRRegular_restrict_and_rankAtStalk_of_equiv_cay + (h : C.IsComposition.{u, v, u}) + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) + (hBv : ∀ b ∈ B, polar C.norm b v = 0) (hu : IsUnit (C.norm v)) + (D : NonAssocSubalgebra k A) (e : Cay (C.restrict B) (-C.norm v) ≃ₗ[k] D) + (he : ∀ p, ((e p : D) : A) = cayToAlgebra C B v p) {s : ℕ} + (hB : Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ s) : + QuadraticForm.IsGPRRegular (C.restrict D).norm ∧ + Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ 2 * s := by + let : Module.Finite k B := by + have := QuadraticForm.finite_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Finite.equiv (toSubmoduleEquiv B) + let : Module.Projective k B := by + have := QuadraticForm.projective_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Projective.of_equiv (toSubmoduleEquiv B) + have hpull : (C.restrict D).norm.comp e.toLinearMap = + ((C.restrict B).cay (-C.norm v)).norm := by + refine QuadraticMap.ext fun p ↦ ?_ + rw [QuadraticMap.comp_apply, LinearEquiv.coe_coe] + change C.norm ((e p : D) : A) = _ + rw [he p, norm_cayToAlgebra hBv h.isMultiplicative] + let : Module.Finite k D := Module.Finite.equiv e + let : Module.Projective k D := Module.Projective.of_equiv e + have hcay : QuadraticForm.IsGPRNonsingular.{u, v, u} + ((C.restrict B).cay (-C.norm v)).norm := + hreg.prod_isGPRNonsingular + (hreg.isGPRNonsingular.smul_of_isUnit (by rwa [neg_neg] : IsUnit (-(-C.norm v)))) + have hDns : QuadraticForm.IsGPRNonsingular.{u, v, u} (C.restrict D).norm := by + have hcomp := hcay.comp_linearEquiv e.symm + have heq : ((C.restrict B).cay (-C.norm v)).norm.comp e.symm.toLinearMap = + (C.restrict D).norm := by + rw [← hpull] + refine QuadraticMap.ext fun d ↦ ?_ + simp + rwa [heq] at hcomp + have hDcomp : (C.restrict D).IsComposition.{u, v, u} := + ⟨hDns, h.isMultiplicative.restrict⟩ + have hDrank : Module.rankAtStalk (R := k) D = fun _ ↦ 2 * s := by + rw [← Module.rankAtStalk_eq_of_equiv e, rankAtStalk_cay, ← rankAtStalk_toSubmodule, hB] + rfl + have hDrank' : Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = + fun _ ↦ 2 * s := by + rw [rankAtStalk_toSubmodule] + exact hDrank + exact ⟨hDcomp.isGPRRegular_of_rankAtStalk_ne_one hDrank (by omega), hDrank'⟩ + +/-! ### A regular subalgebra of full rank is everything -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **The ranks add up.** A subalgebra with regular restricted norm is a direct summand — that is +`QuadraticForm.orthogonalDecomposition` — so its rank and the rank of its orthogonal complement +add up to the rank of the ambient algebra, pointwise on `Spec k`. -/ +theorem rankAtStalk_add_polarOrthogonal + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) : + Module.rankAtStalk (R := k) A = + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule + + Module.rankAtStalk (R := k) + (C.norm.polarOrthogonal B.toNonUnitalSubalgebra.toSubmodule) := by + have := QuadraticForm.finite_of_comp_isGPRRegular (Q := C.norm) hreg + have := QuadraticForm.projective_of_comp_isGPRRegular (Q := C.norm) hreg + have := QuadraticForm.finite_polarOrthogonal (Q := C.norm) hreg + have := QuadraticForm.projective_polarOrthogonal (Q := C.norm) hreg + have h := Module.rankAtStalk_eq_of_equiv + (QuadraticForm.orthogonalDecomposition (Q := C.norm) + (N := B.toNonUnitalSubalgebra.toSubmodule) hreg) + rw [Module.rankAtStalk_prod] at h + exact h.symm + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- A subalgebra with regular restricted norm has rank at most that of the ambient algebra. This +is what bounds the tower: each rung doubles the rank, and no rung can outgrow `C`. -/ +theorem rankAtStalk_le_of_isGPRRegular + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) (p : PrimeSpectrum k) : + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule p ≤ + Module.rankAtStalk (R := k) A p := by + have h := congrFun (rankAtStalk_add_polarOrthogonal hreg) p + simp only [Pi.add_apply] at h + omega + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **The exhaustion criterion.** A subalgebra whose restricted norm is regular is a direct +summand, so if its rank agrees with the rank of the ambient algebra everywhere on `Spec k`, the +complement has rank zero and hence vanishes: the subalgebra is the whole algebra. + +This is the rank bookkeeping that turns "`C` is exhausted" into a statement about `Bᗮ`. -/ +theorem mem_of_isGPRRegular_of_rankAtStalk_eq + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ r) + (x : A) : x ∈ B := by + have htop := QuadraticForm.eq_top_of_isGPRRegular_of_rankAtStalk_eq + (Q := C.norm) (N := B.toNonUnitalSubalgebra.toSubmodule) hreg hA hB + have hx : x ∈ B.toNonUnitalSubalgebra.toSubmodule := htop ▸ Submodule.mem_top + exact hx + +/-! ### One rung of the tower -/ + +/-- **The doubling step.** Over an LG ring, a regular subalgebra of a composition algebra whose +constant rank `s` is smaller than the constant rank `r` of the ambient algebra is contained in a +regular subalgebra of constant rank `2s` — the image of `Cay(B, -n(v))` — and when `2s = r` that +image is the whole algebra. + +Regularity of the new subalgebra is *not* proved from regularity of the doubled quadratic form, +which would need `q₁ ⊥ q₂` regular from `q₁` regular. It comes from `GPR 19.11` +(`ConicAlgebra.IsComposition.isGPRRegular_of_rankAtStalk_ne_one`): the image is a composition +algebra of constant rank `2s`, and `2s ≠ 1` because it is even. This is the step that `GPR 19.11` +unblocks, and it is what lets the induction feed its own output back in. -/ +theorem IsComposition.exists_isGPRRegular_rankAtStalk_two_mul (hLG : IsLGRing k) + (h : C.IsComposition.{u, v, u}) + (hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm) {r s : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) + (hB : Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ s) + (hlt : s < r) : + ∃ (D : NonAssocSubalgebra k A) (v : A), + IsUnit (C.norm v) ∧ (∀ b ∈ B, polar C.norm b v = 0) ∧ + QuadraticForm.IsGPRRegular (C.restrict D).norm ∧ + Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ 2 * s) ∧ + (2 * s = r → Function.Bijective (cayToAlgebra C B v)) := by + let : IsAlternative A := h.isAlternative_general + have : Module.Finite k B := by + have := QuadraticForm.finite_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Finite.equiv (toSubmoduleEquiv B) + have : Module.Projective k B := by + have := QuadraticForm.projective_of_comp_isGPRRegular (Q := C.norm) hreg + exact Module.Projective.of_equiv (toSubmoduleEquiv B) + obtain ⟨v, hu, hBv, hinj, -, -⟩ := h.exists_cayToAlgebra hLG hreg + (hasFullSupport_polarOrthogonal_of_rankAtStalk_lt hreg hA hB hlt) + obtain ⟨D, e, he⟩ := exists_subalgebra_equiv_cay hBv hu hinj + -- The norm of `D`, pulled back along `e`, is the Cayley–Dickson norm. + have hpull : (C.restrict D).norm.comp e.toLinearMap = ((C.restrict B).cay (-C.norm v)).norm := by + refine QuadraticMap.ext fun p ↦ ?_ + rw [QuadraticMap.comp_apply, LinearEquiv.coe_coe] + change C.norm ((e p : A)) = _ + rw [he p, norm_cayToAlgebra hBv h.isMultiplicative] + have : Module.Finite k D := Module.Finite.equiv e + have : Module.Projective k D := Module.Projective.of_equiv e + -- `D` is a composition algebra: `GN (C.8.3)` for the norm, restriction for multiplicativity. + have hcay : QuadraticForm.IsGPRNonsingular.{u, v, u} + ((C.restrict B).cay (-C.norm v)).norm := + hreg.prod_isGPRNonsingular + (hreg.isGPRNonsingular.smul_of_isUnit (by rwa [neg_neg] : IsUnit (-(-C.norm v)))) + have hDns : QuadraticForm.IsGPRNonsingular.{u, v, u} (C.restrict D).norm := by + have hcomp := hcay.comp_linearEquiv e.symm + have heq : ((C.restrict B).cay (-C.norm v)).norm.comp e.symm.toLinearMap = + (C.restrict D).norm := by + rw [← hpull] + refine QuadraticMap.ext fun d ↦ ?_ + simp + rwa [heq] at hcomp + have hDcomp : (C.restrict D).IsComposition.{u, v, u} := ⟨hDns, h.isMultiplicative.restrict⟩ + -- The rank doubles. + have hDrank : Module.rankAtStalk (R := k) D = fun _ ↦ 2 * s := by + rw [← Module.rankAtStalk_eq_of_equiv e, rankAtStalk_cay, ← rankAtStalk_toSubmodule, hB] + rfl + have hDrank' : Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = + fun _ ↦ 2 * s := by + rw [rankAtStalk_toSubmodule] + exact hDrank + refine ⟨D, v, hu, hBv, hDcomp.isGPRRegular_of_rankAtStalk_ne_one hDrank (by omega), hDrank', + fun hfull ↦ ⟨hinj, fun x ↦ ?_⟩⟩ + have hmem : x ∈ D := mem_of_isGPRRegular_of_rankAtStalk_eq + (hDcomp.isGPRRegular_of_rankAtStalk_ne_one hDrank (by omega)) hA (hfull ▸ hDrank') x + exact ⟨e.symm ⟨x, hmem⟩, by rw [← he, e.apply_symm_apply]⟩ + +/-! ### Iterating: `GPR 19.17` -/ + +/-- The induction behind `GPR 19.17`, with an explicit fuel parameter `n` bounding `r - s`. + +Each pass either finishes — when the double already fills up `C` — or replaces `B` by a regular +subalgebra of twice the rank, which is still at most `r` because a regular subalgebra is a direct +summand (`ConicAlgebra.rankAtStalk_le_of_isGPRRegular`). Since `s ≥ 1`, doubling strictly +decreases `r - s`, so the fuel suffices. -/ +private theorem IsComposition.exists_bijective_cayToAlgebra_aux [Nontrivial k] (hLG : IsLGRing k) + (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) : + ∀ (n s : ℕ) (B : NonAssocSubalgebra k A), + QuadraticForm.IsGPRRegular (C.restrict B).norm → + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) → + 0 < s → s < r → r - s ≤ n → + ∃ (D : NonAssocSubalgebra k A) (v : A) (t : ℕ), + 2 * t = r ∧ + Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ t) ∧ + IsUnit (C.norm v) ∧ (∀ b ∈ D, polar C.norm b v = 0) ∧ + QuadraticForm.IsGPRRegular (C.restrict D).norm ∧ + Function.Bijective (cayToAlgebra C D v) := by + intro n + induction n with + | zero => intro s _ _ _ _ hsr hfuel; omega + | succ n ih => + intro s B hreg hs hs0 hsr hfuel + obtain ⟨D, v, hu, hBv, hDreg, hDrank, hbij⟩ := + h.exists_isGPRRegular_rankAtStalk_two_mul hLG hreg hA hs hsr + by_cases hfull : 2 * s = r + · exact ⟨B, v, s, hfull, hs, hu, hBv, hreg, hbij hfull⟩ + · have hle : 2 * s ≤ r := by + have := rankAtStalk_le_of_isGPRRegular hDreg (Classical.arbitrary (PrimeSpectrum k)) + rwa [hDrank, hA] at this + exact ih (2 * s) D hDreg hDrank (by omega) (by omega) (by omega) + +/-- **`GPR 19.17`: a composition algebra of rank greater than two arises by the Cayley–Dickson +process.** Over an LG ring, a composition algebra of constant rank `r > 2` is the double of one of +its own subalgebras: there are a subalgebra `B` with regular restricted norm and a `v ∈ Bᗮ` with +`n(v) ∈ kˣ` for which + + `Cay(B, -n(v)) → C`, `u + wj ↦ u + wv`, + +is bijective. It is automatically unital, multiplicative and an isometry +(`ConicAlgebra.cayToAlgebra_one`, `ConicAlgebra.cayToAlgebra_mul`, +`ConicAlgebra.norm_cayToAlgebra`), so `C` *is* `Cay(B, -n(v))`. Since `B` is again a composition +algebra — of half the rank, by `ConicAlgebra.rankAtStalk_cay` — iterating the statement descends +the whole tower. + +The tower starts at the rank-two subalgebra of `GPR 19.16(b)` and not at `k · 1`, whose restricted +norm `⟨1⟩` is regular only when `2 ∈ kˣ`. That is why the hypothesis is `2 < r` rather than +`1 < r`: rank two is the base case of the process, not a step in it. -/ +theorem IsComposition.exists_bijective_cayToAlgebra [Nontrivial k] (hLG : IsLGRing k) + (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : 2 < r) : + ∃ (B : NonAssocSubalgebra k A) (v : A) (s : ℕ), + 2 * s = r ∧ + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) ∧ + IsUnit (C.norm v) ∧ + QuadraticForm.IsGPRRegular (C.restrict B).norm ∧ + Function.Bijective (cayToAlgebra C B v) ∧ + cayToAlgebra C B v 1 = 1 ∧ + (∀ p q, cayToAlgebra C B v (p * q) = cayToAlgebra C B v p * cayToAlgebra C B v q) ∧ + (∀ p, C.norm (cayToAlgebra C B v p) = ((C.restrict B).cay (-C.norm v)).norm p) := by + let : IsAlternative A := h.isAlternative_general + obtain ⟨u, hu⟩ := h.exists_isRegularRankTwoComposition_of_rankAtStalk hLG (by + intro 𝔭 + simp only [hA] + omega) + have hdisc : IsUnit (C.elementDiscriminant u) := + (C.isRegularRankTwoComposition_iff_isUnit_discriminant u).mp hu + have hreg : QuadraticForm.IsGPRRegular (C.restrict (C.adjoinElement u)).norm := + C.normAdjoinElement_isGPRRegular hdisc + have hrank : Module.rankAtStalk (R := k) + (C.adjoinElement u).toNonUnitalSubalgebra.toSubmodule = fun _ ↦ 2 := by + rw [rankAtStalk_toSubmodule, ← Module.rankAtStalk_eq_of_equiv (C.quadraticSpanEquiv hdisc), + Module.rankAtStalk_prod, Module.rankAtStalk_self] + rfl + obtain ⟨B, v, s, hs2, hsrank, hunit, hBv, hBreg, hbij⟩ := + h.exists_bijective_cayToAlgebra_aux hLG hA r 2 (C.adjoinElement u) hreg hrank + (by omega) hr (by omega) + exact ⟨B, v, s, hs2, hsrank, hunit, hBreg, hbij, cayToAlgebra_one, + cayToAlgebra_mul hBv C.conjIsInvolution_of_projective hunit, + norm_cayToAlgebra hBv h.isMultiplicative⟩ + +/-- **Full `GPR 19.17`, starting in rank two.** A composition algebra of constant rank greater +than one over an LG ring is either already of rank two, or is a Cayley–Dickson double of a regular +composition subalgebra of half its rank. Reapplying the second alternative to that subalgebra +gives the finite tower starting in rank two asserted by the corollary. -/ +theorem IsComposition.rank_eq_two_or_exists_bijective_cayToAlgebra [Nontrivial k] + (hLG : IsLGRing k) (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : 1 < r) : + r = 2 ∨ + ∃ (B : NonAssocSubalgebra k A) (v : A) (s : ℕ), + 2 * s = r ∧ + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) ∧ + IsUnit (C.norm v) ∧ + QuadraticForm.IsGPRRegular (C.restrict B).norm ∧ + Function.Bijective (cayToAlgebra C B v) ∧ + cayToAlgebra C B v 1 = 1 ∧ + (∀ p q, cayToAlgebra C B v (p * q) = + cayToAlgebra C B v p * cayToAlgebra C B v q) ∧ + ∀ p, C.norm (cayToAlgebra C B v p) = + ((C.restrict B).cay (-C.norm v)).norm p := by + by_cases h2 : r = 2 + · exact Or.inl h2 + · exact Or.inr (h.exists_bijective_cayToAlgebra hLG hA (by omega)) + +/-- The scalar subalgebra `k · 1 = k[0]`, as a free rank-one module. -/ +noncomputable def scalarAdjoinZeroLinearEquiv (C : ConicAlgebra k A) : + k ≃ₗ[k] C.adjoinElement 0 where + toFun r := ⟨r • (1 : A), (C.mem_adjoinElement_iff 0 _).mpr ⟨r, 0, by simp⟩⟩ + invFun x := C.unitForm x + map_add' r s := Subtype.ext (add_smul r s (1 : A)) + map_smul' r s := Subtype.ext (smul_smul r s (1 : A)).symm + left_inv r := by simp + right_inv x := by + apply Subtype.ext + obtain ⟨r, s, hx⟩ := (C.mem_adjoinElement_iff 0 x).mp x.2 + change C.unitForm x • (1 : A) = x + rw [← hx] + simp [C.unitForm_one] + +/-- **The second clause of `GPR 19.17`.** If `2` is invertible, the Cayley–Dickson tower may be +started at the base ring itself. The scalar subalgebra has rank one and its norm is the regular +form `⟨1⟩`; the same doubling induction as above then reaches the ambient algebra. -/ +theorem IsComposition.exists_bijective_cayToAlgebra_of_invertible_two [Nontrivial k] + [Invertible (2 : k)] (hLG : IsLGRing k) (h : C.IsComposition.{u, v, u}) {r : ℕ} + (hA : Module.rankAtStalk (R := k) A = fun _ ↦ r) (hr : 1 < r) : + ∃ (B : NonAssocSubalgebra k A) (v : A) (s : ℕ), + 2 * s = r ∧ + Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = (fun _ ↦ s) ∧ + IsUnit (C.norm v) ∧ + QuadraticForm.IsGPRRegular (C.restrict B).norm ∧ + Function.Bijective (cayToAlgebra C B v) := by + let B := C.adjoinElement 0 + let e := scalarAdjoinZeroLinearEquiv C + have hB : Module.rankAtStalk (R := k) B.toNonUnitalSubalgebra.toSubmodule = fun _ ↦ 1 := by + rw [rankAtStalk_toSubmodule, ← Module.rankAtStalk_eq_of_equiv e, + Module.rankAtStalk_self] + rfl + have hpull : (C.restrict B).norm.comp e.toLinearMap = QuadraticForm.rankOne (1 : k) := by + refine QuadraticMap.ext fun x ↦ ?_ + change C.norm (x • (1 : A)) = QuadraticForm.rankOne (1 : k) x + rw [C.norm.map_smul, C.norm_one, QuadraticForm.rankOne_apply] + simp only [smul_eq_mul, mul_one, one_mul, pow_two] + have hreg : QuadraticForm.IsGPRRegular (C.restrict B).norm := by + apply (QuadraticForm.isGPRRegular_comp_linearEquiv_iff e).mp + rw [hpull] + exact (QuadraticForm.isGPRRegular_rankOne_iff_isUnit_two (isUnit_one : IsUnit (1 : k))).mpr + (isUnit_of_invertible (2 : k)) + obtain ⟨D, v, s, hs, hD, hv, hDv, hDreg, hbij⟩ := + h.exists_bijective_cayToAlgebra_aux hLG hA r 1 B hreg hB (by omega) hr (by omega) + exact ⟨D, v, s, hs, hD, hv, hDreg, hbij⟩ + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChange.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChange.lean new file mode 100644 index 0000000000..97761b0adf --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChange.lean @@ -0,0 +1,191 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective +public import Mathlib.RingTheory.TensorProduct.Basic + +/-! +# Base change of conic algebras (the final paragraph of `GPR 16.1`) + +A conic algebra `(A, n)` over `k` gives a conic algebra `(S ⊗[k] A, n_S)` over every commutative +`k`-algebra `S`. This is what lets the classification arguments localize, and it is a prerequisite +for Cayley–Dickson doubling (Layer 6), whose compatibility with base change is `GPR 18.x`. + +## Main definitions + +* `ConicAlgebra.baseChangeOfProjective` : the conic algebra `S ⊗[k] A`. + +## Main results + +* `ConicAlgebra.mul_add_mul_baseChangeOfProjective` : the linearized degree-two identity holds on + `S ⊗[k] A`. It is proved *before* the degree-two identity itself, because it is bi-additive and + so reduces to pure tensors, whereas the degree-two identity is quadratic and its additivity step + is exactly the linearized identity. +* `ConicAlgebra.baseChangeOfProjective_norm_tmul`, `ConicAlgebra.baseChangeOfProjective_trace_tmul`, + `ConicAlgebra.baseChangeOfProjective_conj_tmul` : norm, trace and conjugation on pure tensors. + +## Implementation notes + +**Finitely generated projective, and why the name says so.** The norm is base changed with +`QuadraticForm.baseChangeOfProjective` (`QuadraticForm/BaseChangeProjective.lean`), which needs +`A` finitely generated projective over `k` but — unlike mathlib's `QuadraticForm.baseChange` — +nothing about `2`. So this is *not* base change of conic algebras in general, and the name carries +the restriction to the call site rather than burying it in a docstring: a hypothesis on a +**definition** is against overview §2, and one that is invisible would be worse. + +The final paragraph of `GPR 16.1` has no such restriction, because a quadratic form base changes +over an arbitrary +module: `q_S` is the unique form on `S ⊗[k] M` with `q_S(s ⊗ m) = s² q(m)` and the expected +polar form. +Proving that needs quadratic maps as degree-two polynomial laws (Roby); mathlib now has polynomial +laws (`PolynomialLaw`) but does not yet relate them to `QuadraticMap`, and this project does not +either. `baseChangeOfProjective` sidesteps it by choosing a bilinear `b` with `b(x, x) = q(x)`, +which exists whenever the module is projective (`QuadraticMap.hasBilinRepr_of_projective`) — though +not only then: the zero form has one on every module, and when `2` is invertible half the polar form +represents every form. Nothing downstream needs the general case: composition algebras are finitely +generated projective by definition, and Cayley–Dickson doubling preserves that. See the TODO below. + +**The multiplication is mathlib's.** `S ⊗[k] A` carries `NonAssocRing` from +`Mathlib/RingTheory/TensorProduct/Basic.lean`, which builds the multiplication on a tensor product +of two possibly non-associative algebras. Nothing has to be constructed here beyond the norm. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.1. +* N. Roby, *Lois polynômes et lois formelles en théorie des modules*, Ann. Sci. ÉNS **80** (1963), + 213–348: quadratic maps as degree-two polynomial laws, which is what general base change needs. + +## TODO + +* Base change of a quadratic form over an **arbitrary** module, hence the full statement following + `GPR 16.1` without the + projectivity hypothesis. This is missing from mathlib too, and is all that stands between + `ConicAlgebra.baseChangeOfProjective` and `ConicAlgebra.baseChange`. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] +variable (S : Type w) [CommRing S] [Algebra k S] (C : ConicAlgebra k A) + +/-! ### The base-changed norm -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The norm of the base-changed algebra on a pure tensor. -/ +theorem baseChangeOfProjective_norm_tmul (s : S) (a : A) : + (C.norm.baseChangeOfProjective S) (s ⊗ₜ[k] a) = C.norm a • (s * s) := + QuadraticForm.baseChangeOfProjective_tmul _ _ _ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The polar form of the base-changed norm on pure tensors. -/ +theorem baseChangeOfProjective_polar_tmul (s s' : S) (a a' : A) : + polar (C.norm.baseChangeOfProjective S) (s ⊗ₜ[k] a) (s' ⊗ₜ[k] a') = + polar C.norm a a' • (s * s') := by + have h := QuadraticForm.polarBilin_baseChangeOfProjective (A := S) C.norm + simpa using DFunLike.congr_fun (DFunLike.congr_fun h (s ⊗ₜ[k] a)) (s' ⊗ₜ[k] a') + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The trace of the base-changed algebra on a pure tensor: `t(s ⊗ a) = t(a) • s`. -/ +theorem baseChangeOfProjective_trace_tmul (s : S) (a : A) : + polar (C.norm.baseChangeOfProjective S) 1 (s ⊗ₜ[k] a) = C.trace a • s := by + rw [show (1 : S ⊗[k] A) = (1 : S) ⊗ₜ[k] (1 : A) from rfl, baseChangeOfProjective_polar_tmul, + one_mul] + rfl + +/-! ### The degree-two identity -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] in +variable {S} in +/-- Moving a scalar of `k` out of the `S`-action on a pure tensor. -/ +private theorem smul_smul_tmul (c : k) (s s' : S) (a : A) : + (c • s) • (s' ⊗ₜ[k] a) = c • ((s * s') ⊗ₜ[k] a) := by + rw [smul_assoc, TensorProduct.smul_tmul', smul_eq_mul] + +/-- **The linearized degree-two identity on `S ⊗[k] A`.** Both sides are additive in each +argument, so this reduces to pure tensors, where it is `ConicAlgebra.mul_add_mul` in `A`. -/ +theorem mul_add_mul_baseChangeOfProjective (x y : S ⊗[k] A) : + x * y + y * x = + polar (C.norm.baseChangeOfProjective S) 1 x • y + + polar (C.norm.baseChangeOfProjective S) 1 y • x - + polar (C.norm.baseChangeOfProjective S) x y • (1 : S ⊗[k] A) := by + induction x with + | add x₁ x₂ h₁ h₂ => + simp only [add_mul, mul_add, QuadraticMap.polar_add_left, QuadraticMap.polar_add_right] + linear_combination (norm := module) h₁ + h₂ + | tmul s a => + induction y with + | add y₁ y₂ h₁ h₂ => + simp only [add_mul, mul_add, QuadraticMap.polar_add_right] + linear_combination (norm := module) h₁ + h₂ + | tmul s' a' => + rw [Algebra.TensorProduct.tmul_mul_tmul, Algebra.TensorProduct.tmul_mul_tmul, + baseChangeOfProjective_trace_tmul, baseChangeOfProjective_trace_tmul, + baseChangeOfProjective_polar_tmul, show s' * s = s * s' from mul_comm _ _, + ← TensorProduct.tmul_add, C.mul_add_mul a a', + show (1 : S ⊗[k] A) = (1 : S) ⊗ₜ[k] (1 : A) from rfl, smul_smul_tmul, smul_smul_tmul, + smul_smul_tmul, mul_comm s' s, mul_one] + simp only [TensorProduct.tmul_sub, TensorProduct.tmul_add, TensorProduct.tmul_smul] + +/-- **The degree-two identity on `S ⊗[k] A`.** On pure tensors it is the identity in `A`; the +additivity step is `ConicAlgebra.mul_add_mul_baseChangeOfProjective`. -/ +theorem mul_self_baseChangeOfProjective (x : S ⊗[k] A) : + x * x = polar (C.norm.baseChangeOfProjective S) 1 x • x - + (C.norm.baseChangeOfProjective S) x • (1 : S ⊗[k] A) := by + induction x with + | tmul s a => + rw [Algebra.TensorProduct.tmul_mul_tmul, baseChangeOfProjective_trace_tmul, + baseChangeOfProjective_norm_tmul, C.mul_self_eq a, + show (1 : S ⊗[k] A) = (1 : S) ⊗ₜ[k] (1 : A) from rfl] + simp only [TensorProduct.tmul_sub, TensorProduct.tmul_smul] + rw [smul_smul_tmul, smul_smul_tmul, mul_one] + | add x y hx hy => + have hnorm : (C.norm.baseChangeOfProjective S) (x + y) = + (C.norm.baseChangeOfProjective S) x + (C.norm.baseChangeOfProjective S) y + + polar (C.norm.baseChangeOfProjective S) x y := by + simp only [QuadraticMap.polar]; ring + rw [add_mul, mul_add, mul_add, + show x * x + x * y + (y * x + y * y) = x * x + y * y + (x * y + y * x) by abel, + hx, hy, mul_add_mul_baseChangeOfProjective S C x y, QuadraticMap.polar_add_right, hnorm] + module + +/-- **Base change of a conic algebra** (the final paragraph of `GPR 16.1`). -/ +noncomputable def baseChangeOfProjective : ConicAlgebra S (S ⊗[k] A) where + norm := C.norm.baseChangeOfProjective S + norm_one := by + rw [show (1 : S ⊗[k] A) = (1 : S) ⊗ₜ[k] (1 : A) from rfl, + baseChangeOfProjective_norm_tmul, C.norm_one, mul_one, one_smul] + mul_self := mul_self_baseChangeOfProjective S C + +@[simp] theorem baseChangeOfProjective_norm : + (C.baseChangeOfProjective S).norm = C.norm.baseChangeOfProjective S := rfl + +theorem baseChangeOfProjective_norm_apply_tmul (s : S) (a : A) : + (C.baseChangeOfProjective S).norm (s ⊗ₜ[k] a) = C.norm a • (s * s) := + baseChangeOfProjective_norm_tmul S C s a + +@[simp] theorem baseChangeOfProjective_trace_apply_tmul (s : S) (a : A) : + (C.baseChangeOfProjective S).trace (s ⊗ₜ[k] a) = C.trace a • s := + baseChangeOfProjective_trace_tmul S C s a + +/-- Conjugation of the base change is the base change of the conjugation. -/ +@[simp] theorem baseChangeOfProjective_conj_tmul (s : S) (a : A) : + (C.baseChangeOfProjective S).conj (s ⊗ₜ[k] a) = s ⊗ₜ[k] C.conj a := by + rw [conj_apply, baseChangeOfProjective_trace_apply_tmul, conj_apply, + show (1 : S ⊗[k] A) = (1 : S) ⊗ₜ[k] (1 : A) from rfl, TensorProduct.tmul_sub, + TensorProduct.tmul_smul, smul_smul_tmul, mul_one] + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChangeMultiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChangeMultiplicative.lean new file mode 100644 index 0000000000..509daad276 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/BaseChangeMultiplicative.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative + +/-! +# Base change preserves multiplicativity (`GPR 19.7`) + +If the norm of a conic algebra `A` over `k` permits composition, then so does the norm of +`S ⊗[k] A` for every commutative `k`-algebra `S`. Together with the base-change stability of +non-singularity, which is built into `QuadraticForm.IsGPRNonsingular` by definition, this is what +makes `ConicAlgebra.IsComposition` stable under base change, and it is the step that lets a +statement about composition algebras over a ring be tested on the residue fields. + +## Main results + +* `ConicAlgebra.IsMultiplicative.baseChangeOfProjective` : `n(XY) = n(X) n(Y)` on `S ⊗[k] A`. + +## Implementation notes + +Multiplicativity is *quadratic*, so it does not reduce to pure tensors on its own: the additivity +step in an induction over `S ⊗[k] A` produces a cross term `n(X₁Y, X₂Y)`, which is not part of the +statement being proved. The proof therefore runs the three levels of linearization from +`Conic/Multiplicative.lean` in the reverse of the usual order, each one supplying the additivity +step of the next: + +* `polar_mul_add_polar_mul_baseChangeOfProjective` (`n(XZ, YW) + n(XW, YZ) = n(X, Y) n(Z, W)`) is + additive in each of its four arguments separately, so it *does* reduce to pure tensors, by four + nested inductions; +* `polar_mul_mul_right_baseChangeOfProjective` and `polar_mul_mul_left_baseChangeOfProjective` + (`n(XZ, YZ) = n(X, Y) n(Z)` and `n(XY, XZ) = n(X) n(Y, Z)`) are additive in two of their three + arguments and quadratic in the third; the cross term of the quadratic one is the second + linearization above; +* multiplicativity itself is quadratic in both arguments, and its two cross terms are the two + first linearizations. + +The two first linearizations are genuinely two statements: `A` is not assumed associative or +commutative, so neither follows from the other (`Conic/Multiplicative.lean` makes the same point +about `A` itself). Nothing here needs alternativity, regularity, or a hypothesis on `2`; the +finite projectivity is inherited from `ConicAlgebra.baseChangeOfProjective`, which needs it to base +change the norm at all. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.1, 19.7. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] +variable (S : Type w) [CommRing S] [Algebra k S] {C : ConicAlgebra k A} + +namespace IsMultiplicative + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Expanding the base-changed norm of a sum. This is `QuadraticMap.polar` read backwards, and is +the reason every induction below has a cross term. -/ +private theorem norm_baseChangeOfProjective_add (x y : S ⊗[k] A) : + (C.norm.baseChangeOfProjective S) (x + y) = + (C.norm.baseChangeOfProjective S) x + (C.norm.baseChangeOfProjective S) y + + polar (C.norm.baseChangeOfProjective S) x y := by + simp only [QuadraticMap.polar] + ring + +/-- **The second linearization of multiplicativity, after base change**: +`n(XZ, YW) + n(XW, YZ) = n(X, Y) n(Z, W)` on `S ⊗[k] A`. + +Both sides are additive in each of the four arguments separately, so four nested inductions reduce +this to pure tensors, where it is `ConicAlgebra.IsMultiplicative.polar_mul_add_polar_mul` in `A` +together with commutativity of `S`. -/ +theorem polar_mul_add_polar_mul_baseChangeOfProjective (h : C.IsMultiplicative) + (x y z w : S ⊗[k] A) : + polar (C.norm.baseChangeOfProjective S) (x * z) (y * w) + + polar (C.norm.baseChangeOfProjective S) (x * w) (y * z) = + polar (C.norm.baseChangeOfProjective S) x y * + polar (C.norm.baseChangeOfProjective S) z w := by + induction x with + | add x₁ x₂ h₁ h₂ => + simp only [add_mul, QuadraticMap.polar_add_left] + linear_combination h₁ + h₂ + | tmul s a => + induction y with + | add y₁ y₂ h₁ h₂ => + simp only [add_mul, QuadraticMap.polar_add_right] + linear_combination h₁ + h₂ + | tmul s' a' => + induction z with + | add z₁ z₂ h₁ h₂ => + simp only [mul_add, QuadraticMap.polar_add_left, QuadraticMap.polar_add_right] + linear_combination h₁ + h₂ + | tmul u c => + induction w with + | add w₁ w₂ h₁ h₂ => + simp only [mul_add, QuadraticMap.polar_add_left, QuadraticMap.polar_add_right] + linear_combination h₁ + h₂ + | tmul u' c' => + have hS₁ : (s * u) * (s' * u') = (s * s') * (u * u') := by ring + have hS₂ : (s * u') * (s' * u) = (s * s') * (u * u') := by ring + rw [Algebra.TensorProduct.tmul_mul_tmul, Algebra.TensorProduct.tmul_mul_tmul, + Algebra.TensorProduct.tmul_mul_tmul, Algebra.TensorProduct.tmul_mul_tmul, + baseChangeOfProjective_polar_tmul, baseChangeOfProjective_polar_tmul, + baseChangeOfProjective_polar_tmul, baseChangeOfProjective_polar_tmul, + hS₁, hS₂, smul_mul_smul_comm, ← add_smul, h.polar_mul_add_polar_mul] + +/-- **The first linearization of multiplicativity, after base change**, in the left variable: +`n(XZ, YZ) = n(X, Y) n(Z)` on `S ⊗[k] A`. + +Additive in `X` and in `Y`, quadratic in `Z`; the cross term of the induction on `Z` is +`ConicAlgebra.IsMultiplicative.polar_mul_add_polar_mul_baseChangeOfProjective`. -/ +theorem polar_mul_mul_right_baseChangeOfProjective (h : C.IsMultiplicative) (x y z : S ⊗[k] A) : + polar (C.norm.baseChangeOfProjective S) (x * z) (y * z) = + polar (C.norm.baseChangeOfProjective S) x y * (C.norm.baseChangeOfProjective S) z := by + induction x with + | add x₁ x₂ h₁ h₂ => + simp only [add_mul, QuadraticMap.polar_add_left] + linear_combination h₁ + h₂ + | tmul s a => + induction y with + | add y₁ y₂ h₁ h₂ => + simp only [add_mul, QuadraticMap.polar_add_right] + linear_combination h₁ + h₂ + | tmul s' a' => + induction z with + | add z₁ z₂ h₁ h₂ => + have key := + h.polar_mul_add_polar_mul_baseChangeOfProjective S (s ⊗ₜ[k] a) (s' ⊗ₜ[k] a') + z₁ z₂ + simp only [mul_add, QuadraticMap.polar_add_left, QuadraticMap.polar_add_right, + norm_baseChangeOfProjective_add] + linear_combination h₁ + h₂ + key + | tmul u c => + have hS : (s * u) * (s' * u) = (s * s') * (u * u) := by ring + rw [Algebra.TensorProduct.tmul_mul_tmul, Algebra.TensorProduct.tmul_mul_tmul, + baseChangeOfProjective_polar_tmul, baseChangeOfProjective_polar_tmul, + baseChangeOfProjective_norm_tmul, hS, smul_mul_smul_comm, h.polar_mul_mul_right] + +/-- **The first linearization of multiplicativity, after base change**, in the right variable: +`n(XY, XZ) = n(X) n(Y, Z)` on `S ⊗[k] A`. + +Not a consequence of `polar_mul_mul_right_baseChangeOfProjective`, since `A` is not assumed +commutative, but proved the same way, with the roles of the additive and the quadratic arguments +exchanged. -/ +theorem polar_mul_mul_left_baseChangeOfProjective (h : C.IsMultiplicative) (x y z : S ⊗[k] A) : + polar (C.norm.baseChangeOfProjective S) (x * y) (x * z) = + (C.norm.baseChangeOfProjective S) x * polar (C.norm.baseChangeOfProjective S) y z := by + induction y with + | add y₁ y₂ h₁ h₂ => + simp only [mul_add, QuadraticMap.polar_add_left] + linear_combination h₁ + h₂ + | tmul t b => + induction z with + | add z₁ z₂ h₁ h₂ => + simp only [mul_add, QuadraticMap.polar_add_right] + linear_combination h₁ + h₂ + | tmul u c => + induction x with + | add x₁ x₂ h₁ h₂ => + have key := h.polar_mul_add_polar_mul_baseChangeOfProjective S x₁ x₂ (t ⊗ₜ[k] b) + (u ⊗ₜ[k] c) + rw [QuadraticMap.polar_comm (C.norm.baseChangeOfProjective S) (x₁ * (u ⊗ₜ[k] c)) + (x₂ * (t ⊗ₜ[k] b))] at key + simp only [add_mul, QuadraticMap.polar_add_left, QuadraticMap.polar_add_right, + norm_baseChangeOfProjective_add] + linear_combination h₁ + h₂ + key + | tmul s a => + have hS : (s * t) * (s * u) = (s * s) * (t * u) := by ring + rw [Algebra.TensorProduct.tmul_mul_tmul, Algebra.TensorProduct.tmul_mul_tmul, + baseChangeOfProjective_polar_tmul, baseChangeOfProjective_polar_tmul, + baseChangeOfProjective_norm_tmul, hS, smul_mul_smul_comm, h.polar_mul_mul_left] + +/-- **Multiplicativity is stable under base change.** If the norm of `A` permits composition, so +does the norm of `S ⊗[k] A` for every commutative `k`-algebra `S`. + +The induction on the left argument has cross term +`polar_mul_mul_right_baseChangeOfProjective`, the one on the right argument +`polar_mul_mul_left_baseChangeOfProjective`, and on pure tensors the identity is +`n(ab) = n(a) n(b)` in `A` times `(st)² = s²t²` in `S`. -/ +theorem baseChangeOfProjective (h : C.IsMultiplicative) : + (C.baseChangeOfProjective S).IsMultiplicative := by + intro x y + simp only [baseChangeOfProjective_norm] + induction x with + | add x₁ x₂ h₁ h₂ => + rw [add_mul, norm_baseChangeOfProjective_add, norm_baseChangeOfProjective_add, h₁, h₂, + h.polar_mul_mul_right_baseChangeOfProjective S] + ring + | tmul s a => + induction y with + | add y₁ y₂ h₁ h₂ => + rw [mul_add, norm_baseChangeOfProjective_add, norm_baseChangeOfProjective_add, h₁, h₂, + h.polar_mul_mul_left_baseChangeOfProjective S] + ring + | tmul t b => + have hS : (s * t) * (s * t) = (s * s) * (t * t) := by ring + rw [Algebra.TensorProduct.tmul_mul_tmul, baseChangeOfProjective_norm_tmul, + baseChangeOfProjective_norm_tmul, baseChangeOfProjective_norm_tmul, hS, + smul_mul_smul_comm, h.norm_mul] + +end IsMultiplicative + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Basic.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Basic.lean new file mode 100644 index 0000000000..d06493931e --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Basic.lean @@ -0,0 +1,384 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Tactic.LinearCombination +public import Mathlib.Tactic.Module +public import LeanPool.CompositionAlgebrasOverRings.Conic.Defs +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs + +/-! +# Trace, conjugation, and the conic calculus + +The trace and the conjugation of a conic algebra (`GPR 16.1`–`16.6`), and the identities they +satisfy. Everything here is derived from the two axioms of `ConicAlgebra`; no regularity, no +projectivity, and no assumption that `2` is invertible. + +## Main definitions + +* `ConicAlgebra.trace` : `t(x) = n(1, x)`, the un-halved polar form of the norm at the unit. + Note `t(1) = 2`, not `1`. +* `ConicAlgebra.conj` : `x ↦ t(x) • 1 - x`, a `k`-linear involution. +* `ConicAlgebra.traceDefect` : `t(x)t(y) - n(x, y) - t(xy)`, the obstruction to conjugation being + an anti-homomorphism. + +## Main results + +* `ConicAlgebra.conj_conj` : conjugation is an involution. +* `ConicAlgebra.add_conj` : `x + conj x = t(x) • 1`. +* `ConicAlgebra.mul_conj_self`, `ConicAlgebra.conj_mul_self` : `x (conj x) = (conj x) x = n(x) • 1`. +* `ConicAlgebra.trace_conj`, `ConicAlgebra.norm_conj` : trace and norm are conjugation-invariant. +* `ConicAlgebra.mul_add_mul` : the linearized degree-two identity + `xy + yx = t(x) • y + t(y) • x - n(x, y) • 1`. +* `ConicAlgebra.conj_mul_conj` : `(conj y) (conj x) = conj (xy) + traceDefect x y • 1`, the sharp + unconditional statement of how far conjugation is from being an anti-homomorphism. +* `ConicAlgebra.traceDefect_smul_eq_smul_one` : in an **alternative** conic algebra, + `traceDefect x y • x` is a scalar multiple of `1`. +* `ConicAlgebra.traceDefect_eq_zero`, `ConicAlgebra.conj_mul` : over a **field**, conjugation of an + alternative conic algebra is an anti-homomorphism, `conj (xy) = (conj y) (conj x)`. + +## Implementation notes + +Conjugation is **not** mathlib's `star`. `Star` is a typeclass on the type `A`, but the conjugation +of a conic algebra is a function of the norm, which is data attached to `C : ConicAlgebra k A` and +need not be unique; two conic structures on the same algebra have different conjugations. So `conj` +is a field-free definition taking `C` as an argument, and no `StarRing` instance is (or can be) +declared. + +⚠ **Alternativity alone does not make conjugation an anti-homomorphism over a ring.** The +obstruction `traceDefect x y = t(x)t(y) - n(x, y) - t(xy)` vanishes identically over a field, but +not over an arbitrary commutative ring, even for **associative** `A`. This is not new: `GPR 16.10` +gives the exact criterion (conjugation is an involution iff the obstruction lies in `Ann(A)`), the +projectivity hypotheses in `GPR 16.14(b)` and `GPR 17.6` are there for this reason, and `GPR` says +so explicitly in `17.4` ("one might be tempted to conjecture that conic alternative algebras are +multiplicative. But, according to Exc. 17.8 below, this is not so"). Counterexample: let `k = ℤ/4`, +let `M = (ℤ/2)²` as a `k`-module with basis `m₁, m₂`, let `β : M × M → k` be the `k`-bilinear form +with `β(m₁, m₂) = 2` and `β = 0` on the other three pairs of basis vectors, and put +`A = k·1 ⊕ M` with + + `(a·1 + m)(b·1 + p) = (ab + β(m, p))·1 + (a p + b m)`. + +Then `A` is associative — associativity of the `M`-component asks `β(m, p) q = β(p, q) m`, and both +sides lie in `2 · M = 0` — and `n(a·1 + m) = a² - β(m, m)` with `t(a·1 + m) = 2a` makes it a conic +algebra. But `traceDefect m₁ m₂ = β(m₂, m₁) - β(m₁, m₂) = -2 ≠ 0`, so +`conj (m₁ m₂) = 2·1 ≠ 0 = conj m₂ · conj m₁`. Here `A` is finitely generated but *not* projective; +projectivity of `A` (which every composition algebra has) is the hypothesis that rules such examples +out in general, via a localization argument — `GPR 16.14(b)`. It is a small variant of +`GPR Exc. 17.8`, due to McCrimmon; see `Conic/TraceDefectCounterexample.lean`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.1–16.6 (the + conic calculus), 16.10 and 16.14 (when conjugation is an involution), 17.6 and Exc. 17.8 (the + role of projectivity, and McCrimmon's counterexample without it). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section CommRing + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + +/-! ### Norm identities -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem norm_add (x y : A) : + C.norm (x + y) = C.norm x + C.norm y + QuadraticMap.polar C.norm x y := by + simp only [QuadraticMap.polar]; ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem norm_sub (x y : A) : + C.norm (x - y) = C.norm x + C.norm y - QuadraticMap.polar C.norm x y := by + rw [sub_eq_add_neg, C.norm_add x (-y), QuadraticMap.polar_neg_right, QuadraticMap.map_neg] + ring + +/-! ### The trace -/ + +/-- The **trace** of a conic algebra: `t(x) = n(1, x)`, the un-halved polar form of the norm, +evaluated at the unit (`GPR 16.2`). + +⚠ `t(1) = 2`, not `1`: this is `QuadraticMap.polar`, not `QuadraticMap.associated`. -/ +def trace : A →ₗ[k] k := C.norm.polarBilin 1 + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem trace_apply (x : A) : C.trace x = QuadraticMap.polar C.norm 1 x := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem trace_one : C.trace (1 : A) = 2 := by + rw [trace_apply, QuadraticMap.polar_self, C.norm_one] + simp + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The degree-two identity, in terms of the trace: `x² = t(x) • x - n(x) • 1`. -/ +theorem mul_self_eq (x : A) : x * x = C.trace x • x - C.norm x • (1 : A) := C.mul_self x + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The **linearized degree-two identity**: `xy + yx = t(x) • y + t(y) • x - n(x, y) • 1`. + +This is the workhorse of the conic calculus, and holds in every conic algebra — no alternativity, +no regularity. It is obtained from the degree-two identity at `x + y` by subtracting the identities +at `x` and at `y`; only additivity is used, so it is valid in characteristic 2. -/ +theorem mul_add_mul (x y : A) : + x * y + y * x = + C.trace x • y + C.trace y • x - QuadraticMap.polar C.norm x y • (1 : A) := by + have hx := C.mul_self_eq x + have hy := C.mul_self_eq y + have hxy := C.mul_self_eq (x + y) + rw [add_mul, mul_add, mul_add, map_add, C.norm_add] at hxy + linear_combination (norm := module) hxy - hx - hy + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The linearized degree-two identity, solved for `y * x`. -/ +theorem mul_comm_eq (x y : A) : + y * x = C.trace x • y + C.trace y • x - QuadraticMap.polar C.norm x y • (1 : A) - x * y := by + linear_combination (norm := module) C.mul_add_mul x y + +/-! ### Conjugation -/ + +/-- The **conjugation** of a conic algebra: `conj x = t(x) • 1 - x` (`GPR 16.2`), as a `k`-linear +map. + +It is not mathlib's `star`: the conjugation depends on the norm, which is data, so it cannot be a +typeclass on `A`. -/ +def conj : A →ₗ[k] A := (LinearMap.toSpanSingleton k A 1).comp C.trace - LinearMap.id + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem conj_apply (x : A) : C.conj x = C.trace x • (1 : A) - x := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem add_conj (x : A) : x + C.conj x = C.trace x • (1 : A) := by + rw [conj_apply]; abel + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem conj_one : C.conj (1 : A) = 1 := by + rw [conj_apply, trace_one, two_smul]; abel + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem trace_conj (x : A) : C.trace (C.conj x) = C.trace x := by + rw [conj_apply, map_sub, map_smul, trace_one, smul_eq_mul]; ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Conjugation is an involution (`GPR 16.2`). -/ +@[simp] theorem conj_conj (x : A) : C.conj (C.conj x) = x := by + rw [conj_apply (x := C.conj x), trace_conj, conj_apply]; abel + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem norm_conj (x : A) : C.norm (C.conj x) = C.norm x := by + rw [conj_apply, C.norm_sub, QuadraticMap.map_smul, C.norm_one, QuadraticMap.polar_smul_left, + ← trace_apply, smul_eq_mul, smul_eq_mul, mul_one] + ring + +omit [IsScalarTower k A A] in +/-- `x (conj x) = n(x) • 1` (`GPR 16.2`). -/ +@[simp] theorem mul_conj_self (x : A) : x * C.conj x = C.norm x • (1 : A) := by + rw [conj_apply, mul_sub, mul_smul_comm, mul_one, C.mul_self_eq]; abel + +omit [SMulCommClass k A A] in +/-- `(conj x) x = n(x) • 1` (`GPR 16.2`). -/ +@[simp] theorem conj_mul_self (x : A) : C.conj x * x = C.norm x • (1 : A) := by + rw [conj_apply, sub_mul, smul_mul_assoc, one_mul, C.mul_self_eq]; abel + +/-! ### The base ring + +`ConicAlgebra.baseRing k` is `k` with norm `x ↦ x²`. Its trace is doubling and its conjugation is +the **identity** — the degenerate case that starts the Cayley–Dickson tower, and the reason the +first double is commutative (`ConicAlgebra.mul_comm_cay`). -/ + +section BaseRing + +variable (k) in +@[simp] theorem baseRing_trace_apply (x : k) : (baseRing k).trace x = 2 * x := by + rw [trace_apply, QuadraticMap.polar, baseRing_norm_apply, baseRing_norm_apply, + baseRing_norm_apply] + ring + +variable (k) in +/-- The conjugation of the base ring is the identity: `conj x = t(x)·1 - x = 2x - x = x`. -/ +@[simp] theorem baseRing_conj_apply (x : k) : (baseRing k).conj x = x := by + rw [conj_apply, baseRing_trace_apply, smul_eq_mul, mul_one] + ring + +end BaseRing + +/-! ### The obstruction to anti-multiplicativity of the conjugation -/ + +/-- The **trace defect** `t(x)t(y) - n(x, y) - t(xy)`: the obstruction to conjugation being an +anti-homomorphism, by `ConicAlgebra.conj_mul_conj`. + +This name is ours, not `GPR`'s, but the quantity is: `traceDefect x y = n(x, conj y) - t(xy)`, the +negative of the obstruction `t(x, y) - n(x, conj y)` appearing in `GPR 16.5(11)` and `GPR 16.10` +(where `t(x, y)` denotes the *bilinear* trace `t(xy)`, and `n(x, conj y) = t(x)t(y) - n(x, y)` by +`GPR 16.5(10)`). Equivalently it is the difference of the two sides of the identity +`t(xy) = t(x)t(y) - n(x, y)`, which holds in every composition algebra but not in every conic +algebra. See the ⚠ in the module docstring for an associative conic algebra over `ℤ/4` with nonzero +trace defect. -/ +def traceDefect (x y : A) : k := + C.trace x * C.trace y - QuadraticMap.polar C.norm x y - C.trace (x * y) + +/-- **How far conjugation is from being an anti-homomorphism**, exactly, in any conic algebra +(`GPR 16.5(11)`): `(conj y) (conj x) = conj (xy) + traceDefect x y • 1`. -/ +theorem conj_mul_conj (x y : A) : + C.conj y * C.conj x = C.conj (x * y) + C.traceDefect x y • (1 : A) := by + have hyx := C.mul_comm_eq x y + simp only [conj_apply, traceDefect, sub_mul, mul_sub, smul_mul_assoc, mul_smul_comm, one_mul, + mul_one] + rw [hyx] + module + +/-- Conjugation is an anti-homomorphism exactly where the trace defect vanishes. Globally, +`GPR 16.10(a)`: conjugation is an involution iff `traceDefect x y ∈ Ann(A)` for all `x, y`, which +for the faithful `A` we care about means it vanishes. -/ +theorem conj_mul_of_traceDefect_eq_zero {x y : A} (h : C.traceDefect x y = 0) : + C.conj (x * y) = C.conj y * C.conj x := by + rw [C.conj_mul_conj, h, zero_smul, add_zero] + +/-- The conjugation of `C` is an **involution** (`GPR 16.9` ff.): an anti-automorphism of `A`. + +Only anti-multiplicativity is asked for, because the rest is automatic: `conj` is `k`-linear by +construction, fixes `1` (`ConicAlgebra.conj_one`) and squares to the identity +(`ConicAlgebra.conj_conj`), all with no hypotheses. By `ConicAlgebra.conj_mul_conj` this condition +says exactly that the trace defect lies in `Ann(A)`, which is `GPR 16.10(a)`. + +It holds for alternative `C` over a field (`ConicAlgebra.conj_mul`) and, more generally, whenever +`A` is finitely generated projective (`ConicAlgebra.conjIsInvolution_of_projective`), but not in +general — see `Conic/TraceDefectCounterexample.lean`. -/ +def ConjIsInvolution : Prop := ∀ x y : A, C.conj (x * y) = C.conj y * C.conj x + +theorem conjIsInvolution_of_traceDefect_eq_zero (h : ∀ x y : A, C.traceDefect x y = 0) : + C.ConjIsInvolution := fun x y ↦ C.conj_mul_of_traceDefect_eq_zero (h x y) + +variable (k) in +/-- The conjugation of the base ring is an involution, trivially: it is the identity +(`ConicAlgebra.baseRing_conj_apply`), and `k` is commutative. This is what starts the +Cayley–Dickson tower. -/ +theorem conjIsInvolution_baseRing : (baseRing k).ConjIsInvolution := fun x y ↦ by + rw [baseRing_conj_apply, baseRing_conj_apply, baseRing_conj_apply, mul_comm] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Anti-multiplicativity, as a rewrite rule. `ConicAlgebra.ConjIsInvolution` is a `def`, so it +has to be unfolded before `simp` can use it. -/ +theorem ConjIsInvolution.conj_mul (h : C.ConjIsInvolution) (x y : A) : + C.conj (x * y) = C.conj y * C.conj x := h x y + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem traceDefect_self (x : A) : C.traceDefect x x = 0 := by + rw [traceDefect, QuadraticMap.polar_self, C.mul_self_eq, map_sub, map_smul, map_smul, trace_one, + smul_eq_mul, smul_eq_mul, nsmul_eq_mul] + push_cast + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem traceDefect_one_left (y : A) : C.traceDefect 1 y = 0 := by + rw [traceDefect, trace_one, one_mul, ← trace_apply] + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem traceDefect_one_right (x : A) : C.traceDefect x 1 = 0 := by + rw [traceDefect, trace_one, mul_one, QuadraticMap.polar_comm, ← trace_apply] + ring + +omit [SMulCommClass k A A] in +theorem traceDefect_smul_left (a : k) (x y : A) : + C.traceDefect (a • x) y = a * C.traceDefect x y := by + rw [traceDefect, traceDefect, map_smul, QuadraticMap.polar_smul_left, smul_mul_assoc a x y, + map_smul, smul_eq_mul, smul_eq_mul, smul_eq_mul] + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The trace defect is alternating: `traceDefect x y + traceDefect y x = 0`. Consequently it +vanishes on the diagonal (`traceDefect_self`) and is antisymmetric. -/ +theorem traceDefect_add_traceDefect_swap (x y : A) : + C.traceDefect x y + C.traceDefect y x = 0 := by + have h := congrArg C.trace (C.mul_add_mul x y) + simp only [map_add, map_sub, map_smul, trace_one, smul_eq_mul] at h + rw [traceDefect, traceDefect, QuadraticMap.polar_comm C.norm y x] + linear_combination -h + +end CommRing + +/-! ### Alternative conic algebras + +In an alternative conic algebra the trace defect is still not visibly zero, but it is *almost* so: +`traceDefect x y • x` is a scalar multiple of the unit. Over a field that forces it to vanish. -/ + +section Alternative + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] [IsAlternative A] (C : ConicAlgebra k A) + +omit [SMulCommClass k A A] in +/-- Left alternativity plus the degree-two identity: `x(xy) = t(x) • xy - n(x) • y`. -/ +theorem mul_mul_self_eq (x y : A) : x * (x * y) = C.trace x • (x * y) - C.norm x • y := by + rw [IsAlternative.mul_mul_self_left, C.mul_self_eq, sub_mul, smul_mul_assoc, smul_mul_assoc, + one_mul] + +/-- Flexibility plus the degree-two identity, expanding `x(yx)`. -/ +theorem mul_mul_comm_eq (x y : A) : + x * (y * x) = (C.trace y * C.trace x - QuadraticMap.polar C.norm x y) • x + - (C.trace y * C.norm x) • (1 : A) + C.norm x • y := by + rw [C.mul_comm_eq x y, mul_sub, mul_sub, mul_add, mul_smul_comm, mul_smul_comm, mul_smul_comm, + mul_one, C.mul_self_eq, C.mul_mul_self_eq] + module + +/-- **The trace defect is almost zero in an alternative conic algebra**: `traceDefect x y • x` is a +scalar multiple of `1`. + +Over a field this forces `traceDefect x y = 0` (`traceDefect_eq_zero`): if the scalar were nonzero, +`x` would lie in `k · 1`, where the defect vanishes anyway. Over a general commutative ring it does +not — see the ⚠ in the module docstring. -/ +theorem traceDefect_smul_eq_smul_one (x y : A) : + C.traceDefect x y • x + = (C.trace y * C.norm x - QuadraticMap.polar C.norm x (x * y)) • (1 : A) := by + have h := C.mul_add_mul x (x * y) + rw [IsAlternative.flexible, C.mul_mul_self_eq, C.mul_mul_comm_eq] at h + rw [traceDefect] + linear_combination (norm := module) h + +end Alternative + +/-! ### Alternative conic algebras over a field + +Over a field, the conjugation of an alternative conic algebra is an anti-homomorphism. -/ + +section Field + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] [IsAlternative A] (C : ConicAlgebra K A) + +/-- Over a **field**, the trace defect of an alternative conic algebra vanishes: +`t(xy) = t(x)t(y) - n(x, y)`. + +⚠ The field hypothesis is doing real work; see the ⚠ in the module docstring for an associative +conic algebra over `ℤ/4` whose trace defect is nonzero. -/ +theorem traceDefect_eq_zero (x y : A) : C.traceDefect x y = 0 := by + by_cases hx : ∃ a : K, x = a • (1 : A) + · obtain ⟨a, rfl⟩ := hx + rw [C.traceDefect_smul_left, C.traceDefect_one_left, mul_zero] + · by_contra h + refine hx ⟨(C.traceDefect x y)⁻¹ * + (C.trace y * C.norm x - QuadraticMap.polar C.norm x (x * y)), ?_⟩ + rw [mul_smul, ← C.traceDefect_smul_eq_smul_one x y, smul_smul, inv_mul_cancel₀ h, one_smul] + +/-- The trace is "multiplicative up to the norm" over a field: `t(xy) = t(x)t(y) - n(x, y)`. -/ +theorem trace_mul (x y : A) : + C.trace (x * y) = C.trace x * C.trace y - QuadraticMap.polar C.norm x y := by + have := C.traceDefect_eq_zero x y + rw [traceDefect] at this + linear_combination -this + +/-- **Conjugation is an algebra anti-homomorphism** for an alternative conic algebra over a field: +`conj (xy) = conj y * conj x`. -/ +theorem conj_mul (x y : A) : C.conj (x * y) = C.conj y * C.conj x := + C.conj_mul_of_traceDefect_eq_zero (C.traceDefect_eq_zero x y) + +end Field + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDickson.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDickson.lean new file mode 100644 index 0000000000..ca736e8e88 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDickson.lean @@ -0,0 +1,372 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import Mathlib.LinearAlgebra.QuadraticForm.Prod +public import Mathlib.RingTheory.Finiteness.Prod +public import Mathlib.Algebra.Module.Projective +public import Mathlib.LinearAlgebra.FreeModule.StrongRankCondition + +/-! +# The Cayley–Dickson construction (`GPR 18.3`, `GPR 18.4`) + +Given a conic algebra `B` over `k` and a scalar `μ ∈ k`, the **Cayley–Dickson double** +`Cay(B, μ)` is the `k`-module `B ⊕ B`, written `u + v j`, with + + `(u₁ + v₁ j)(u₂ + v₂ j) = (u₁u₂ + μ (conj v₂)v₁) + (v₂u₁ + v₁(conj u₂)) j`, `1 = 1_B + 0 j`, + `n(u + v j) = n_B(u) - μ n_B(v)`. + +It is again a conic algebra (`ConicAlgebra.cay`, `GPR 18.4`), and its trace and conjugation are + + `t(u + v j) = t_B(u)`, `conj (u + v j) = conj u - v j`. + +## Main definitions + +* `ConicAlgebra.Cay C μ` : the underlying `k`-module `B ⊕ B`, as a type synonym carrying the + Cayley–Dickson multiplication rather than the componentwise one. +* `ConicAlgebra.cay` : **`GPR 18.4`** — the conic algebra structure on `Cay C μ`. + +## Main results + +* `ConicAlgebra.cay_norm_apply`, `ConicAlgebra.cay_trace_apply`, `ConicAlgebra.cay_conj_apply` : + the formulas `GPR 18.4(3)`, `(5)`, `(6)`. +* `ConicAlgebra.cayIsometryEquiv` : a norm isometry acts componentwise on doubles; if it is + unital and multiplicative, so is the doubled equivalence. +* `ConicAlgebra.cayIsometryEquivOfEq` : transport between doubles whose parameters are equal. +* `ConicAlgebra.inl` : the embedding `B ↪ Cay C μ` of `GPR 18.3`, a unital algebra map. + +## Implementation notes + +**`μ` is an arbitrary scalar, not a unit.** Everything here holds for every `μ ∈ k`, including +`0`; hypotheses that `μ` be invertible belong to later theorems (`GPR 18.11` ff.), never to the +construction. + +**No hypotheses on `B` beyond conic.** The degree-two identity for `Cay(B, μ)` needs exactly two +facts about `B`: `(conj v)v = n(v) · 1` (`ConicAlgebra.conj_mul_self`) and `u + conj u = t(u) · 1` +(`ConicAlgebra.add_conj`), both of which hold in every conic algebra with no regularity, +projectivity, alternativity or assumption on `2`. In particular the norm is written down directly, +so — unlike `ConicAlgebra.baseChangeOfProjective` — nothing here needs `B` to be projective. + +**Why a type synonym.** `B × B` already carries the componentwise ring structure from mathlib, and +the Cayley–Dickson multiplication is a different one, so it must live on a synonym. The synonym +depends on the conic structure `C`, not just on `B`, because the multiplication uses the +conjugation of `B`; two conic structures on the same `B` double to genuinely different algebras. + +**External, not internal.** `GPR 18.1` builds `B + Bl` inside an ambient algebra; `GPR 18.2` warns +that this sum need not be direct. The external construction on `B ⊕ B` has no such problem and is +the one used here and in `GPR 18.3` ff. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.1–18.4. +-/ + +@[expose] public section + +universe u v w + +namespace ConicAlgebra + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [SMulCommClass k B B] [IsScalarTower k B B] + +/-- The underlying `k`-module `B ⊕ B` of the Cayley–Dickson double `Cay(B, μ)`, as a type synonym: +`B × B` already has the componentwise multiplication, and this one is different. The element +`(u, v)` is `GPR`'s `u + v j`. + +The parameters `C` and `μ` are part of the type even though the underlying module does not depend +on them: the multiplication does, so distinct parameters must give distinct types for instance +resolution to be sound. -/ +def Cay (_C : ConicAlgebra k B) (_μ : k) : Type v := B × B + +variable (C : ConicAlgebra k B) (μ : k) + +namespace Cay + +omit [SMulCommClass k B B] [IsScalarTower k B B] + +instance : AddCommGroup (Cay C μ) := inferInstanceAs (AddCommGroup (B × B)) +instance : Module k (Cay C μ) := inferInstanceAs (Module k (B × B)) + +/-- The double of a finitely generated module is finitely generated: rank doubles, so a +composition algebra of rank `d` doubles to one of rank `2d`. -/ +instance [Module.Finite k B] : Module.Finite k (Cay C μ) := + inferInstanceAs (Module.Finite k (B × B)) + +/-- The double of a projective module is projective, which is what keeps the Cayley–Dickson tower +inside the composition algebras. -/ +instance [Module.Projective k B] : Module.Projective k (Cay C μ) := + inferInstanceAs (Module.Projective k (B × B)) + +/-- The double of a free module is free. -/ +instance [Module.Free k B] : Module.Free k (Cay C μ) := + inferInstanceAs (Module.Free k (B × B)) + +/-- **The rank doubles.** This is what makes the Cayley–Dickson tower run through ranks +`1, 2, 4, 8` (`GPR 19.18`). -/ +theorem finrank_cay [Nontrivial k] [Module.Free k B] [Module.Finite k B] : + Module.finrank k (Cay C μ) = 2 * Module.finrank k B := + (Module.finrank_prod (R := k) (M := B) (M' := B)).trans (by ring) + +variable {C μ} + +@[simp] theorem fst_add (x y : Cay C μ) : (x + y).1 = x.1 + y.1 := rfl +@[simp] theorem snd_add (x y : Cay C μ) : (x + y).2 = x.2 + y.2 := rfl +@[simp] theorem fst_zero : (0 : Cay C μ).1 = 0 := rfl +@[simp] theorem snd_zero : (0 : Cay C μ).2 = 0 := rfl +@[simp] theorem fst_neg (x : Cay C μ) : (-x).1 = -x.1 := rfl +@[simp] theorem snd_neg (x : Cay C μ) : (-x).2 = -x.2 := rfl +@[simp] theorem fst_sub (x y : Cay C μ) : (x - y).1 = x.1 - y.1 := rfl +@[simp] theorem snd_sub (x y : Cay C μ) : (x - y).2 = x.2 - y.2 := rfl +@[simp] theorem fst_smul (c : k) (x : Cay C μ) : (c • x).1 = c • x.1 := rfl +@[simp] theorem snd_smul (c : k) (x : Cay C μ) : (c • x).2 = c • x.2 := rfl + +theorem ext {x y : Cay C μ} (h₁ : x.1 = y.1) (h₂ : x.2 = y.2) : x = y := Prod.ext h₁ h₂ + +/-- The element `u + v j` of `Cay(B, μ)`, with components `u` and `v`. Writing explicit elements +with `Cay.mk` rather than as a bare pair keeps their type `Cay C μ` visible, so that the lemmas +about the doubled multiplication apply to them. -/ +def mk (u v : B) : Cay C μ := (u, v) + +@[simp] theorem fst_mk (u v : B) : (mk u v : Cay C μ).1 = u := rfl +@[simp] theorem snd_mk (u v : B) : (mk u v : Cay C μ).2 = v := rfl + +variable (C μ) + +/-- The **Cayley–Dickson multiplication** `GPR 18.3`: +`(u₁ + v₁j)(u₂ + v₂j) = (u₁u₂ + μ (conj v₂)v₁) + (v₂u₁ + v₁(conj u₂)) j`. -/ +instance : Mul (Cay C μ) := + ⟨fun x y ↦ ((x.1 * y.1 + μ • (C.conj y.2 * x.2), y.2 * x.1 + x.2 * C.conj y.1) : B × B)⟩ + +instance : One (Cay C μ) := ⟨((1, 0) : B × B)⟩ + +variable {C μ} + +@[simp] theorem fst_mul (x y : Cay C μ) : (x * y).1 = x.1 * y.1 + μ • (C.conj y.2 * x.2) := rfl +@[simp] theorem snd_mul (x y : Cay C μ) : (x * y).2 = y.2 * x.1 + x.2 * C.conj y.1 := rfl +@[simp] theorem fst_one : (1 : Cay C μ).1 = 1 := rfl +@[simp] theorem snd_one : (1 : Cay C μ).2 = 0 := rfl + +variable (C μ) + +instance : NonAssocRing (Cay C μ) := + { (inferInstance : AddCommGroup (Cay C μ)), (inferInstance : Mul (Cay C μ)), + (inferInstance : One (Cay C μ)) with + left_distrib := fun x y z ↦ Cay.ext (by simp [mul_add, add_mul, smul_add]; abel) + (by simp [mul_add, add_mul]; abel) + right_distrib := fun x y z ↦ Cay.ext (by simp [mul_add, add_mul, smul_add]; abel) + (by simp [mul_add, add_mul]; abel) + zero_mul := fun x ↦ Cay.ext (by simp) (by simp) + mul_zero := fun x ↦ Cay.ext (by simp) (by simp) + one_mul := fun x ↦ Cay.ext (by simp) (by simp) + mul_one := fun x ↦ Cay.ext (by simp) (by simp) } + +instance : SMulCommClass k (Cay C μ) (Cay C μ) := + ⟨fun c x y ↦ Cay.ext + (by simp [mul_smul_comm, smul_mul_assoc, smul_comm c μ]) + (by simp [mul_smul_comm, smul_mul_assoc])⟩ + +instance : IsScalarTower k (Cay C μ) (Cay C μ) := + ⟨fun c x y ↦ Cay.ext + (by simp [mul_smul_comm, smul_mul_assoc, smul_comm c μ]) + (by simp [mul_smul_comm, smul_mul_assoc])⟩ + +end Cay + +/-! ### The conic structure -/ + +/-- The Cayley–Dickson norm `n(u + v j) = n_B(u) - μ n_B(v)`, i.e. `n_B ⊥ ⟨-μ⟩ n_B`. -/ +noncomputable def cayNorm : QuadraticForm k (Cay C μ) := + (QuadraticMap.prod C.norm ((-μ) • C.norm) : QuadraticForm k (B × B)) + +variable {C μ} + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +@[simp] theorem cayNorm_apply (x : Cay C μ) : + C.cayNorm μ x = C.norm x.1 - μ * C.norm x.2 := by + change C.norm x.1 + ((-μ) • C.norm) x.2 = _ + rw [smul_apply, smul_eq_mul] + ring + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +theorem polar_cayNorm (x y : Cay C μ) : + QuadraticMap.polar (C.cayNorm μ) x y = + QuadraticMap.polar C.norm x.1 y.1 - μ * QuadraticMap.polar C.norm x.2 y.2 := by + simp only [QuadraticMap.polar, cayNorm_apply, Cay.fst_add, Cay.snd_add] + ring + +variable (C μ) + +/-- **`GPR 18.4`: the Cayley–Dickson double of a conic algebra is a conic algebra.** + +The first component of `x * x` is `u² + μ (conj v)v = t(u)·u - n(u)·1 + μ n(v)·1`, and the second is +`vu + v(conj u) = v(u + conj u) = t(u)·v`. No hypothesis on `B` or on `μ`. -/ +noncomputable def cay : ConicAlgebra k (Cay C μ) where + norm := C.cayNorm μ + norm_one := by simp [C.norm_one] + mul_self x := by + have htrace : QuadraticMap.polar (C.cayNorm μ) 1 x = C.trace x.1 := by + rw [polar_cayNorm] + simp [trace_apply] + refine Cay.ext ?_ ?_ + · rw [Cay.fst_mul, Cay.fst_sub, Cay.fst_smul, Cay.fst_smul, htrace, cayNorm_apply, + Cay.fst_one, C.mul_self_eq x.1, C.conj_mul_self x.2] + module + · rw [Cay.snd_mul, Cay.snd_sub, Cay.snd_smul, Cay.snd_smul, htrace, Cay.snd_one, + smul_zero, sub_zero, ← mul_add, C.add_conj x.1, mul_smul_comm, mul_one] + +variable {C μ} + +@[simp] theorem cay_norm_apply (x : Cay C μ) : + (C.cay μ).norm x = C.norm x.1 - μ * C.norm x.2 := + cayNorm_apply x + +/-- **`GPR 18.4(5)`.** The trace of `Cay(B, μ)` is the trace of `B` on the first component. -/ +@[simp] theorem cay_trace_apply (x : Cay C μ) : (C.cay μ).trace x = C.trace x.1 := by + rw [trace_apply] + change QuadraticMap.polar (C.cayNorm μ) 1 x = _ + rw [polar_cayNorm] + simp [trace_apply] + +/-- **`GPR 18.4(6)`.** The conjugation of `Cay(B, μ)` is `u + v j ↦ conj u - v j`. -/ +@[simp] theorem cay_conj_apply (x : Cay C μ) : + (C.cay μ).conj x = ((C.conj x.1, -x.2) : Cay C μ) := by + refine Cay.ext ?_ ?_ + · rw [conj_apply, Cay.fst_sub, Cay.fst_smul, cay_trace_apply, Cay.fst_one, conj_apply] + · rw [conj_apply, Cay.snd_sub, Cay.snd_smul, Cay.snd_one, smul_zero, zero_sub] + +/-- `GPR 18.4(6)` on an explicit element: the conjugate of `u + v j` is `conj u - v j`. + +Not a simp lemma, since `cay_conj_apply` already rewrites its left-hand side; it is for `simp only` +calls that keep elements in `Cay.mk` form. -/ +theorem cay_conj_mk (u v : B) : + (C.cay μ).conj (Cay.mk u v) = Cay.mk (C.conj u) (-v) := by + rw [cay_conj_apply] + rfl + +/-! ### Functoriality -/ + +section Functoriality + +variable {B' : Type w} [NonAssocRing B'] [Module k B'] [SMulCommClass k B' B'] + [IsScalarTower k B' B'] (D : ConicAlgebra k B') + +/-- Equal Cayley–Dickson parameters give canonically isometric doubles. This explicit transport is +needed because the parameter is part of the type `Cay C μ`. -/ +noncomputable def cayIsometryEquivOfEq {a b : k} (h : a = b) : + (D.cay a).norm.IsometryEquiv (D.cay b).norm := by + subst b + exact QuadraticMap.IsometryEquiv.refl _ + +@[simp] theorem cayIsometryEquivOfEq_map_one {a b : k} (h : a = b) : + cayIsometryEquivOfEq D h (1 : Cay D a) = 1 := by + subst b + rfl + +theorem cayIsometryEquivOfEq_map_mul {a b : k} (h : a = b) (x y : Cay D a) : + cayIsometryEquivOfEq D h (x * y) = + cayIsometryEquivOfEq D h x * cayIsometryEquivOfEq D h y := by + subst b + rfl + +/-- A norm isometry acts componentwise on Cayley–Dickson doubles with the same parameter. + +No unitality or multiplicativity is needed for this statement: the doubled norm is the +orthogonal product `n ⊥ (-μ)n`. -/ +noncomputable def cayIsometryEquiv (e : C.norm.IsometryEquiv D.norm) : + (C.cay μ).norm.IsometryEquiv (D.cay μ).norm where + toLinearEquiv := + { toFun := fun x ↦ ((e x.1, e x.2) : Cay D μ) + invFun := fun x ↦ ((e.symm x.1, e.symm x.2) : Cay C μ) + map_add' := fun x y ↦ Cay.ext (map_add e x.1 y.1) (map_add e x.2 y.2) + map_smul' := fun c x ↦ Cay.ext (map_smul e c x.1) (map_smul e c x.2) + left_inv := fun x ↦ Cay.ext (e.symm_apply_apply x.1) (e.symm_apply_apply x.2) + right_inv := fun x ↦ Cay.ext (e.apply_symm_apply x.1) (e.apply_symm_apply x.2) } + map_app' x := + (cay_norm_apply ((e x.1, e x.2) : Cay D μ)).trans (by + rw [e.map_app, e.map_app] + exact (cay_norm_apply x).symm) + +@[simp] theorem cayIsometryEquiv_apply (e : C.norm.IsometryEquiv D.norm) (x : Cay C μ) : + cayIsometryEquiv D e x = ((e x.1, e x.2) : Cay D μ) := rfl + +/-- The componentwise equivalence of doubles is unital when the original equivalence is. -/ +theorem cayIsometryEquiv_map_one (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : B) = 1) : cayIsometryEquiv D e (1 : Cay C μ) = 1 := + Cay.ext h1 (map_zero e) + +/-- The componentwise equivalence of doubles is multiplicative when the original equivalence is +unital and multiplicative. -/ +theorem cayIsometryEquiv_map_mul (e : C.norm.IsometryEquiv D.norm) + (h1 : e (1 : B) = 1) (hmul : ∀ x y, e (x * y) = e x * e y) (x y : Cay C μ) : + cayIsometryEquiv D e (x * y) = cayIsometryEquiv D e x * cayIsometryEquiv D e y := by + have htrace (z : B) : D.trace (e z) = C.trace z := by + rw [trace_apply, trace_apply, QuadraticMap.polar, QuadraticMap.polar] + rw [show (1 : B') = e (1 : B) from h1.symm, ← map_add, e.map_app, e.map_app, e.map_app] + have hconj (z : B) : D.conj (e z) = e (C.conj z) := by + rw [conj_apply, conj_apply, htrace, map_sub, map_smul, h1] + apply Cay.ext + · change e (x.1 * y.1 + μ • (C.conj y.2 * x.2)) = + e x.1 * e y.1 + μ • (D.conj (e y.2) * e x.2) + rw [map_add, map_smul, hmul, hmul, hconj] + · change e (y.2 * x.1 + x.2 * C.conj y.1) = + e y.2 * e x.1 + e x.2 * D.conj (e y.1) + rw [map_add, hmul, hmul, hconj] + +end Functoriality + +/-! ### `GPR 18.11`: the conjugation of the double -/ + +/-- **`GPR 18.11`.** If the conjugation of `B` is an involution then so is the conjugation of +`Cay(B, μ)`. No associativity and no hypothesis on `μ`: the verification is the two component +identities `conj(u₁u₂ + μ (conj v₂)v₁) = (conj u₂)(conj u₁) + μ (conj v₁)v₂` and +`-(v₂u₁ + v₁(conj u₂)) = -v₂u₁ - v₁(conj u₂)`. -/ +theorem ConjIsInvolution.cay (hconj : C.ConjIsInvolution) : (C.cay μ).ConjIsInvolution := by + intro x y + rw [cay_conj_apply, cay_conj_apply, cay_conj_apply] + refine Cay.ext ?_ ?_ + · change C.conj (x.1 * y.1 + μ • (C.conj y.2 * x.2)) + = C.conj y.1 * C.conj x.1 + μ • (C.conj (-x.2) * -y.2) + rw [map_add, map_smul, hconj, hconj, conj_conj, map_neg, neg_mul_neg] + · change -(y.2 * x.1 + x.2 * C.conj y.1) + = -x.2 * C.conj y.1 + -y.2 * C.conj (C.conj x.1) + rw [conj_conj, neg_mul, neg_mul, neg_add] + abel + +/-! ### The embedding of `B` -/ + +variable (C μ) + +/-- **`GPR 18.3`.** The embedding `u ↦ u + 0 j` of `B` into `Cay(B, μ)`. It is injective, unital +and multiplicative, so `B` is a unital subalgebra of its double. -/ +def inl : B →ₗ[k] Cay C μ where + toFun u := ((u, 0) : B × B) + map_add' u u' := Cay.ext rfl (by change (0 : B) = 0 + 0; rw [add_zero]) + map_smul' c u := Cay.ext rfl (by change (0 : B) = c • (0 : B); rw [smul_zero]) + +variable {C μ} + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +@[simp] theorem inl_apply (u : B) : C.inl μ u = ((u, 0) : Cay C μ) := rfl + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +theorem inl_one : C.inl μ 1 = 1 := rfl + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +theorem inl_mul (u u' : B) : C.inl μ (u * u') = C.inl μ u * C.inl μ u' := + Cay.ext (by change u * u' = u * u' + μ • (C.conj 0 * 0); simp) + (by change (0 : B) = 0 * u + 0 * C.conj u'; simp) + +omit [SMulCommClass k B B] [IsScalarTower k B B] in +theorem inl_injective : Function.Injective (C.inl μ) := fun _ _ h ↦ congrArg Prod.fst h + +theorem norm_inl (u : B) : (C.cay μ).norm (C.inl μ u) = C.norm u := by + rw [cay_norm_apply] + change C.norm u - μ * C.norm 0 = C.norm u + simp + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAlternative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAlternative.lean new file mode 100644 index 0000000000..939a6a5660 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAlternative.lean @@ -0,0 +1,222 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson + +/-! +# The double is alternative exactly when the base is associative (`GPR 18.14(c)`) + +`Cay(B, μ)` is alternative **if and only if** `B` is associative and the conjugation of `B` is an +involution (`GPR 18.14(c)`). Both directions are proved here, for every scalar `μ` and with no +hypothesis on `B` beyond the conic structure. + +The direction `⇐` is the one that builds algebras: octonions from quaternions, quaternions from +quadratic étale algebras. The direction `⇒` is what stops the tower — it is the source of the +rank dichotomy `1, 2, 4, 8` (`GPR 19.18`), since the fourth double is alternative only if the +third is associative, which it is not. + +## The hypotheses of `⇐` + +Both are needed, and neither is free: + +* **`B` associative**, as the explicit hypothesis `∀ a b c : B, a * b * c = a * (b * c)` rather + than a `Ring B` instance, so that the same statement serves both directions of the equivalence: + the converse produces associativity of a `B` that is only a `NonAssocRing`, and cannot produce + an instance. `ConicAlgebra.isAlternative_cay` below is the `[Ring B] [Algebra k B]` form, which + is what the Cayley–Dickson tower consumes. +* **The conjugation of `B` is an involution** (`ConicAlgebra.ConjIsInvolution`). This does *not* + follow from associativity over an arbitrary base — `Conic/TraceDefectCounterexample.lean` is an + associative conic algebra whose conjugation is not an anti-homomorphism — but it does hold as + soon as `B` is finitely generated projective (`ConicAlgebra.conjIsInvolution_of_projective`) or + the base is a field (`ConicAlgebra.conj_mul`). + +`μ` remains an arbitrary scalar, in both directions. In particular the converse needs no unit +hypothesis: it reads off the two conclusions from products in which every `μ` has already +cancelled. + +## The proof of `⇐` + +Write `x = a + bj`, `y = c + dj`. Expanding the two alternative laws in components and using only + +* associativity of `B`, +* anti-multiplicativity of the conjugation, +* `conj z = t(z) · 1 - z` (`ConicAlgebra.conj_apply`), which turns every conjugate into a scalar + multiple of `1` minus the element, and +* `z² = t(z) · z - n(z) · 1` (`ConicAlgebra.mul_self_eq`) for `z = a` and `z = b`, + +turns each of the four component identities into an identity between `k`-linear combinations of +the same products, which `module` closes. This is `GPR`'s "lengthy but straightforward +computation" of `GPR 18.13` specialized to `u₁ = u₂`, `v₁ = v₂`; here it is a single `simp only` +with a normalizing rewrite set, because eliminating the conjugation first makes all the +cancellations linear. + +## The proof of `⇒` + +Each conclusion is one component of one instance of one alternative law, so neither uses the +other, and neither uses `μ`. + +* **Involutivity** is the `j`-component of left alternativity at `x = a + j`, `y = c`: + + `(conj c) a + conj(ac) = t(a) (conj c)`, + +and `t(a) (conj c) - (conj c) a = (conj c) (conj a)`. The element `b` multiplying the conjugate in +the general computation is here specialized to `1`, which is what makes the defect visible without +any faithfulness hypothesis: `GPR 16.10(a)` only places the trace defect in `Ann(B)`, but `B` is +unital, so it vanishes. +* **Associativity** is the `j`-component of the linearized right alternative law + (`IsAlternative.right_alt_linearized`) at `x = a`, `y = b`, `z = cj`: + + `a(bc) + (ab)(conj c) = (ac)b + (a(conj c))b`, + + in which expanding `conj c = t(c) · 1 - c` cancels both the trace terms and the two products that + are not associated, leaving `abc = a(bc)`. Note that this is the linearization, not either + alternative law itself: the plain laws applied to elements of these shapes give back only + alternativity of `B` and the commutator identity, never associativity. + +## Implementation notes + +⚠ The elements `(a, 1)`, `(0, c)` and friends must be introduced **opaquely** — as local +constants of type `Cay C μ` whose components are fixed by hypotheses — and not as pair literals +ascribed to `Cay C μ`. A literal `((a, 1) : Cay C μ)` still elaborates with inferred type `B × B`, +so `ConicAlgebra.Cay.fst_mul` and `ConicAlgebra.Cay.snd_mul`, whose implicit `C` and `μ` are +determined only by that type, no longer unify and every rewrite silently fails. + +## Main results + +* `ConicAlgebra.isAlternative_cay_iff` : **`GPR 18.14(c)`**, the equivalence. +* `ConicAlgebra.isAlternative_cay_of_mul_assoc`, `ConicAlgebra.isAlternative_cay` : the + direction `⇐`, the second in the `[Ring B]` form the tower uses. +* `ConicAlgebra.mul_assoc_of_isAlternative_cay`, + `ConicAlgebra.conjIsInvolution_of_isAlternative_cay` : the two halves of `⇒`. +* `ConicAlgebra.not_isAlternative_cay_of_mul_mul_ne` : the contrapositive, in the form a + non-associativity witness for `B` consumes. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.13, 18.14(c). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section NonAssoc + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [SMulCommClass k B B] [IsScalarTower k B B] + +/-! ### The double of an associative algebra is alternative -/ + +omit [IsScalarTower k B B] in +/-- Reassociating `z b b` when `b² = t(b) b - n(b) 1`. This is the one place associativity of `B` +is used that the simp set cannot reach on its own: the product `(z * b) * b` has no `b * b` +subterm. -/ +private theorem mul_mul_self (C : ConicAlgebra k B) + (hassoc : ∀ a b c : B, a * b * c = a * (b * c)) (b z : B) : + z * b * b = C.trace b • (z * b) - C.norm b • z := by + rw [hassoc, C.mul_self_eq, mul_sub, mul_smul_comm, mul_smul_comm, mul_one] + +/-- **`GPR 18.14(c)`, `⇐`.** If `B` is associative and its conjugation is an involution, then +`Cay(B, μ)` is alternative, for every scalar `μ`. + +Stated with associativity as a hypothesis rather than an instance, so that it can be paired with +`ConicAlgebra.mul_assoc_of_isAlternative_cay` into the equivalence +`ConicAlgebra.isAlternative_cay_iff`. For an associative `B` use `ConicAlgebra.isAlternative_cay`, +which takes `mul_assoc` from the instance. -/ +theorem isAlternative_cay_of_mul_assoc (C : ConicAlgebra k B) (μ : k) + (hassoc : ∀ a b c : B, a * b * c = a * (b * c)) (hconj : C.ConjIsInvolution) : + IsAlternative (Cay C μ) where + left_alt x y := by + refine Cay.ext ?_ ?_ <;> + simp only [Cay.fst_mul, Cay.snd_mul, map_add, map_smul, hconj.conj_mul, conj_conj, + C.conj_apply x.1, C.conj_apply x.2, mul_add, add_mul, mul_sub, sub_mul, smul_mul_assoc, + mul_smul_comm, smul_add, smul_sub, mul_one, one_mul, ← hassoc, + C.mul_self_eq x.1, C.mul_self_eq x.2, mul_mul_self C hassoc x.1, + mul_mul_self C hassoc x.2] <;> + module + right_alt x y := by + refine Cay.ext ?_ ?_ <;> + simp only [Cay.fst_mul, Cay.snd_mul, map_add, map_sub, map_smul, hconj.conj_mul, conj_one, + C.conj_apply x.1, C.conj_apply x.2, mul_add, add_mul, mul_sub, sub_mul, smul_mul_assoc, + mul_smul_comm, smul_add, smul_sub, mul_one, one_mul, ← hassoc, + C.mul_self_eq x.1, C.mul_self_eq x.2, mul_mul_self C hassoc x.1] <;> + module + +/-! ### The base of an alternative double is associative with involutive conjugation -/ + +/-- **`GPR 18.14(c)`, `⇒`, first half.** If `Cay(B, μ)` is alternative then the conjugation of `B` +is an involution. + +The `j`-component of left alternativity at `x = a + j` and `y = c` reads +`(conj c) a + conj(ac) = t(a) (conj c)`, and `t(a) (conj c) - (conj c) a` is `(conj c) (conj a)` by +`ConicAlgebra.conj_apply`. No hypothesis on `μ`, and no associativity of `B`: taking the `j`-part of +`x` to be `1` removes every product in which `μ` or a reassociation could appear. -/ +theorem conjIsInvolution_of_isAlternative_cay (C : ConicAlgebra k B) (μ : k) + (h : IsAlternative (Cay C μ)) : C.ConjIsInvolution := by + intro a c + obtain ⟨x, hx1, hx2⟩ : ∃ x : Cay C μ, x.1 = a ∧ x.2 = 1 := ⟨(a, 1), rfl, rfl⟩ + obtain ⟨y, hy1, hy2⟩ : ∃ y : Cay C μ, y.1 = c ∧ y.2 = 0 := ⟨(c, 0), rfl, rfl⟩ + have key := congrArg Prod.snd (h.left_alt x y) + simp only [Cay.fst_mul, Cay.snd_mul, hx1, hx2, hy1, hy2, map_zero, zero_mul, smul_zero, + add_zero, zero_add, one_mul, mul_one] at key + rw [C.add_conj a, smul_mul_assoc, one_mul] at key + rw [C.conj_apply a, mul_sub, mul_smul_comm, mul_one] + linear_combination (norm := module) key + +/-- **`GPR 18.14(c)`, `⇒`, second half.** If `Cay(B, μ)` is alternative then `B` is associative. + +The `j`-component of the linearized right alternative law at `x = a`, `y = b`, `z = cj` reads +`a(bc) + (ab)(conj c) = (ac)b + (a(conj c))b`; expanding `conj c = t(c) · 1 - c` cancels the trace +terms against the two products that are not associated. No hypothesis on `μ`: every product below +has a zero component where `μ` would enter. -/ +theorem mul_assoc_of_isAlternative_cay (C : ConicAlgebra k B) (μ : k) + (h : IsAlternative (Cay C μ)) (a b c : B) : a * b * c = a * (b * c) := by + let := h + obtain ⟨x, hx1, hx2⟩ : ∃ x : Cay C μ, x.1 = b ∧ x.2 = 0 := ⟨(b, 0), rfl, rfl⟩ + obtain ⟨y, hy1, hy2⟩ : ∃ y : Cay C μ, y.1 = c ∧ y.2 = 0 := ⟨(c, 0), rfl, rfl⟩ + obtain ⟨z, hz1, hz2⟩ : ∃ z : Cay C μ, z.1 = 0 ∧ z.2 = a := ⟨(0, a), rfl, rfl⟩ + have key := congrArg Prod.snd (IsAlternative.right_alt_linearized x y z) + simp only [Cay.snd_add, Cay.fst_mul, Cay.snd_mul, hx1, hx2, hy1, hy2, hz1, hz2, map_zero, + zero_mul, mul_zero, smul_zero, add_zero, zero_add] at key + simp only [C.conj_apply c, mul_sub, sub_mul, mul_smul_comm, smul_mul_assoc, mul_one] at key + linear_combination (norm := module) -key + +/-- **`GPR 18.14(c)`.** The Cayley–Dickson double `Cay(B, μ)` is alternative exactly when `B` is +associative and its conjugation is an involution — for every scalar `μ`. -/ +theorem isAlternative_cay_iff (C : ConicAlgebra k B) (μ : k) : + IsAlternative (Cay C μ) ↔ + (∀ a b c : B, a * b * c = a * (b * c)) ∧ C.ConjIsInvolution := + ⟨fun h ↦ + ⟨mul_assoc_of_isAlternative_cay C μ h, conjIsInvolution_of_isAlternative_cay C μ h⟩, + fun h ↦ isAlternative_cay_of_mul_assoc C μ h.1 h.2⟩ + +/-- **The double of a non-associative algebra is not alternative.** The contrapositive of +`ConicAlgebra.mul_assoc_of_isAlternative_cay`, in the form that a single witness to the failure of +associativity in `B` consumes: this is what makes the fourth Cayley–Dickson rung — the sedenions, +`GPR 19.23` — fail to be alternative, and hence fail to be a composition algebra. -/ +theorem not_isAlternative_cay_of_mul_mul_ne (C : ConicAlgebra k B) (μ : k) {a b c : B} + (hne : a * b * c ≠ a * (b * c)) : ¬ IsAlternative (Cay C μ) := + fun h ↦ hne (mul_assoc_of_isAlternative_cay C μ h a b c) + +end NonAssoc + +/-! ### The associative case + +The form the Cayley–Dickson tower consumes: `B` associative as an instance, which is what +`Conic/CayleyDicksonAssociative.lean` supplies for a double. -/ + +variable {k : Type u} {B : Type v} [CommRing k] [Ring B] [Algebra k B] + +/-- **`GPR 18.14(c)`, `⇐`, for an associative `B`.** If the conjugation of an associative conic +algebra `B` is an involution, then `Cay(B, μ)` is alternative, for every scalar `μ`. -/ +theorem isAlternative_cay (C : ConicAlgebra k B) (μ : k) (hconj : C.ConjIsInvolution) : + IsAlternative (Cay C μ) := + isAlternative_cay_of_mul_assoc C μ (fun a b c ↦ mul_assoc a b c) hconj + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean new file mode 100644 index 0000000000..f124709da6 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean @@ -0,0 +1,184 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson + +/-! +# Commutativity and associativity of the double (`GPR 18.14(a),(b)`) + +`Cay(B, μ)` is associative **if and only if** `B` is commutative and associative with involutive +conjugation (`GPR 18.14(b)`), and commutative **if and only if** `B` is the base ring +(`GPR 18.14(a)`). This file proves the directions that build algebras, and packages them as `Ring`, +`CommRing` and `Algebra` structures on the double so that the Cayley–Dickson tower can be iterated. + +The two results play different roles. Associativity of `Cay(B, μ)` is what +`ConicAlgebra.isMultiplicative_cay` and `ConicAlgebra.isAlternative_cay` need of *their* input, so +it is what carries the tower from one rung to the next. Commutativity is needed only once, to get +the tower started: `mul_assoc_cay` asks its input to be commutative, and the first double +`Cay(k, μ)` is the last rung for which that is true. + +Iteration is the whole point. `ConicAlgebra.isMultiplicative_cay` (`GPR 18.15`) and +`ConicAlgebra.isAlternative_cay` (`GPR 18.14(c)`) both require their input `B` to be *associative*, +which for a double `Cay(B₀, μ₀)` is exactly what this file supplies. Without it the tower stops one +rung up from the base ring. + +## The computation + +Write `x = (a, b)`, `y = (c, d)`, `z = (e, f)`. Both components of `(xy)z` and of `x(yz)` expand +into four terms each, and they match term by term using only + +* anti-multiplicativity of the conjugation of `B`, to push `conj` through the products it meets + (`conj (fc) = (conj c) (conj f)`, `conj (d (conj e)) = e (conj d)`), and +* commutativity and associativity of `B`, to reorder the resulting monomials. + +The conjugates `conj a, conj c, conj e, …` are never expanded via `conj z = t(z)·1 - z`; they behave +as atoms throughout. This is unlike `Conic/CayleyDicksonAlternative.lean`, where eliminating the +conjugation first is what makes the cancellations linear — here commutativity does that job instead, +and `ring` closes both components. + +## Main results + +* `ConicAlgebra.mul_assoc_cay` : **`GPR 18.14(b)`, `⇐`**. +* `ConicAlgebra.mul_comm_cay` : **`GPR 18.14(a)`, `⇐`**. +* `ConicAlgebra.exists_mul_ne_mul_cay`, `ConicAlgebra.exists_mul_mul_ne_mul_mul_cay` : explicit + witnesses for the failure of commutativity and of associativity. +* `ConicAlgebra.Cay.ring`, `ConicAlgebra.Cay.algebra`, `ConicAlgebra.Cay.commRing` : the resulting + structures. + +## Implementation notes + +`Cay.ring` and `Cay.algebra` are **`def`s, not instances**: associativity of the double depends on +hypotheses on `B` (`CommRing`, and involutivity of the conjugation) that instance search cannot +discharge, and a global instance would be unsound. Use them with `letI` at the point where the next +rung of the tower is built. `Cay.algebra` is `Algebra.ofModule`, which needs exactly the +`SMulCommClass`/`IsScalarTower` pair the double already carries. + +⚠ The involutivity hypothesis does *not* follow from commutativity and associativity over an +arbitrary base — see the trace-defect counterexample over `ℤ/4` — but it does as soon as `B` is +finitely generated projective, or the base is a field. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.13, + 18.14(a),(b). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {B : Type v} [CommRing k] [CommRing B] [Algebra k B] + (C : ConicAlgebra k B) (μ : k) + +/-- **`GPR 18.14(b)`, `⇐`.** If `B` is commutative associative and its conjugation is an +involution, then `Cay(B, μ)` is associative, for every scalar `μ`. -/ +theorem mul_assoc_cay (hconj : C.ConjIsInvolution) (x y z : Cay C μ) : + x * y * z = x * (y * z) := by + have halg : ∀ r : k, C.conj (algebraMap k B r) = algebraMap k B r := fun r ↦ by + rw [Algebra.algebraMap_eq_smul_one, map_smul, conj_one] + refine Cay.ext ?_ ?_ <;> + simp only [Cay.fst_mul, Cay.snd_mul, map_add, hconj.conj_mul, conj_conj, mul_add, add_mul, + Algebra.smul_def, halg] <;> + ring + +/-- The double of a commutative associative conic algebra with involutive conjugation, as a +`Ring`. A `def`, not an instance: see the module docstring. -/ +@[instance_reducible] def Cay.ring (hconj : C.ConjIsInvolution) : Ring (Cay C μ) := + { (inferInstance : NonAssocRing (Cay C μ)) with + mul_assoc := mul_assoc_cay C μ hconj } + +/-- The double as a `k`-algebra, given the `Ring` structure of `ConicAlgebra.Cay.ring`. Built by +`Algebra.ofModule` from the `SMulCommClass`/`IsScalarTower` instances the double already has. -/ +@[instance_reducible] def Cay.algebra (hconj : C.ConjIsInvolution) : + letI := Cay.ring C μ hconj + Algebra k (Cay C μ) := + letI := Cay.ring C μ hconj + Algebra.ofModule (fun r x y ↦ by exact smul_mul_assoc r x y) + (fun r x y ↦ by exact mul_smul_comm r x y) + +/-! ### Failure of commutativity and associativity (`GPR 18.14(a),(b)`, `⇒`) + +The contrapositives, in the explicit form the tower needs: a witness that `B`'s conjugation is not +the identity produces a witness that the double is not commutative, and a witness that `B` is not +commutative produces a witness that the double is not associative. These are what show the +Cayley–Dickson tower really does lose a property at each step rather than merely failing to +preserve it. -/ + +section Failure + +variable {k' : Type u} {B' : Type v} [CommRing k'] [NonAssocRing B'] [Module k' B'] + [SMulCommClass k' B' B'] [IsScalarTower k' B' B'] (C' : ConicAlgebra k' B') (μ' : k') + +omit [SMulCommClass k' B' B'] [IsScalarTower k' B' B'] in +/-- **`Cay(B, μ)` is not commutative** as soon as the conjugation of `B` moves some element: +`(u, 0)(0, 1) = (0, u)` while `(0, 1)(u, 0) = (0, conj u)`. -/ +theorem exists_mul_ne_mul_cay {u : B'} (h : C'.conj u ≠ u) : + ∃ x y : Cay C' μ', x * y ≠ y * x := by + set x : Cay C' μ' := ((u, 0) : B' × B') with hx + set y : Cay C' μ' := ((0, 1) : B' × B') with hy + refine ⟨x, y, fun hcon ↦ h ?_⟩ + have h2 : (x * y).2 = (y * x).2 := by rw [hcon] + have hx1 : x.1 = u := rfl + have hx2 : x.2 = (0 : B') := rfl + have hy1 : y.1 = (0 : B') := rfl + have hy2 : y.2 = (1 : B') := rfl + simp only [Cay.snd_mul, hx1, hx2, hy1, hy2, map_zero, mul_zero, add_zero, zero_add, + one_mul] at h2 + exact h2.symm + +omit [SMulCommClass k' B' B'] [IsScalarTower k' B' B'] in +/-- **`Cay(B, μ)` is not associative** as soon as `B` is not commutative. With `x = (0, 1)`, +`y = (conj a, 0)` and `z = (conj c, 0)`, the second components of `(xy)z` and `x(yz)` are `ac` and +`ca`. -/ +theorem exists_mul_mul_ne_mul_mul_cay (hconj : C'.ConjIsInvolution) {a c : B'} + (h : a * c ≠ c * a) : ∃ x y z : Cay C' μ', x * y * z ≠ x * (y * z) := by + set x : Cay C' μ' := ((0, 1) : B' × B') with hx + set y : Cay C' μ' := ((C'.conj a, 0) : B' × B') with hy + set z : Cay C' μ' := ((C'.conj c, 0) : B' × B') with hz + refine ⟨x, y, z, fun hcon ↦ h ?_⟩ + have h2 : (x * y * z).2 = (x * (y * z)).2 := by rw [hcon] + have hx1 : x.1 = (0 : B') := rfl + have hx2 : x.2 = (1 : B') := rfl + have hy1 : y.1 = C'.conj a := rfl + have hy2 : y.2 = (0 : B') := rfl + have hz1 : z.1 = C'.conj c := rfl + have hz2 : z.2 = (0 : B') := rfl + simp only [Cay.snd_mul, Cay.fst_mul, hx1, hx2, hy1, hy2, hz1, hz2, map_zero, mul_zero, + zero_mul, add_zero, zero_add, smul_zero, one_mul, mul_one, conj_conj, + hconj.conj_mul] at h2 + exact h2 + +end Failure + +/-! ### Commutativity (`GPR 18.14(a)`) -/ + +/-- If the conjugation of a commutative `B` is the **identity** then `Cay(B, μ)` is commutative. + +Both products come out as `(ac + μ db, da + bc)`; only commutativity of `B` is used, since with +`conj = id` there is nothing left for the conjugation to do. The hypothesis holds for the base ring +(`ConicAlgebra.baseRing_conj_apply`) and essentially only there — `GPR 18.14(a)` says +`Cay(B, μ)` is commutative exactly when `B = k`. -/ +theorem mul_comm_cay (hconj : ∀ u : B, C.conj u = u) (x y : Cay C μ) : x * y = y * x := by + refine Cay.ext ?_ ?_ <;> + simp only [Cay.fst_mul, Cay.snd_mul, hconj, Algebra.smul_def] <;> ring + +/-- With the conjugation of `B` the identity, the conjugation is automatically an involution: the +condition `conj (xy) = conj y * conj x` reduces to `xy = yx`. -/ +theorem conjIsInvolution_of_conj_eq_id (hconj : ∀ u : B, C.conj u = u) : C.ConjIsInvolution := + fun x y ↦ by rw [hconj, hconj, hconj, mul_comm] + +/-- The double of a commutative conic algebra whose conjugation is the identity, as a `CommRing`. +This is the instance that gets the Cayley–Dickson tower off the ground: it makes `Cay(k, μ₁)` +commutative, which is what `ConicAlgebra.mul_assoc_cay` needs in order to make `Cay(Cay(k, μ₁), μ₂)` +associative. A `def`, not an instance — see the module docstring. -/ +@[instance_reducible] def Cay.commRing (hconj : ∀ u : B, C.conj u = u) : CommRing (Cay C μ) := + { Cay.ring C μ (conjIsInvolution_of_conj_eq_id C hconj) with + mul_comm := mul_comm_cay C μ hconj } + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonConverse.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonConverse.lean new file mode 100644 index 0000000000..541cdf60bf --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonConverse.lean @@ -0,0 +1,222 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAlternative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAssociative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective + +/-! +# The converse halves of `GPR 18.14` and `GPR 18.15` + +`Conic/CayleyDicksonAssociative.lean` proves the directions of `GPR 18.14(a),(b)` that *build* +algebras — if `B` is commutative with trivial conjugation then `Cay(B, μ)` is commutative, and if +`B` is commutative associative with involutive conjugation then `Cay(B, μ)` is associative — and +records two explicit failure witnesses. `Conic/CayleyDicksonAlternative.lean` proves both +directions of `GPR 18.14(c)`. + +This file supplies the remaining implications, so that `GPR 18.14(a)` and `GPR 18.14(b)` become +equivalences, and then discharges their conjugation hypotheses over a projective module to obtain +`GPR 18.15`. + +## Method + +Nothing here needs the associator formulas of `GPR 18.13`. Each converse is read off from a single +well-chosen instance, exactly as in `GPR 18.14(c)`: + +* `B` embeds in the double as the elements `(u, 0)`, and that embedding respects products. So any + identity holding in `Cay(B, μ)` holds in `B` — this gives commutativity and associativity of `B` + at once, with no hypothesis on `μ`. +* The conjugation is handled by the failure witnesses already available: `(u, 0)(0, 1) = (0, u)` + while `(0, 1)(u, 0) = (0, conj u)`, so commutativity of the double forces `conj u = u`; and an + associative double is alternative, so `ConicAlgebra.conjIsInvolution_of_isAlternative_cay` + applies. +* Commutativity of `B` under an associative double is the contrapositive of + `ConicAlgebra.exists_mul_mul_ne_mul_mul_cay`, whose conjugation hypothesis the previous point + has just supplied. + +## Main results + +* `ConicAlgebra.mul_comm_of_mul_comm_cay`, `ConicAlgebra.conj_eq_id_of_mul_comm_cay` : + **`GPR 18.14(a)`, `⇒`**. +* `ConicAlgebra.mul_comm_cay_iff` : **`GPR 18.14(a)`**, the equivalence. +* `ConicAlgebra.mul_assoc_of_mul_assoc_cay`, `ConicAlgebra.conjIsInvolution_of_mul_assoc_cay`, + `ConicAlgebra.mul_comm_of_mul_assoc_cay` : **`GPR 18.14(b)`, `⇒`**. +* `ConicAlgebra.mul_assoc_cay_iff` : **`GPR 18.14(b)`**, the equivalence. +* `ConicAlgebra.isAlternative_cay_iff_of_projective`, + `ConicAlgebra.mul_assoc_cay_iff_of_projective` : **`GPR 18.15`(b),(a)** — over a finitely + generated projective module the hypothesis on the conjugation of `B` is automatic + (`GPR 16.14(b)`), so the criteria become conditions on the multiplication of `B` alone. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.14, 18.15, + 16.14(b). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section General + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [instSMulComm : SMulCommClass k B B] [instTower : IsScalarTower k B B] + (C : ConicAlgebra k B) (μ : k) + +omit instSMulComm instTower in +/-- On elements with zero `j`-part the product of the double is the product of `B`: the `μ`-term +of the first component needs a nonzero `j`-part. -/ +theorem Cay.fst_mul_of_snd_eq_zero {x y : Cay C μ} (hy : y.2 = 0) : + (x * y).1 = x.1 * y.1 := by + simp only [Cay.fst_mul, hy, map_zero, zero_mul, smul_zero, add_zero] + +omit instSMulComm instTower in +/-- Elements with zero `j`-part are closed under multiplication. -/ +theorem Cay.snd_mul_of_snd_eq_zero {x y : Cay C μ} (hx : x.2 = 0) (hy : y.2 = 0) : + (x * y).2 = 0 := by + simp only [Cay.snd_mul, hx, hy, zero_mul, add_zero] + +omit instSMulComm instTower in +/-- **`GPR 18.14(a)`, `⇒`, first half.** A commutative double forces `B` commutative, since `B` +sits inside it as the elements with zero `j`-part. -/ +theorem mul_comm_of_mul_comm_cay (h : ∀ x y : Cay C μ, x * y = y * x) (a b : B) : + a * b = b * a := by + obtain ⟨x, hx1, hx2⟩ : ∃ x : Cay C μ, x.1 = a ∧ x.2 = 0 := ⟨(a, 0), rfl, rfl⟩ + obtain ⟨y, hy1, hy2⟩ : ∃ y : Cay C μ, y.1 = b ∧ y.2 = 0 := ⟨(b, 0), rfl, rfl⟩ + have key : (x * y).1 = (y * x).1 := by rw [h x y] + rwa [Cay.fst_mul_of_snd_eq_zero C μ hy2, Cay.fst_mul_of_snd_eq_zero C μ hx2, hx1, hy1] at key + +omit instSMulComm instTower in +/-- **`GPR 18.14(a)`, `⇒`, second half.** A commutative double forces the conjugation of `B` to be +the identity. This is the contrapositive of `ConicAlgebra.exists_mul_ne_mul_cay`. -/ +theorem conj_eq_id_of_mul_comm_cay (h : ∀ x y : Cay C μ, x * y = y * x) (u : B) : + C.conj u = u := by + by_contra hu + obtain ⟨x, y, hxy⟩ := exists_mul_ne_mul_cay C μ hu + exact hxy (h x y) + +omit instSMulComm instTower in +/-- **`GPR 18.14(b)`, `⇒`, first half.** An associative double forces `B` associative, by the same +embedding. No hypothesis on `μ`. -/ +theorem mul_assoc_of_mul_assoc_cay (h : ∀ x y z : Cay C μ, x * y * z = x * (y * z)) + (a b c : B) : a * b * c = a * (b * c) := by + obtain ⟨x, hx1, hx2⟩ : ∃ x : Cay C μ, x.1 = a ∧ x.2 = 0 := ⟨(a, 0), rfl, rfl⟩ + obtain ⟨y, hy1, hy2⟩ : ∃ y : Cay C μ, y.1 = b ∧ y.2 = 0 := ⟨(b, 0), rfl, rfl⟩ + obtain ⟨z, hz1, hz2⟩ : ∃ z : Cay C μ, z.1 = c ∧ z.2 = 0 := ⟨(c, 0), rfl, rfl⟩ + have hxy : (x * y).2 = 0 := Cay.snd_mul_of_snd_eq_zero C μ hx2 hy2 + have hyz : (y * z).2 = 0 := Cay.snd_mul_of_snd_eq_zero C μ hy2 hz2 + have key : (x * y * z).1 = (x * (y * z)).1 := by rw [h x y z] + rwa [Cay.fst_mul_of_snd_eq_zero C μ hz2, Cay.fst_mul_of_snd_eq_zero C μ hy2, + Cay.fst_mul_of_snd_eq_zero C μ hyz, Cay.fst_mul_of_snd_eq_zero C μ hz2, hx1, hy1, hz1] at key + +omit instSMulComm instTower in +/-- An associative double is alternative. -/ +theorem isAlternative_cay_of_mul_assoc_cay (h : ∀ x y z : Cay C μ, x * y * z = x * (y * z)) : + IsAlternative (Cay C μ) where + left_alt a b := (h a a b).symm + right_alt a b := h b a a + +include instSMulComm instTower in +/-- **The converse of the multiplicativity criterion.** If the norm of `Cay(B, μ)` permits +composition then so does the norm of `B`, for every `μ`. + +Same embedding: `n_{Cay}(u, 0) = n_B(u) - μ·n_B(0) = n_B(u)`, and `(u, 0)(v, 0) = (uv, 0)`. + +⚠ This is the converse *implication*, not the sharp criterion. `GPR Exc. 18.18` says that for `B` +multiplicative, `Cay(B, μ)` is multiplicative **if and only if** `μ[B, B, B] ⊆ Rad(Dn_B)`; that +characterization needs the associator formulas of `GPR 18.13` and is not proved here. The forward +implication proved elsewhere (`ConicAlgebra.isMultiplicative_cay`) is the case `[B, B, B] = 0`. -/ +theorem isMultiplicative_of_isMultiplicative_cay (h : (C.cay μ).IsMultiplicative) : + C.IsMultiplicative := by + intro a b + obtain ⟨x, hx1, hx2⟩ : ∃ x : Cay C μ, x.1 = a ∧ x.2 = 0 := ⟨(a, 0), rfl, rfl⟩ + obtain ⟨y, hy1, hy2⟩ : ∃ y : Cay C μ, y.1 = b ∧ y.2 = 0 := ⟨(b, 0), rfl, rfl⟩ + have hxy : (x * y).2 = 0 := Cay.snd_mul_of_snd_eq_zero C μ hx2 hy2 + have key := h x y + simp only [cay, cayNorm_apply, hxy, hx2, hy2, map_zero, mul_zero, sub_zero, + Cay.fst_mul_of_snd_eq_zero C μ hy2, hx1, hy1] at key + exact key + +include instSMulComm instTower in +/-- **`GPR 18.14(b)`, `⇒`, second half.** An associative double is alternative, so +`ConicAlgebra.conjIsInvolution_of_isAlternative_cay` applies. -/ +theorem conjIsInvolution_of_mul_assoc_cay (h : ∀ x y z : Cay C μ, x * y * z = x * (y * z)) : + C.ConjIsInvolution := + conjIsInvolution_of_isAlternative_cay C μ (isAlternative_cay_of_mul_assoc_cay C μ h) + +include instSMulComm instTower in +/-- **`GPR 18.14(b)`, `⇒`, third half.** An associative double forces `B` *commutative*. + +This is the one implication that is not an embedding argument. It is the contrapositive of +`ConicAlgebra.exists_mul_mul_ne_mul_mul_cay`, whose hypothesis that the conjugation of `B` be an +involution is supplied by `ConicAlgebra.conjIsInvolution_of_mul_assoc_cay`. -/ +theorem mul_comm_of_mul_assoc_cay (h : ∀ x y z : Cay C μ, x * y * z = x * (y * z)) (a c : B) : + a * c = c * a := by + by_contra hac + obtain ⟨x, y, z, hxyz⟩ := + exists_mul_mul_ne_mul_mul_cay C μ (conjIsInvolution_of_mul_assoc_cay C μ h) hac + exact hxyz (h x y z) + +end General + +section CommRing + +variable {k : Type u} {B : Type v} [CommRing k] [CommRing B] [Algebra k B] + (C : ConicAlgebra k B) (μ : k) + +/-- **`GPR 18.14(a)`.** For `B` commutative, the double `Cay(B, μ)` is commutative exactly when +the conjugation of `B` is the identity — for every scalar `μ`. -/ +theorem mul_comm_cay_iff : (∀ x y : Cay C μ, x * y = y * x) ↔ ∀ u : B, C.conj u = u := + ⟨conj_eq_id_of_mul_comm_cay C μ, mul_comm_cay C μ⟩ + +/-- **`GPR 18.14(b)`.** For `B` commutative, the double `Cay(B, μ)` is associative exactly when +the conjugation of `B` is an involution — for every scalar `μ`. -/ +theorem mul_assoc_cay_iff : + (∀ x y z : Cay C μ, x * y * z = x * (y * z)) ↔ C.ConjIsInvolution := + ⟨conjIsInvolution_of_mul_assoc_cay C μ, mul_assoc_cay C μ⟩ + +end CommRing + +/-! ### `GPR 18.15`: discharging the hypothesis on the conjugation + +Over a finitely generated projective module the conjugation of an alternative conic algebra is +automatically an involution (`GPR 16.14(b)`, `ConicAlgebra.conjIsInvolution_of_projective`). Since +an associative `B` is alternative, that removes the conjugation hypothesis from both criteria and +leaves conditions on the multiplication of `B` alone. -/ + +section Projective + +variable {k : Type u} {B : Type v} [CommRing k] [NonAssocRing B] [Module k B] + [SMulCommClass k B B] [IsScalarTower k B B] [Module.Finite k B] [Module.Projective k B] + (C : ConicAlgebra k B) (μ : k) + +/-- **`GPR 18.15(b)`.** For `B` finitely generated projective, `Cay(B, μ)` is alternative exactly +when `B` is associative. -/ +theorem isAlternative_cay_iff_of_projective : + IsAlternative (Cay C μ) ↔ ∀ a b c : B, a * b * c = a * (b * c) := by + refine ⟨mul_assoc_of_isAlternative_cay C μ, fun hassoc ↦ ?_⟩ + have : IsAlternative B := ⟨fun a b ↦ (hassoc a a b).symm, fun a b ↦ hassoc b a a⟩ + exact isAlternative_cay_of_mul_assoc C μ hassoc C.conjIsInvolution_of_projective + +end Projective + +section ProjectiveCommRing + +variable {k : Type u} {B : Type v} [CommRing k] [CommRing B] [Algebra k B] + [Module.Finite k B] [Module.Projective k B] (C : ConicAlgebra k B) (μ : k) + +/-- **`GPR 18.15(a)`.** For `B` a finitely generated projective commutative algebra, `Cay(B, μ)` +is associative — unconditionally, the conjugation hypothesis of `GPR 18.14(b)` being automatic. -/ +theorem mul_assoc_cay_of_projective (x y z : Cay C μ) : x * y * z = x * (y * z) := + mul_assoc_cay C μ C.conjIsInvolution_of_projective x y z + +end ProjectiveCommRing + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean new file mode 100644 index 0000000000..ab3cf6c94d --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative + +/-! +# The double of an associative multiplicative conic algebra is multiplicative (`GPR Exc. 18.18`) + +`Cay(B, μ)` has a multiplicative norm **if and only if** `B` is associative with a multiplicative +norm (`GPR Exc. 18.18`). This file proves the direction that builds algebras: it is what carries +`n(xy) = n(x)n(y)` up the tower `k → k[√·] → ℍ → 𝕆`, and — since `𝕆` is *not* associative — it is +also where the tower stops, which is the content of the sedenion non-example (`GPR 19.23`, +Layer 8). + +## The computation + +Write `x = u₁ + v₁ j`, `y = u₂ + v₂ j`. Expanding + + `n(xy) = n_B(u₁u₂ + μ (conj v₂)v₁) - μ n_B(v₂u₁ + v₁(conj u₂))` + +with `n_B` multiplicative and `n_B(conj z) = n_B(z)` leaves exactly the terms of +`n(x)n(y) = (n_B(u₁) - μ n_B(v₁))(n_B(u₂) - μ n_B(v₂))`, plus + + `μ · [ n_B(u₁u₂, (conj v₂)v₁) - n_B(v₂u₁, v₁(conj u₂)) ]`. + +So everything reduces to the vanishing of that bracket, `polar_shuffle` below. That is where +associativity of `B` is spent, and it is spent exactly once: the two polar terms are moved onto a +common form by the two halves of norm-associativity +(`ConicAlgebra.IsMultiplicative.polar_mul_left` and `.polar_mul_right`), and what stands between +them is `v₂(u₁u₂) = (v₂u₁)u₂`. + +⚠ No hypothesis is needed on the conjugation of `B` — unlike `ConicAlgebra.isAlternative_cay`, +which needs it to be an involution. Only `conj (conj z) = z` is used, and that holds in every +conic algebra (`ConicAlgebra.conj_conj`). Nor is anything needed on `μ`, on `2`, or on the module +underlying `B`. + +## Main results + +* `ConicAlgebra.isMultiplicative_cay` : **`GPR Exc. 18.18`**, the direction `⇐`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.13, Exc. 18.18. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {B : Type v} [CommRing k] [Ring B] [Algebra k B] {C : ConicAlgebra k B} + +/-- The one place associativity of `B` enters `GPR Exc. 18.18`: for a multiplicative norm on an +associative `B`, + + `n(u₁u₂, (conj v₂)v₁) = n(v₂u₁, v₁(conj u₂))`. + +Both sides equal `n(v₁, (v₂u₁)u₂)`: the left by norm-associativity on the left +(`ConicAlgebra.IsMultiplicative.polar_mul_left`) followed by `v₂(u₁u₂) = (v₂u₁)u₂`, the right by +norm-associativity on the right (`ConicAlgebra.IsMultiplicative.polar_mul_right`). -/ +private theorem polar_shuffle (h : C.IsMultiplicative) (u₁ u₂ v₁ v₂ : B) : + QuadraticMap.polar C.norm (u₁ * u₂) (C.conj v₂ * v₁) + = QuadraticMap.polar C.norm (v₂ * u₁) (v₁ * C.conj u₂) := + calc QuadraticMap.polar C.norm (u₁ * u₂) (C.conj v₂ * v₁) + = QuadraticMap.polar C.norm (C.conj v₂ * v₁) (u₁ * u₂) := QuadraticMap.polar_comm .. + _ = QuadraticMap.polar C.norm v₁ (C.conj (C.conj v₂) * (u₁ * u₂)) := h.polar_mul_left .. + _ = QuadraticMap.polar C.norm v₁ (v₂ * u₁ * C.conj (C.conj u₂)) := by + rw [conj_conj, conj_conj, mul_assoc] + _ = QuadraticMap.polar C.norm (v₁ * C.conj u₂) (v₂ * u₁) := (h.polar_mul_right ..).symm + _ = QuadraticMap.polar C.norm (v₂ * u₁) (v₁ * C.conj u₂) := QuadraticMap.polar_comm .. + +/-- **`GPR Exc. 18.18`, `⇐`.** If `B` is associative and its norm is multiplicative, then the +norm of +`Cay(B, μ)` is multiplicative, for every scalar `μ`. + +This is the step that makes `ℍ` a composition algebra out of `ℂ`, and `𝕆` out of `ℍ`; it fails to +apply one rung further because `𝕆` is not associative, which is why the sedenions +`Cay(𝕆, μ)` are conic but not composition (`GPR 19.23`). -/ +theorem isMultiplicative_cay (C : ConicAlgebra k B) (μ : k) (h : C.IsMultiplicative) : + (C.cay μ).IsMultiplicative := by + intro x y + simp only [cay_norm_apply, Cay.fst_mul, Cay.snd_mul, C.norm_add, QuadraticMap.map_smul, + QuadraticMap.polar_smul_right, h.norm_mul, norm_conj, smul_eq_mul, + polar_shuffle h x.1 y.1 x.2 y.2] + ring + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Defs.lean new file mode 100644 index 0000000000..a77b1380b1 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Defs.lean @@ -0,0 +1,120 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.Basic + +/-! +# Conic algebras + +A **conic algebra** over a commutative ring `k` (`GPR 16.1`) is a unital, not necessarily +associative `k`-algebra `A` together with a quadratic form `n : A → k`, the *norm*, such that + +* `n 1 = 1`, and +* `x * x - n(1, x) • x + n x • 1 = 0` for every `x`, where `n(1, x) = polar n 1 x`. + +The second axiom says that every element satisfies a monic quadratic equation whose coefficients +are the trace and the norm; conic algebras are exactly the "algebras of degree two" in the older +literature. + +## Main definitions + +* `ConicAlgebra k A` : the conic structure on a unital non-associative `k`-algebra `A`. +* `ConicAlgebra.baseRing` : the conic structure on `k` itself, with norm `x ↦ x ^ 2`. + +The trace, the conjugation and their calculus live in `CompositionAlgebras/Conic/Basic.lean`. + +## Implementation notes + +**The norm is data, not a property.** Over a general commutative ring a unital algebra can carry +more than one conic norm, so `ConicAlgebra k A` is a *structure* whose first field is the norm — +not a `Prop`-valued mixin asserting that some norm exists. Consequently it is passed explicitly +(`C : ConicAlgebra k A`) rather than found by instance search, and every derived notion (trace, +conjugation) is a function of `C`. + +**No regularity, no projectivity, no `2 ∈ kˣ`.** The definition carries none of them, by design +(overview §2): the sedenions (`GPR 19.23`) must be conic without a non-singular norm, and the +characteristic-2 purely inseparable example (`GPR 19.4`) must be conic with an identically zero +polar form. Anything stronger belongs on theorems, not here. + +⚠ **Un-halved polar.** The degree-two identity uses `QuadraticMap.polar` — `n(x + y) - n x - n y` +— and never `QuadraticMap.associated`, which is half of it and requires `Invertible 2`. In +particular `n(1, 1) = 2`, not `1`. See overview §6(a). + +**Typeclass shape.** A unital non-associative `k`-algebra is spelled +`[NonAssocRing A] [Module k A] [SMulCommClass k A A] [IsScalarTower k A A]`, mathlib's idiom for a +bilinear multiplication (mathlib's `Algebra` class is only available for *associative* `A`, and +implies exactly these four for such `A`, so associative examples need no extra work). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.1. +-/ + +@[expose] public section + +universe u v + +variable (k : Type u) (A : Type v) [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] + +/-- A **conic algebra** over `k` (`GPR 16.1`): a unital, not necessarily associative `k`-algebra +`A` together with a quadratic norm `n` satisfying `n 1 = 1` and the degree-two identity + +`x * x - n(1, x) • x + n x • 1 = 0`. + +The norm is *data*: over a general commutative ring it need not be determined by the algebra +structure. -/ +structure ConicAlgebra where + /-- The norm of the conic algebra, `n_C` in `GPR 16.1`. It is data, not a property: a unital + algebra may admit several conic norms. -/ + norm : QuadraticForm k A + /-- The norm is normalized at the unit: `n 1 = 1`. -/ + norm_one : norm 1 = 1 + /-- The **degree-two identity** `x * x = n(1, x) • x - n x • 1`, i.e. + `x * x - n(1, x) • x + n x • 1 = 0`. The scalar `n(1, x)` is the *un-halved* polar form of `n` + at the unit, which `Conic/Basic.lean` names `ConicAlgebra.trace`. -/ + mul_self : ∀ x : A, x * x = QuadraticMap.polar norm 1 x • x - norm x • (1 : A) + +namespace ConicAlgebra + +variable {k A} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The degree-two identity in the shape it takes in `GPR 16.1`. -/ +theorem mul_self_sub_polar_smul_add_norm_smul_eq_zero (C : ConicAlgebra k A) (x : A) : + x * x - QuadraticMap.polar C.norm 1 x • x + C.norm x • (1 : A) = 0 := by + rw [C.mul_self]; abel + +variable (k) in +/-- The base ring `k` is a conic algebra over itself, with norm the squaring map. This is the +rank-one composition algebra; it is recorded here as the smallest sanity check on the axioms. -/ +def baseRing : ConicAlgebra k k where + norm := QuadraticMap.sq + norm_one := one_mul 1 + mul_self x := by + have : QuadraticMap.polar (QuadraticMap.sq (R := k)) 1 x = 2 * x := by + simp [QuadraticMap.polar, QuadraticMap.sq_apply]; ring + rw [this] + simp [QuadraticMap.sq_apply, smul_eq_mul] + ring + +@[simp] theorem baseRing_norm_apply (x : k) : (baseRing k).norm x = x * x := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **A conic algebra is determined by its norm.** The remaining two fields are propositions, so +two conic structures on the same algebra with the same norm are equal. + +⚠ This says nothing about *uniqueness* of the norm, which is false in general and holds for +finitely generated projective algebras only — see `ConicAlgebra.norm_eq_of_projective`. -/ +@[ext] theorem ext {C D : ConicAlgebra k A} (h : C.norm = D.norm) : C = D := by + rcases C with ⟨n, hn₁, hn₂⟩ + rcases D with ⟨m, hm₁, hm₂⟩ + simp only at h + subst h + rfl + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Division.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Division.lean new file mode 100644 index 0000000000..5a3dc3054c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Division.lean @@ -0,0 +1,188 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Division + +/-! +# Division conic algebras (`GPR 8.6`, `GPR 13.8`) + +A conic algebra can fall short of being a division algebra in the sense of `GPR 8.6` (`IsDivision`: +nonzero, with bijective left and right multiplications by nonzero elements) in two ways: its norm +may have a nonzero null vector, or — without alternativity — a two-sided inverse may fail to make +the multiplications bijective. This file compares the three conditions + +* `IsDivision A`, +* `C.HasTwoSidedInverses` (every nonzero element has a two-sided inverse), +* `C.norm.Anisotropic`, + +over a field. Without any hypothesis on the multiplication, division implies anisotropy, and +anisotropy implies two-sided inverses (`n(x)⁻¹ (conj x)`). For an **alternative** conic algebra all +three agree, once `A ≠ 0`: that is `GPR 13.8` for conic algebras. The real sedenions show that the +alternativity hypothesis cannot be dropped (`ConicAlgebra.not_isDivision_realSedenion`, +`GPR Exc. 19.29(e)`). + +The engine is the pair of identities `(conj x) (x y) = n(x) y = (y x) (conj x)`, which hold in every +alternative conic algebra: write `conj x = t(x)·1 - x` and apply the alternative laws and +`x² = t(x) x - n(x)·1`. So when `n(x)` is invertible, `n(x)⁻¹ (conj x)` inverts left and right +multiplication by `x`. + +## Main results + +* `ConicAlgebra.conj_mul_mul_of_isAlternative`, `ConicAlgebra.mul_mul_conj_of_isAlternative` : + `(conj x) (x y) = n(x) y` and `(y x) (conj x) = n(x) y` in an alternative conic algebra. +* `ConicAlgebra.anisotropic_of_isDivision` : a division conic algebra has anisotropic norm. +* `ConicAlgebra.hasTwoSidedInverses_of_anisotropic` : over a field, an anisotropic norm gives + two-sided inverses. No alternativity is needed. +* `ConicAlgebra.anisotropic_of_hasTwoSidedInverses` : for an alternative conic algebra, two-sided + inverses force the norm to be anisotropic. +* `ConicAlgebra.isDivision_of_anisotropic` : over a field, a nonzero alternative conic algebra with + anisotropic norm is a division algebra. +* `ConicAlgebra.isDivision_iff_hasTwoSidedInverses`, `ConicAlgebra.isDivision_iff_anisotropic` : + **`GPR 13.8`** for alternative conic algebras over a field. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6, 13.8, + Exc. 19.29. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +section CommRing + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + +omit [SMulCommClass k A A] in +/-- In an alternative conic algebra, `(conj x) (x y) = n(x) y`: expand `conj x = t(x)·1 - x`, use +the left alternative law `x (x y) = (x x) y`, and the degree-two identity `x x = t(x) x - n(x)·1`. +-/ +theorem conj_mul_mul_of_isAlternative [IsAlternative A] (x y : A) : + C.conj x * (x * y) = C.norm x • y := by + rw [C.conj_apply, sub_mul, smul_mul_assoc, one_mul, IsAlternative.mul_mul_self_left, + C.mul_self_eq, sub_mul, smul_mul_assoc, smul_mul_assoc, one_mul] + abel + +omit [IsScalarTower k A A] in +/-- In an alternative conic algebra, `(y x) (conj x) = n(x) y`, by the right alternative law. -/ +theorem mul_mul_conj_of_isAlternative [IsAlternative A] (x y : A) : + (y * x) * C.conj x = C.norm x • y := by + rw [C.conj_apply, mul_sub, mul_smul_comm, mul_one, IsAlternative.mul_self_mul_right, + C.mul_self_eq, mul_sub, mul_smul_comm, mul_smul_comm, mul_one] + abel + +omit [SMulCommClass k A A] in +/-- `x ((conj x) y) = n(x) y`: the identity `conj_mul_mul_of_isAlternative` for `conj x`. -/ +theorem mul_conj_mul_of_isAlternative [IsAlternative A] (x y : A) : + x * (C.conj x * y) = C.norm x • y := by + simpa only [C.conj_conj, C.norm_conj] using C.conj_mul_mul_of_isAlternative (C.conj x) y + +omit [IsScalarTower k A A] in +/-- `(y (conj x)) x = n(x) y`: the identity `mul_mul_conj_of_isAlternative` for `conj x`. -/ +theorem mul_conj_mul_conj_of_isAlternative [IsAlternative A] (x y : A) : + (y * C.conj x) * x = C.norm x • y := by + simpa only [C.conj_conj, C.norm_conj] using C.mul_mul_conj_of_isAlternative (C.conj x) y + +omit [IsScalarTower k A A] in +/-- **A division conic algebra has anisotropic norm.** If `n(x) = 0` then `x (conj x) = n(x)·1 = 0`, +and `conj x ≠ 0` when `x ≠ 0`, so `x` would be a zero divisor. No alternativity is needed. -/ +theorem anisotropic_of_isDivision (h : IsDivision A) : C.norm.Anisotropic := by + intro x hx + by_contra hx0 + have hc : C.conj x ≠ 0 := fun h0 ↦ hx0 <| by + simpa only [C.conj_conj, map_zero] using congrArg C.conj h0 + have hmul : x * C.conj x = 0 := by rw [C.mul_conj_self, hx, zero_smul] + exact (h.eq_zero_or_eq_zero_of_mul_eq_zero hmul).elim hx0 hc + +omit [SMulCommClass k A A] in +/-- **For an alternative conic algebra, two-sided inverses force an anisotropic norm.** If `x y = 1` +and `n(x) = 0`, then `conj x = (conj x) (x y) = n(x) y = 0`, so `x = 0`. Only the one-sided inverse +`x y = 1` is used. -/ +theorem anisotropic_of_hasTwoSidedInverses [IsAlternative A] (h : C.HasTwoSidedInverses) : + C.norm.Anisotropic := by + intro x hx + by_contra hx0 + obtain ⟨y, hxy, -⟩ := h hx0 + have hc : C.conj x = 0 := by + have := C.conj_mul_mul_of_isAlternative x y + rwa [hxy, mul_one, hx, zero_smul] at this + exact hx0 (by simpa only [C.conj_conj, map_zero] using congrArg C.conj hc) + +end CommRing + +section Field + +variable {K : Type u} {A : Type v} [Field K] [NonAssocRing A] [Module K A] + [SMulCommClass K A A] [IsScalarTower K A A] (C : ConicAlgebra K A) + +/-- **Over a field, an anisotropic norm gives two-sided inverses**: `n(x)⁻¹ (conj x)` inverts any +nonzero `x`. Only `x (conj x) = (conj x) x = n(x)·1` is used, so neither alternativity nor +associativity is needed — and the result is correspondingly weak: see +`ConicAlgebra.HasTwoSidedInverses`. -/ +theorem hasTwoSidedInverses_of_anisotropic (h : C.norm.Anisotropic) : C.HasTwoSidedInverses := by + intro x hx + have hn : C.norm x ≠ 0 := fun h0 ↦ hx (h x h0) + refine ⟨(C.norm x)⁻¹ • C.conj x, ?_, ?_⟩ + · rw [mul_smul_comm, C.mul_conj_self, smul_smul, inv_mul_cancel₀ hn, one_smul] + · rw [smul_mul_assoc, C.conj_mul_self, smul_smul, inv_mul_cancel₀ hn, one_smul] + +/-- Over a field, a division conic algebra has two-sided inverses. -/ +theorem hasTwoSidedInverses_of_isDivision (h : IsDivision A) : C.HasTwoSidedInverses := + C.hasTwoSidedInverses_of_anisotropic (C.anisotropic_of_isDivision h) + +/-- **Over a field, a nonzero alternative conic algebra with anisotropic norm is a division +algebra** in the sense of `GPR 8.6`. For `u ≠ 0` the scalar `n(u)` is invertible, and +`v ↦ n(u)⁻¹ ((conj u) v)` and `v ↦ n(u)⁻¹ (v (conj u))` invert left and right multiplication by `u`, +by the identities `(conj x) (x y) = n(x) y = x ((conj x) y)` and +`(y x) (conj x) = n(x) y = (y (conj x)) x`. -/ +theorem isDivision_of_anisotropic [IsAlternative A] [Nontrivial A] (h : C.norm.Anisotropic) : + IsDivision A where + nontrivial := inferInstance + bijective_mul_left u hu := by + have hn : C.norm u ≠ 0 := fun h0 ↦ hu (h u h0) + refine Function.bijective_iff_has_inverse.mpr + ⟨fun v ↦ (C.norm u)⁻¹ • (C.conj u * v), fun v ↦ ?_, fun v ↦ ?_⟩ + · change (C.norm u)⁻¹ • (C.conj u * (u * v)) = v + rw [C.conj_mul_mul_of_isAlternative, smul_smul, inv_mul_cancel₀ hn, one_smul] + · change u * ((C.norm u)⁻¹ • (C.conj u * v)) = v + rw [mul_smul_comm, C.mul_conj_mul_of_isAlternative, smul_smul, inv_mul_cancel₀ hn, + one_smul] + bijective_mul_right u hu := by + have hn : C.norm u ≠ 0 := fun h0 ↦ hu (h u h0) + refine Function.bijective_iff_has_inverse.mpr + ⟨fun v ↦ (C.norm u)⁻¹ • (v * C.conj u), fun v ↦ ?_, fun v ↦ ?_⟩ + · change (C.norm u)⁻¹ • ((v * u) * C.conj u) = v + rw [C.mul_mul_conj_of_isAlternative, smul_smul, inv_mul_cancel₀ hn, one_smul] + · change ((C.norm u)⁻¹ • (v * C.conj u)) * u = v + rw [smul_mul_assoc, C.mul_conj_mul_conj_of_isAlternative, smul_smul, inv_mul_cancel₀ hn, + one_smul] + +/-- **`GPR 13.8`, for conic algebras over a field.** An alternative conic algebra is a division +algebra in the sense of `GPR 8.6` exactly when it is nonzero and every nonzero element has a +two-sided inverse. Without alternativity only `→` holds: the real sedenions have two-sided inverses +but are not a division algebra (`ConicAlgebra.not_isDivision_realSedenion`). -/ +theorem isDivision_iff_hasTwoSidedInverses [IsAlternative A] : + IsDivision A ↔ Nontrivial A ∧ C.HasTwoSidedInverses := + ⟨fun h ↦ ⟨h.nontrivial, C.hasTwoSidedInverses_of_isDivision h⟩, fun ⟨_, h⟩ ↦ + C.isDivision_of_anisotropic (C.anisotropic_of_hasTwoSidedInverses h)⟩ + +/-- An alternative conic algebra over a field is a division algebra exactly when it is nonzero and +its norm is anisotropic. -/ +theorem isDivision_iff_anisotropic [IsAlternative A] : + IsDivision A ↔ Nontrivial A ∧ C.norm.Anisotropic := + ⟨fun h ↦ ⟨h.nontrivial, C.anisotropic_of_isDivision h⟩, fun ⟨_, h⟩ ↦ + C.isDivision_of_anisotropic h⟩ + +end Field + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Doubling.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Doubling.lean new file mode 100644 index 0000000000..888110958d --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Doubling.lean @@ -0,0 +1,359 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Moufang +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity + +/-! +# Doubling inside an ambient conic algebra (`GPR 18.1`) + +Let `A` be a conic **alternative** algebra, `B ⊆ A` a unital subalgebra, and `v ∈ A` an element +**orthogonal to `B`** — `n(b, v) = 0` for every `b ∈ B` — whose norm is a unit. Then the three +identities + + `x(yv) = (yx)v`, `(xv)y = (x (conj y))v`, `(xv)(yv) = -n(v) ((conj y) x)` (`x, y ∈ B`) + +hold. They are exactly the three clauses of the Cayley–Dickson multiplication +`(u₁ + v₁j)(u₂ + v₂j) = (u₁u₂ + μ (conj v₂)v₁) + (v₂u₁ + v₁(conj u₂)) j` with `μ = -n(v)`, so +`B + Bv` is a copy of `Cay(B, μ)` sitting inside `A`. `Conic/CayleyDickson.lean` builds `Cay(B, μ)` +externally; this file is the internal counterpart, and the comparison between the two is +`ConicAlgebra.cayToAlgebra`. + +## The mechanism + +Everything rests on one unconditional observation. The linearized degree-two identity +`xy + yx = t(x)y + t(y)x - n(x,y)·1` (`ConicAlgebra.mul_add_mul`, valid in *every* conic algebra) +collapses, for `x ∈ B` and `v ⊥ B`, to + + `xv = v (conj x)`, `vx = (conj x) v` + +(`ConicAlgebra.mul_eq_mul_conj`, `ConicAlgebra.mul_eq_conj_mul`): orthogonality to `B` turns +multiplication by `v` into a twisted commutation rule. Note `1 ∈ B`, so `t(v) = n(1, v) = 0` and +hence `conj v = -v` and `v² = -n(v)·1`. + +Given that rule, the three identities follow from the alternative laws alone — the alternating +property of the associator, the middle Moufang identity `(ab)(ca) = a(bc)a`, and flexibility — +together with `n(v)` being a unit, which lets right multiplication by `v` be cancelled: +`(zv)v = -n(v)z`. + +## Why no regularity hypothesis + +`GPR 19.3` produces alternativity of a composition algebra from the vanishing of the *radical* of +its norm, which over a general commutative ring is not implied by non-singularity (see +`Composition/Basic.lean`). Alternativity is therefore assumed here rather than derived, as an honest +hypothesis on a conic algebra. For a composition algebra it is automatic over every commutative ring +(`ConicAlgebra.IsComposition.isAlternative_general`, `Composition/Alternative.lean`, which this +layer may not import). + +What is *not* assumed is any regularity of the norm — not on `A`, not on `B`. The three identities +below are cancellation statements proved by multiplying by `v` and using `n(v) ∈ kˣ`, so no +non-degeneracy of the ambient norm is used anywhere. Nor is `B` assumed associative, nor +multiplicativity of the norm; those enter only when the norm of the doubled algebra is computed. + +## Main definitions + +* `ConicAlgebra.cayToAlgebra` : the map `Cay(B, -n(v)) → A`, `u + wj ↦ u + wv`. + +## Main results + +* `ConicAlgebra.mul_eq_mul_conj`, `ConicAlgebra.mul_eq_conj_mul` : the commutation rule + `xv = v (conj x)`, `vx = (conj x) v` for `x ∈ B`, in any conic algebra whatsoever. +* `ConicAlgebra.mul_mul_orthogonal` : `x(yv) = (yx)v`, `GPR 18.1(1)`. +* `ConicAlgebra.mul_orthogonal_mul` : `(xv)y = (x (conj y))v`, `GPR 18.1(2)`. +* `ConicAlgebra.mul_orthogonal_mul_mul_orthogonal` : `(xv)(yv) = -n(v)((conj y)x)`, `GPR 18.1(3)`. +* `ConicAlgebra.cayToAlgebra_mul` : **`GPR 18.1`** — the doubling map is multiplicative, so + `B + Bv` is a copy of `Cay(B, -n(v))` inside `A`. +* `ConicAlgebra.norm_cayToAlgebra` : it is an isometry for the Cayley–Dickson norm. This is where + multiplicativity of `n` is used, through `B ⊥ Bv`. +* `ConicAlgebra.cayToAlgebra_injective` : it is injective when `n|_B` is regular. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 18.1, 18.3. +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] {C : ConicAlgebra k A} {v : A} + +/-! ### An element of trace zero -/ + +section TraceZero + +variable (htv : C.trace v = 0) +include htv + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- An element of trace zero is the negative of its conjugate. -/ +theorem conj_eq_neg_of_trace_eq_zero : C.conj v = -v := by + rw [conj_apply, htv, zero_smul, zero_sub] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The degree-two identity for an element of trace zero: `v² = -n(v)·1`. -/ +theorem mul_self_of_trace_eq_zero : v * v = -(C.norm v • (1 : A)) := by + rw [C.mul_self_eq, htv, zero_smul, zero_sub] + +variable [IsAlternative A] + +omit [IsScalarTower k A A] in +/-- **Right multiplication by `v` squares to `-n(v)`**: `(zv)v = -n(v)·z`, for `v` of trace zero +and *any* `z`. This is the cancellation device of the whole file; it consumes right alternativity +and nothing else. -/ +theorem mul_mul_self_of_trace_eq_zero (z : A) : z * v * v = -(C.norm v • z) := by + rw [IsAlternative.mul_self_mul_right, mul_self_of_trace_eq_zero htv, mul_neg, mul_smul_comm, + mul_one] + +omit [IsScalarTower k A A] in +/-- **Cancelling `v`.** If `n(v)` is a unit then right multiplication by `v` is injective, so an +element killed by `v` is zero. -/ +theorem eq_zero_of_mul_eq_zero (hu : IsUnit (C.norm v)) {d : A} (hd : d * v = 0) : d = 0 := by + have h := mul_mul_self_of_trace_eq_zero htv d + rw [hd, zero_mul, eq_comm, neg_eq_zero] at h + obtain ⟨w, hw⟩ := hu + calc d = ((w⁻¹ : kˣ) : k) • ((w : k) • d) := by rw [smul_smul, Units.inv_mul, one_smul] + _ = 0 := by rw [hw, h, smul_zero] + +end TraceZero + +/-! ### An element orthogonal to a subalgebra -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- A unital subalgebra is closed under conjugation, since `conj b = t(b)·1 - b`. -/ +theorem conj_mem {B : NonAssocSubalgebra k A} {b : A} (hb : b ∈ B) : C.conj b ∈ B := by + rw [conj_apply] + exact sub_mem (SMulMemClass.smul_mem _ (show (1 : A) ∈ B from B.one_mem)) hb + +section Orthogonal + +variable {B : NonAssocSubalgebra k A} (hBv : ∀ b ∈ B, polar C.norm b v = 0) +include hBv + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- An element orthogonal to a unital subalgebra has trace zero: the unit lies in the +subalgebra, and `t(v) = n(1, v)`. -/ +theorem trace_eq_zero_of_orthogonal : C.trace v = 0 := + (C.trace_apply v).trans (hBv 1 B.one_mem) + +omit [IsScalarTower k A A] in +/-- **The commutation rule**, first form: `xv = v (conj x)` for `x ∈ B` and `v ⊥ B`. + +This holds in every conic algebra — no alternativity, no regularity, no hypothesis on `2`. It is +the linearized degree-two identity `xy + yx = t(x)y + t(y)x - n(x,y)·1` with `y = v`, where both +`t(v)` and `n(x, v)` vanish. -/ +theorem mul_eq_mul_conj {x : A} (hx : x ∈ B) : x * v = v * C.conj x := by + have hlin := C.mul_add_mul x v + rw [trace_eq_zero_of_orthogonal hBv, hBv x hx, zero_smul, zero_smul, sub_zero, add_zero] at hlin + rw [conj_apply, mul_sub, mul_smul_comm, mul_one] + linear_combination (norm := module) hlin + +omit [SMulCommClass k A A] in +/-- **The commutation rule**, second form: `vx = (conj x) v` for `x ∈ B` and `v ⊥ B`. -/ +theorem mul_eq_conj_mul {x : A} (hx : x ∈ B) : v * x = C.conj x * v := by + have hlin := C.mul_add_mul x v + rw [trace_eq_zero_of_orthogonal hBv, hBv x hx, zero_smul, zero_smul, sub_zero, add_zero] at hlin + rw [conj_apply, sub_mul, smul_mul_assoc, one_mul] + linear_combination (norm := module) hlin + +variable [IsAlternative A] + +/-- Conjugating by `v`: `(vc)v = -n(v) (conj c)` for `c ∈ B`. -/ +theorem mul_mul_eq_neg_smul_conj {c : A} (hc : c ∈ B) : + v * c * v = -(C.norm v • C.conj c) := by + rw [mul_eq_conj_mul hBv hc, + mul_mul_self_of_trace_eq_zero (trace_eq_zero_of_orthogonal hBv) (C.conj c)] + +variable (hconj : C.ConjIsInvolution) +include hconj + +omit [IsScalarTower k A A] [IsAlternative A] in +/-- `xv` has trace zero for `x ∈ B`: conjugation negates it. -/ +theorem conj_mul_orthogonal {x : A} (hx : x ∈ B) : C.conj (x * v) = -(x * v) := by + rw [hconj, conj_eq_neg_of_trace_eq_zero (trace_eq_zero_of_orthogonal hBv), neg_mul, + ← mul_eq_mul_conj hBv hx] + +/-- `(xv)(vy) = -n(v)(yx)` for `x, y ∈ B`. + +The two commutation rules put the product in the shape `(vb)(cv)` of the middle Moufang identity +`(ab)(ca) = a(bc)a`, and flexibility then turns `v(bc)v` into a single conjugation by `v`. -/ +theorem mul_orthogonal_mul_orthogonal_mul {x y : A} (hx : x ∈ B) (hy : y ∈ B) : + x * v * (v * y) = -(C.norm v • (y * x)) := by + rw [mul_eq_mul_conj hBv hx, mul_eq_conj_mul hBv hy, IsAlternative.middle_moufang, + ← IsAlternative.flexible, + mul_mul_eq_neg_smul_conj hBv (mul_mem (conj_mem hx) (conj_mem hy)), hconj, conj_conj, + conj_conj] + +/-- **`GPR 18.1(3)`**: `(xv)(yv) = -n(v)((conj y)x)` for `x, y ∈ B`. + +This is the first component of the Cayley–Dickson product `(0 + v₁j)(0 + v₂j) = μ (conj v₂)v₁`, with +`μ = -n(v)`. -/ +theorem mul_orthogonal_mul_mul_orthogonal {x y : A} (hx : x ∈ B) (hy : y ∈ B) : + x * v * (y * v) = -(C.norm v • (C.conj y * x)) := by + rw [mul_eq_mul_conj hBv hy, mul_orthogonal_mul_orthogonal_mul hBv hconj hx (conj_mem hy)] + +variable (hu : IsUnit (C.norm v)) +include hu + +/-- **`GPR 18.1(1)`**: `x(yv) = (yx)v` for `x, y ∈ B`. + +Both sides are cancelled against `v` on the right: `((yx)v)v = -n(v)(yx)` at once, while +`(x(yv))v` is unwound by moving the associator `⁅x, yv, v⁆` around its cyclic orbit to +`⁅yv, v, x⁆`, whose two terms are `-n(v)(yx)` and `-n(v)(xy)`. The `xy` terms cancel. -/ +theorem mul_mul_orthogonal {x y : A} (hx : x ∈ B) (hy : y ∈ B) : + x * (y * v) = y * x * v := by + have htv := trace_eq_zero_of_orthogonal hBv + refine sub_eq_zero.mp (eq_zero_of_mul_eq_zero htv hu ?_) + have hcyc : associator x (y * v) v = associator (y * v) v x := by + rw [IsAlternative.associator_swap_left, IsAlternative.associator_swap_right, neg_neg] + simp only [associator] at hcyc + rw [mul_mul_self_of_trace_eq_zero htv y, + mul_orthogonal_mul_orthogonal_mul hBv hconj hy hx] at hcyc + simp only [mul_neg, neg_mul, mul_smul_comm, smul_mul_assoc] at hcyc + have key : x * (y * v) * v = -(C.norm v • (y * x)) := by + linear_combination (norm := module) hcyc + rw [sub_mul, key, mul_mul_self_of_trace_eq_zero htv (y * x), sub_self] + +/-- **`GPR 18.1(2)`**: `(xv)y = (x (conj y))v` for `x, y ∈ B`. + +Conjugating `GPR 18.1(1)` at the pair `(conj y, x)` turns it into this, because conjugation is an +anti-homomorphism and negates every element of `Bv`. -/ +theorem mul_orthogonal_mul {x y : A} (hx : x ∈ B) (hy : y ∈ B) : + x * v * y = x * C.conj y * v := by + have h := congrArg C.conj (mul_mul_orthogonal hBv hconj hu (conj_mem (C := C) hy) hx) + have hl : C.conj (C.conj y * (x * v)) = -(x * v * y) := by + rw [hconj, conj_mul_orthogonal hBv hconj hx, conj_conj, neg_mul] + have hr : C.conj (x * C.conj y * v) = -(x * C.conj y * v) := + conj_mul_orthogonal hBv hconj (mul_mem hx (conj_mem (C := C) hy)) + rw [hl, hr] at h + exact neg_inj.mp h + +end Orthogonal + +/-! ### The comparison with the external double -/ + +section Cay + +/-- **The internal doubling map** `Cay(B, -n(v)) → A`, `u + wj ↦ u + wv` (`GPR 18.1`). + +It is defined for every `v`, with no orthogonality or invertibility hypothesis; those are what make +it multiplicative (`ConicAlgebra.cayToAlgebra_mul`) and injective +(`ConicAlgebra.cayToAlgebra_injective`). The Cayley–Dickson scalar is forced to be `-n(v)`, which +is `GPR 18.1`'s `μ`. -/ +def cayToAlgebra (C : ConicAlgebra k A) (B : NonAssocSubalgebra k A) (v : A) : + Cay (C.restrict B) (-C.norm v) →ₗ[k] A where + toFun p := (p.1 : A) + (p.2 : A) * v + map_add' p q := by + simp only [Cay.fst_add, Cay.snd_add, AddMemClass.coe_add, add_mul] + abel + map_smul' c p := by + simp only [Cay.fst_smul, Cay.snd_smul, SetLike.val_smul, smul_add, smul_mul_assoc, + RingHom.id_apply] + +variable {B : NonAssocSubalgebra k A} + +omit [SMulCommClass k A A] in +@[simp] theorem cayToAlgebra_apply (p : Cay (C.restrict B) (-C.norm v)) : + cayToAlgebra C B v p = (p.1 : A) + (p.2 : A) * v := rfl + +omit [SMulCommClass k A A] in +/-- The internal doubling map is unital. -/ +theorem cayToAlgebra_one : cayToAlgebra C B v 1 = 1 := by + rw [cayToAlgebra_apply] + change ((1 : B) : A) + ((0 : B) : A) * v = 1 + rw [OneMemClass.coe_one, ZeroMemClass.coe_zero, zero_mul, add_zero] + +variable (hBv : ∀ b ∈ B, polar C.norm b v = 0) +include hBv + +omit [SMulCommClass k A A] in +/-- **`B ⊥ Bv`.** Norm-associativity moves the `v` across the polar form, where orthogonality to `B` +kills it: `n(b, wv) = n((conj w)b, v) = 0`. This is what makes the internal doubling map an isometry +onto its image, and needs the norm to be multiplicative. -/ +theorem polar_mul_orthogonal (hmul : C.IsMultiplicative) {b w : A} (hb : b ∈ B) (hw : w ∈ B) : + polar C.norm b (w * v) = 0 := by + rw [QuadraticMap.polar_comm, hmul.polar_mul_left, QuadraticMap.polar_comm] + exact hBv _ (mul_mem (conj_mem hw) hb) + +/-- **The internal doubling map is an isometry**: it carries the Cayley–Dickson norm +`n_B ⊥ ⟨n(v)⟩ n_B` to the ambient norm. This is `GPR 18.1`'s norm formula, and it uses +multiplicativity (for `n(wv) = n(w)n(v)`) and `B ⊥ Bv`. -/ +theorem norm_cayToAlgebra (hmul : C.IsMultiplicative) (p : Cay (C.restrict B) (-C.norm v)) : + C.norm (cayToAlgebra C B v p) = ((C.restrict B).cay (-C.norm v)).norm p := by + rw [cayToAlgebra_apply, C.norm_add, hmul.norm_mul, + polar_mul_orthogonal hBv hmul (SetLike.coe_mem p.1) (SetLike.coe_mem p.2), cay_norm_apply, + restrict_norm_apply, restrict_norm_apply] + ring + +/-- The polar form of the Cayley–Dickson norm is the ambient polar form, pulled back. -/ +theorem polar_cayToAlgebra (hmul : C.IsMultiplicative) + (p q : Cay (C.restrict B) (-C.norm v)) : + polar C.norm (cayToAlgebra C B v p) (cayToAlgebra C B v q) = + polar ((C.restrict B).cay (-C.norm v)).norm p q := by + rw [QuadraticMap.polar, QuadraticMap.polar, ← map_add, + norm_cayToAlgebra hBv hmul, norm_cayToAlgebra hBv hmul, norm_cayToAlgebra hBv hmul] + +variable [IsAlternative A] (hconj : C.ConjIsInvolution) (hu : IsUnit (C.norm v)) +include hconj hu + +/-- **`GPR 18.1`.** The internal doubling map is multiplicative: `B + Bv` really is a copy of +`Cay(B, -n(v))` inside `A`. + +The three components of the Cayley–Dickson product are the three identities of this file, and +`μ = -n(v)` is forced by the last of them. -/ +theorem cayToAlgebra_mul (p q : Cay (C.restrict B) (-C.norm v)) : + cayToAlgebra C B v (p * q) = cayToAlgebra C B v p * cayToAlgebra C B v q := by + have hi := mul_mul_orthogonal hBv hconj hu (SetLike.coe_mem p.1) (SetLike.coe_mem q.2) + have hii := mul_orthogonal_mul hBv hconj hu (SetLike.coe_mem p.2) (SetLike.coe_mem q.1) + have hiii := mul_orthogonal_mul_mul_orthogonal hBv hconj (SetLike.coe_mem p.2) + (SetLike.coe_mem q.2) + simp only [cayToAlgebra_apply, Cay.fst_mul, Cay.snd_mul, AddMemClass.coe_add, + MulMemClass.coe_mul, SetLike.val_smul, coe_restrict_conj, add_mul, mul_add] + rw [hi, hii, hiii] + module + +omit [IsAlternative A] hconj in +/-- **The internal doubling map is injective**, as soon as the radical of the restricted norm +vanishes and `n(v)` is a unit. + +The map is an isometry, so its kernel lands in the radical of the Cayley–Dickson norm +`n_B ⊥ ⟨n(v)⟩ n_B`, which vanishes by `GN (C.8.3)`: the first summand has injective polar form and +rescaling by a unit does not change a radical. + +⚠ Regularity of `n|_B` — not merely a vanishing radical — is what `GN (C.8.3)` consumes, and the +asymmetry is real: in characteristic 2 the non-singular form `⟨1⟩` doubles to `⟨1⟩ ⊥ ⟨1⟩`, whose +radical is nonzero. This is the same hypothesis `ConicAlgebra.IsComposition.cay` carries on the +constructive side. -/ +theorem cayToAlgebra_injective (hmul : C.IsMultiplicative) + (hreg : (C.restrict B).norm.IsGPRRegular) : + Function.Injective (cayToAlgebra C B v) := by + have hnd : (C.restrict B).norm.IsGPRNondegenerate := + Submodule.eq_bot_iff _ |>.mpr fun _ hx ↦ + (injective_iff_map_eq_zero _).mp hreg.1 _ hx.2 + have hrad : QuadraticMap.radical ((C.restrict B).cay (-C.norm v)).norm = ⊥ := by + refine QuadraticMap.radical_prod_eq_bot hreg.1 ?_ + rw [neg_neg] + exact (QuadraticMap.radical_smul hu _).trans hnd + refine (injective_iff_map_eq_zero _).mpr fun p hp ↦ ?_ + have hmem : p ∈ QuadraticMap.radical ((C.restrict B).cay (-C.norm v)).norm := by + refine ⟨?_, LinearMap.ext fun q ↦ ?_⟩ + · rw [← norm_cayToAlgebra hBv hmul, hp, map_zero] + · rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, + ← polar_cayToAlgebra hBv hmul, hp, QuadraticMap.polar_zero_left] + rw [hrad, Submodule.mem_bot] at hmem + exact hmem + +end Cay + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean new file mode 100644 index 0000000000..421a41f561 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity + +/-! +# Kirmse's identities, and alternativity of a multiplicative conic algebra + +**Kirmse's identities** for a multiplicative conic algebra are + + `(conj x)(xy) = n(x) y`, `(yx)(conj x) = n(x) y`. + +They are the mechanism behind `GPR 19.3`: substituting `conj x = t(x)·1 - x` and using the +degree-two identity `x² = t(x)·x - n(x)·1` turns them into precisely the two alternative laws, so a +multiplicative conic algebra satisfying them is alternative. + +## The Kirmse element lies in the radical + +Write `w = (conj x)(xy) - n(x)·y` for the defect of the first identity. **In every multiplicative +conic algebra, with no hypothesis whatsoever, `w` lies in the radical of the norm** — that is, both + + `n(w, z) = 0` for every `z` and `n(w) = 0`. + +The first is two applications of norm-associativity (`Conic/Multiplicative.lean`); the second is +the computation + + `n(w) = n(x)²n(y) + n(x)²n(y) - n(x)² · n(y, y) = 2n(x)²n(y) - 2n(x)²n(y) = 0`, + +using `n(y, y) = 2n(y)`. Both are `ConicAlgebra.IsMultiplicative.mem_radical_conj_mul_mul` below, +and similarly for the second identity. + +Consequently the hypothesis that lets `w` be cancelled is exactly **`GPR`'s non-degeneracy**, +`QuadraticForm.IsGPRNondegenerate` — the vanishing of `QuadraticMap.radical` — which is the +hypothesis `GPR 19.3` puts on the norm. `GPR 19.3` itself starts from a unital algebra with such a +form and *derives* the conic structure, and also shows that the polar radical is a central ideal +annihilated by `2` and by every `n(x, y)`; those parts are `Conic/Recognition.lean` +(`ConicAlgebra.ofMultiplicative` and the results after it). Here the conic structure is the input. +Nothing here needs the polar form to be injective, so nothing here is +troubled by characteristic 2, where the polar form of a non-singular form of odd rank has a kernel. + +⚠ **Non-degeneracy is not implied by non-singularity over a ring**, so this is not yet `GPR 19.3` +for composition algebras over an arbitrary base: `QuadraticForm.rankOne 1` over `𝔽₂[t]/(t²)` is +non-singular (`QuadraticForm.isGPRNonsingular_rankOne`) but has `t` in its radical. Over a *field* +non-singularity does imply a vanishing radical +(`QuadraticForm.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot`), which is what +`Composition/Basic.lean` uses. Over a ring, alternativity of composition algebras is proved by a +different route in `Composition/Alternative.lean` +(`ConicAlgebra.IsComposition.isAlternative_general`: regularity, the rank-one case, and the rank +decomposition); see below for why residue-field descent is not that route. + +## Main results + +* `ConicAlgebra.IsMultiplicative.mem_radical_conj_mul_mul`, + `.mem_radical_mul_mul_conj` : the Kirmse defects lie in the radical of the norm, + unconditionally. +* `ConicAlgebra.IsMultiplicative.conj_mul_mul`, `.mul_mul_conj` : **Kirmse's identities**, for a + norm with vanishing radical. +* `ConicAlgebra.IsMultiplicative.isAlternative` : such an algebra is alternative. This is + `GPR 19.3`'s alternativity statement, with `GPR`'s own hypothesis and no assumption on `2`, on + the rank, or on the module. + +## Why not residue-field descent + +Alternativity of a composition algebra over an arbitrary commutative ring, whose norm is only +*non-singular*, is proved in `Composition/Alternative.lean`. A route once recorded here does not +work, and is written out so that it is not attempted again. + +That route was: the alternative laws are multilinear, and a map of finitely generated modules +vanishes as soon as it vanishes after base change to every residue field; over each residue field +the base-changed algebra is again a multiplicative conic algebra with vanishing radical +(`ConicAlgebra.IsComposition.baseChangeOfProjective`, `Composition/BaseChange.lean`), so the theorem +below applies there. + +⚠ The second ingredient — residue-field detection — is **false**. Over `R = 𝔽₂[t]/(t²)`, the map +`R → R`, `x ↦ t x`, is nonzero, yet `R` has the single maximal ideal `(t)` and the map vanishes +after base change to `R ⧸ (t) = 𝔽₂`. Base changing to every *field* over `R`, rather than every +residue field, does not help: `t` is nilpotent, so it dies in every field over `R`. Nothing about +finite generation or projectivity repairs this — residue fields simply cannot see a nilpotent, and +this is the same phenomenon as the ⚠ above, where `t` sits in the radical of a non-singular form +over exactly that ring. The proof in `Composition/Alternative.lean` therefore works over the base: +regularity where the rank exceeds one, and commutativity and associativity outright in rank one. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.3 (composition + algebras are alternative), 16.5 (norm-associativity). +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +namespace IsMultiplicative + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] {C : ConicAlgebra k A} + +omit [SMulCommClass k A A] in +/-- **Kirmse's left identity, in polar form**: `n((conj x)(xy), z) = n(x) n(y, z)`, in every +multiplicative conic algebra and with no regularity hypothesis. + +Norm-associativity moves `conj x` across the polar form as `x` (`conj (conj x) = x`), turning the +left side into `n(xy, xz)`, which is the linearization of multiplicativity in the right variable. -/ +theorem polar_conj_mul_mul (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm (C.conj x * (x * y)) z + = C.norm x * QuadraticMap.polar C.norm y z := by + rw [h.polar_mul_left, conj_conj, h.polar_mul_mul_left] + +omit [IsScalarTower k A A] in +/-- **Kirmse's right identity, in polar form**: `n((yx)(conj x), z) = n(x) n(y, z)`, in every +multiplicative conic algebra and with no regularity hypothesis. -/ +theorem polar_mul_mul_conj (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm ((y * x) * C.conj x) z + = C.norm x * QuadraticMap.polar C.norm y z := by + rw [h.polar_mul_right, conj_conj, h.polar_mul_mul_right, mul_comm] + +omit [SMulCommClass k A A] in +/-- The norm of the left Kirmse defect vanishes: `n((conj x)(xy) - n(x)·y) = 0`. + +Multiplicativity evaluates the two square terms as `n(x)²n(y)` each, and the polar term as +`n(x)² · n(y, y) = 2n(x)²n(y)` by `ConicAlgebra.IsMultiplicative.polar_conj_mul_mul` at `z = y`. +They cancel. No regularity, and nothing on `2`: the `2` here comes from `n(y, y) = 2n(y)` and is +cancelled against itself, never divided by. -/ +theorem norm_conj_mul_mul_sub (h : C.IsMultiplicative) (x y : A) : + C.norm (C.conj x * (x * y) - C.norm x • y) = 0 := by + simp only [C.norm_sub, h.norm_mul, norm_conj, QuadraticMap.map_smul, + QuadraticMap.polar_smul_right, h.polar_conj_mul_mul, QuadraticMap.polar_self, smul_eq_mul, + nsmul_eq_mul] + push_cast + ring + +omit [IsScalarTower k A A] in +/-- The norm of the right Kirmse defect vanishes: `n((yx)(conj x) - n(x)·y) = 0`. -/ +theorem norm_mul_mul_conj_sub (h : C.IsMultiplicative) (x y : A) : + C.norm ((y * x) * C.conj x - C.norm x • y) = 0 := by + simp only [C.norm_sub, h.norm_mul, norm_conj, QuadraticMap.map_smul, + QuadraticMap.polar_smul_right, h.polar_mul_mul_conj, QuadraticMap.polar_self, smul_eq_mul, + nsmul_eq_mul] + push_cast + ring + +omit [SMulCommClass k A A] in +/-- **The left Kirmse defect lies in the radical of the norm**, in every multiplicative conic +algebra and with no hypothesis at all. This is the sharp unconditional statement behind +`GPR 19.3`; the identity `(conj x)(xy) = n(x)·y` is exactly its image under `radical = ⊥`. -/ +theorem mem_radical_conj_mul_mul (h : C.IsMultiplicative) (x y : A) : + C.conj x * (x * y) - C.norm x • y ∈ QuadraticMap.radical C.norm := + ⟨h.norm_conj_mul_mul_sub x y, LinearMap.ext fun z ↦ by + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, QuadraticMap.polar_sub_left, + h.polar_conj_mul_mul, QuadraticMap.polar_smul_left, smul_eq_mul, sub_self]⟩ + +omit [IsScalarTower k A A] in +/-- **The right Kirmse defect lies in the radical of the norm**, unconditionally. -/ +theorem mem_radical_mul_mul_conj (h : C.IsMultiplicative) (x y : A) : + (y * x) * C.conj x - C.norm x • y ∈ QuadraticMap.radical C.norm := + ⟨h.norm_mul_mul_conj_sub x y, LinearMap.ext fun z ↦ by + rw [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply, QuadraticMap.polar_sub_left, + h.polar_mul_mul_conj, QuadraticMap.polar_smul_left, smul_eq_mul, sub_self]⟩ + +variable (hrad : C.norm.IsGPRNondegenerate) +include hrad + +omit [SMulCommClass k A A] in +/-- **Kirmse's left identity**: `(conj x)(xy) = n(x) y`. + +The hypothesis is `GPR`'s non-degeneracy, `QuadraticMap.radical C.norm = ⊥` — exactly what +`GPR 19.3` assumes, and exactly what is needed to cancel the radical element of +`ConicAlgebra.IsMultiplicative.mem_radical_conj_mul_mul`. -/ +theorem conj_mul_mul (h : C.IsMultiplicative) (x y : A) : + C.conj x * (x * y) = C.norm x • y := by + have hmem := h.mem_radical_conj_mul_mul x y + rw [show C.norm.radical = ⊥ from hrad, Submodule.mem_bot, sub_eq_zero] at hmem + exact hmem + +omit [IsScalarTower k A A] in +/-- **Kirmse's right identity**: `(yx)(conj x) = n(x) y`. -/ +theorem mul_mul_conj (h : C.IsMultiplicative) (x y : A) : + (y * x) * C.conj x = C.norm x • y := by + have hmem := h.mem_radical_mul_mul_conj x y + rw [show C.norm.radical = ⊥ from hrad, Submodule.mem_bot, sub_eq_zero] at hmem + exact hmem + +/-- **`GPR 19.3`, the alternativity statement: a multiplicative conic algebra with non-degenerate +norm is alternative.** + +Each alternative law is one of Kirmse's identities rewritten with `conj x = t(x)·1 - x` and the +degree-two identity `x² = t(x)·x - n(x)·1`. + +The hypotheses on the norm are `GPR`'s: multiplicative, with zero radical. Nothing is assumed +about `2`, about the rank, or about the module — in particular no projectivity, which `GPR 19.3` +carries for its other conclusions. The conic structure (the degree-two identity) is an input +here; `GPR 19.3` derives it from the form, which is `ConicAlgebra.ofMultiplicative` in +`Conic/Recognition.lean`. -/ +theorem isAlternative (h : C.IsMultiplicative) : IsAlternative A where + left_alt x y := by + have hk := h.conj_mul_mul hrad x y + rw [conj_apply, sub_mul, smul_mul_assoc, one_mul] at hk + simp only [C.mul_self_eq x, sub_mul, smul_mul_assoc, one_mul] + linear_combination (norm := module) -hk + right_alt x y := by + have hk := h.mul_mul_conj hrad x y + rw [conj_apply, mul_sub, mul_smul_comm, mul_one] at hk + simp only [C.mul_self_eq x, mul_sub, mul_smul_comm, mul_one] + linear_combination (norm := module) -hk + +end IsMultiplicative + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean new file mode 100644 index 0000000000..c334059d21 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean @@ -0,0 +1,291 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic + +/-! +# Multiplicative conic algebras and norm-associativity + +A conic algebra is **multiplicative** (`GPR 19.1`; the older literature says its norm *permits +composition*) if `n(xy) = n(x) n(y)` for all `x, y`. This is the second half of the definition of a +composition algebra (`GPR 19.5`, Layer 7), the first half being a regularity condition on the norm. + +The point of this file is that multiplicativity is much stronger than it looks: linearizing it +twice turns the *quadratic* statement `n(xy) = n(x)n(y)` into a *bilinear* one, and that bilinear +identity is exactly `GPR`'s **norm-associativity** + + `n(xy, z) = n(y, (conj x)z)`, `n(xy, z) = n(x, z(conj y))`, + +which is the workhorse of the whole composition-algebra theory. Everything here holds in an +arbitrary conic algebra over an arbitrary commutative ring: no alternativity, no regularity, no +projectivity, and nothing on `2`. Only additivity of the norm's polar form is used. + +## Main definitions + +* `ConicAlgebra.IsMultiplicative` : `n(xy) = n(x) n(y)`. +* `ConicAlgebra.HasTwoSidedInverses` : every nonzero element has a two-sided multiplicative + inverse. ⚠ This is **weaker** than being a division algebra in the sense of `GPR 8.6`; see its + docstring. + +## Main results + +* `QuadraticForm.polar_mul_mul_right_of_map_mul`, `QuadraticForm.polar_mul_mul_left_of_map_mul`, + `QuadraticForm.polar_mul_add_polar_mul_of_map_mul` : the linearizations `GPR (19.1.3)`–`(19.1.5)` + for any quadratic form permitting composition on a non-associative ring, with no conic structure. +* `ConicAlgebra.IsMultiplicative.polar_mul_mul_right`, + `ConicAlgebra.IsMultiplicative.polar_mul_mul_left` : the first linearization, in either variable, + `n(xz, yz) = n(x, y) n(z)` and `n(xy, xz) = n(x) n(y, z)`. +* `ConicAlgebra.IsMultiplicative.polar_mul_add_polar_mul` : the second linearization, + `n(xz, yw) + n(xw, yz) = n(x, y) n(z, w)`. +* `ConicAlgebra.IsMultiplicative.polar_mul_left` : **norm-associativity**, + `n(xy, z) = n(y, (conj x)z)`. +* `ConicAlgebra.IsMultiplicative.polar_mul_right` : norm-associativity on the other side, + `n(xy, z) = n(x, z(conj y))`. +* `ConicAlgebra.IsMultiplicative.trace_mul` : `t(xy) = t(x)t(y) - n(x, y)`. +* `ConicAlgebra.IsMultiplicative.anisotropic_iff_noZeroDivisors_of_isDomain` : over a domain, + the norm is anisotropic exactly when the algebra has no zero divisors. +* `ConicAlgebra.isMultiplicative_baseRing` : the base ring, with norm the squaring map, is + multiplicative. + +## Implementation notes + +`n(x, y)` above is `QuadraticMap.polar C.norm x y`, the **un-halved** polar form +(overview §6(a)); the two linearizations below are obtained by additivity alone, so every +statement here is valid in characteristic 2. + +The two norm-associativity identities are genuinely two statements, not one applied to the +opposite algebra: `A` is not assumed associative, commutative or alternative, so there is no +symmetry to exploit. They are proved the same way, by specializing the second linearization at +`y = 1` and at `w = 1` respectively. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.5, + 16.12--16.13, 19.1, 22.18. +-/ + +@[expose] public section + +universe u v + +/-! ### Quadratic forms permitting composition -/ + +open QuadraticMap + +namespace QuadraticForm + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + {Q : QuadraticForm k A} + +/-- **`GPR (19.1.4)`**: a quadratic form permitting composition satisfies +`n(xz, yz) = n(x, y) n(z)`. Only right distributivity is used; compare +`ConicAlgebra.IsMultiplicative.polar_mul_mul_right`, the same identity for a conic norm. -/ +theorem polar_mul_mul_right_of_map_mul (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) (x y z : A) : + polar Q (x * z) (y * z) = polar Q x y * Q z := by + have hadd : x * z + y * z = (x + y) * z := (add_mul x y z).symm + simp only [QuadraticMap.polar, hadd, hmul] + ring + +/-- **`GPR (19.1.3)`**: a quadratic form permitting composition satisfies +`n(xy, xz) = n(x) n(y, z)`. Only left distributivity is used; compare +`ConicAlgebra.IsMultiplicative.polar_mul_mul_left`. -/ +theorem polar_mul_mul_left_of_map_mul (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) (x y z : A) : + polar Q (x * y) (x * z) = Q x * polar Q y z := by + have hadd : x * y + x * z = x * (y + z) := (mul_add x y z).symm + simp only [QuadraticMap.polar, hadd, hmul] + ring + +/-- **`GPR (19.1.5)`**: a quadratic form permitting composition satisfies +`n(xz, yw) + n(xw, yz) = n(x, y) n(z, w)`. This is `GPR`'s +`n(xy, wz) + n(wy, xz) = n(x, w) n(y, z)` with the variables renamed, in the shape of +`ConicAlgebra.IsMultiplicative.polar_mul_add_polar_mul`; it is `(19.1.4)` linearized in `z`. -/ +theorem polar_mul_add_polar_mul_of_map_mul (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) + (x y z w : A) : + polar Q (x * z) (y * w) + polar Q (x * w) (y * z) = polar Q x y * polar Q z w := by + have key := polar_mul_mul_right_of_map_mul hmul x y (z + w) + simp only [mul_add, polar_add_left, polar_add_right, QuadraticMap.map_add Q z w] at key + linear_combination key - polar_mul_mul_right_of_map_mul hmul x y z - + polar_mul_mul_right_of_map_mul hmul x y w + +end QuadraticForm + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + +/-- A conic algebra is **multiplicative** (`GPR 19.1`) if its norm permits composition: +`n(xy) = n(x) n(y)`. + +This is a property of the pair `(A, n)`, not of `A` alone — the norm is data — so it is a +predicate on `C : ConicAlgebra k A` rather than a typeclass on `A`. It carries no regularity and +no projectivity: those are separate axes (overview §2), and a composition algebra +(`GPR 19.5`) is a conic algebra having all three. -/ +def IsMultiplicative : Prop := ∀ x y : A, C.norm (x * y) = C.norm x * C.norm y + +/-- **Every nonzero element has a two-sided inverse**: for each `x ≠ 0` there is `y` with +`x * y = 1` and `y * x = 1`. + +⚠ **This property is weaker than being a division algebra as defined in `GPR 8.6`, and is +deliberately not called `IsDivision`.** `GPR 8.6` calls `A` a division algebra when `A ≠ 0` and, for +every `u ≠ 0`, the left and right multiplications `L_u` and `R_u` are bijective. Without +associativity a two-sided inverse does not give that: the real sedenions have an anisotropic norm, +so every nonzero `x` has the two-sided inverse `n(x)⁻¹ (conj x)`, yet they are not a division +algebra (`GPR Exc. 19.29(e)`). For a unital *alternative* algebra the two notions agree, given +`1 ≠ 0` (`GPR 13.8`); in particular they agree for composition algebras, which are alternative. Both +facts are formalized in `Conic/Division.lean` and `Composition/Sedenion.lean`: +`ConicAlgebra.isDivision_iff_hasTwoSidedInverses` is `GPR 13.8` for alternative conic algebras over +a field, and `ConicAlgebra.hasTwoSidedInverses_realSedenion` with +`ConicAlgebra.not_isDivision_realSedenion` is the sedenion example. Theorems stated with +`HasTwoSidedInverses` are about this weaker property; the classification theorems over a field are +also stated with `IsDivision`. + +The property depends only on the multiplication, but is placed in the conic-algebra namespace +because it is used here in the classification of composition algebras. It does not assert +associativity. -/ +def HasTwoSidedInverses (_C : ConicAlgebra k A) : Prop := + ∀ {x : A}, x ≠ 0 → ∃ y : A, x * y = 1 ∧ y * x = 1 + +namespace IsMultiplicative + +variable {C} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Multiplicativity of the norm, as a rewrite rule. `ConicAlgebra.IsMultiplicative` is a `def`, +so it has to be unfolded before `rw`/`simp` can use it. -/ +theorem norm_mul (h : C.IsMultiplicative) (x y : A) : + C.norm (x * y) = C.norm x * C.norm y := h x y + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **First linearization of multiplicativity**, in the left variable: `n(xz, yz) = n(x, y) n(z)`. + +Obtained from `n((x + y)z) = n(x + y) n(z)` by subtracting `n(xz) = n(x)n(z)` and +`n(yz) = n(y)n(z)`; only right distributivity and additivity are used. -/ +theorem polar_mul_mul_right (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm (x * z) (y * z) = QuadraticMap.polar C.norm x y * C.norm z := + QuadraticForm.polar_mul_mul_right_of_map_mul h x y z + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **First linearization of multiplicativity**, in the right variable: `n(xy, xz) = n(x) n(y, z)`. + +Not a consequence of `ConicAlgebra.IsMultiplicative.polar_mul_mul_right` — `A` is not assumed +commutative — but proved the same way, from `n(x(y + z)) = n(x) n(y + z)`. -/ +theorem polar_mul_mul_left (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm (x * y) (x * z) = C.norm x * QuadraticMap.polar C.norm y z := + QuadraticForm.polar_mul_mul_left_of_map_mul h x y z + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **Second linearization of multiplicativity**: `n(xz, yw) + n(xw, yz) = n(x, y) n(z, w)`. + +This is the bilinear shadow of `n(xy) = n(x)n(y)`, and the identity from which both halves of +norm-associativity below are read off. It is +`ConicAlgebra.IsMultiplicative.polar_mul_mul_right` linearized in its second variable. -/ +theorem polar_mul_add_polar_mul (h : C.IsMultiplicative) (x y z w : A) : + QuadraticMap.polar C.norm (x * z) (y * w) + QuadraticMap.polar C.norm (x * w) (y * z) + = QuadraticMap.polar C.norm x y * QuadraticMap.polar C.norm z w := + QuadraticForm.polar_mul_add_polar_mul_of_map_mul h x y z w + +omit [SMulCommClass k A A] in +/-- **Norm-associativity** (`GPR 16.5`, and the reason multiplicativity is so rigid): +`n(xy, z) = n(y, (conj x)z)`. + +The left factor may be moved across the polar form at the cost of conjugating it. Specialize the +second linearization at `y = 1`, where `n(x, 1) = t(x)`, and use `conj x = t(x)·1 - x`. -/ +theorem polar_mul_left (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm y (C.conj x * z) := by + have key := h.polar_mul_add_polar_mul x 1 y z + rw [one_mul, one_mul, QuadraticMap.polar_comm C.norm x 1, ← trace_apply] at key + rw [conj_apply, sub_mul, smul_mul_assoc, one_mul, QuadraticMap.polar_sub_right, + QuadraticMap.polar_smul_right, smul_eq_mul, QuadraticMap.polar_comm C.norm y (x * z)] + linear_combination key + +omit [IsScalarTower k A A] in +/-- **Norm-associativity**, the other side (`GPR 16.5`): `n(xy, z) = n(x, z(conj y))`. + +Not a consequence of `ConicAlgebra.IsMultiplicative.polar_mul_left` — `A` is not assumed +associative or commutative — but proved the same way, specializing the second linearization at +`w = 1`. -/ +theorem polar_mul_right (h : C.IsMultiplicative) (x y z : A) : + QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm x (z * C.conj y) := by + have key := h.polar_mul_add_polar_mul x z y 1 + rw [mul_one, mul_one, QuadraticMap.polar_comm C.norm y 1, ← trace_apply] at key + rw [conj_apply, mul_sub, mul_smul_comm, mul_one, QuadraticMap.polar_sub_right, + QuadraticMap.polar_smul_right, smul_eq_mul] + linear_combination key + +omit [IsScalarTower k A A] in +/-- In a multiplicative conic algebra, the trace of a product is +`t(xy) = t(x)t(y) - n(x, y)` [GPR, 16.12(5), 16.13]. -/ +theorem trace_mul (h : C.IsMultiplicative) (x y : A) : + C.trace (x * y) = C.trace x * C.trace y - QuadraticMap.polar C.norm x y := by + rw [trace_apply, QuadraticMap.polar_comm, h.polar_mul_right x y 1, one_mul, conj_apply, + QuadraticMap.polar_sub_right, QuadraticMap.polar_smul_right, + QuadraticMap.polar_comm C.norm x 1, ← trace_apply, smul_eq_mul] + ring + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- The norm of a product of conjugates: `n((conj x)(conj y)) = n(x) n(y)`. -/ +theorem norm_conj_mul_conj (h : C.IsMultiplicative) (x y : A) : + C.norm (C.conj x * C.conj y) = C.norm x * C.norm y := by + rw [h.norm_mul, norm_conj, norm_conj] + +omit [IsScalarTower k A A] in +/-- Over a domain, a multiplicative conic algebra has anisotropic norm if and only if it has no +zero divisors. Indeed, multiplicativity sends a zero product to a zero product of norms; in the +other direction, a null vector annihilates its conjugate, which is zero only when the original +vector is zero. This is the zero-divisor step used in `GPR 22.19`. -/ +theorem anisotropic_iff_noZeroDivisors_of_isDomain [IsDomain k] + (h : C.IsMultiplicative) : C.norm.Anisotropic ↔ NoZeroDivisors A := by + constructor + · intro hani + refine ⟨fun {x y} hxy ↦ ?_⟩ + have hnorm : C.norm x * C.norm y = 0 := by + rw [← h.norm_mul, hxy, map_zero] + rcases mul_eq_zero.mp hnorm with hx | hy + · exact Or.inl (hani x hx) + · exact Or.inr (hani y hy) + · intro hzero x hx + have hmul : x * C.conj x = 0 := by + rw [C.mul_conj_self, hx, zero_smul] + rcases hzero.eq_zero_or_eq_zero_of_mul_eq_zero hmul with hx | hx + · exact hx + · have := congrArg C.conj hx + simpa only [C.conj_conj, map_zero] using this + +omit [IsScalarTower k A A] in +/-- Over a field, every nonzero element of a multiplicative conic algebra has a two-sided inverse +if and only if its norm is anisotropic. Forwards, a null nonzero element cannot have an inverse +because norms multiply. Backwards, `n(x)⁻¹ (conj x)` is a two-sided inverse. This is the step of +`GPR 22.18` that `GPR` phrases with division algebras; `HasTwoSidedInverses` is weaker than that +notion in general, and agrees with it for composition algebras +(`ConicAlgebra.IsComposition.isDivision_iff_hasTwoSidedInverses`). -/ +theorem hasTwoSidedInverses_iff_anisotropic {K : Type*} [Field K] {B : Type*} [NonAssocRing B] + [Module K B] [SMulCommClass K B B] [IsScalarTower K B B] {D : ConicAlgebra K B} + (h : D.IsMultiplicative) : D.HasTwoSidedInverses ↔ D.norm.Anisotropic := by + constructor + · intro hdiv x hx + by_contra hx0 + obtain ⟨y, hxy, -⟩ := hdiv hx0 + have hnorm := congrArg D.norm hxy + rw [h.norm_mul, hx, zero_mul, D.norm_one] at hnorm + exact zero_ne_one hnorm + · intro hani x hx + have hn : D.norm x ≠ 0 := fun hnx ↦ hx (hani x hnx) + refine ⟨(D.norm x)⁻¹ • D.conj x, ?_, ?_⟩ + · rw [mul_smul_comm, D.mul_conj_self, smul_smul, inv_mul_cancel₀ hn, one_smul] + · rw [smul_mul_assoc, D.conj_mul_self, smul_smul, inv_mul_cancel₀ hn, one_smul] + +end IsMultiplicative + +variable (k) in +/-- The base ring is a multiplicative conic algebra: `(xy)² = x² y²`. Together with +`QuadraticForm.isGPRNonsingular_rankOne` this makes `k` the rank-one composition algebra. -/ +theorem isMultiplicative_baseRing : (baseRing k).IsMultiplicative := fun x y ↦ by + simp only [baseRing_norm_apply] + ring + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Projective.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Projective.lean new file mode 100644 index 0000000000..af803c97e7 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Projective.lean @@ -0,0 +1,242 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import LeanPool.CompositionAlgebrasOverRings.Module.SelfAnnihilating +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective + +/-! +# Projective conic algebras: the trace defect vanishes (`GPR 16.7`, `GPR 16.14(b)`) + +For an alternative conic algebra whose underlying module is finitely generated projective, the +conjugation **is** an algebra anti-homomorphism. `Conic/Basic.lean` proves this over a field, and +`Conic/TraceDefectCounterexample.lean` shows it is false over an arbitrary base; projectivity is +exactly what separates the two. + +## The argument + +`ConicAlgebra.traceDefect_smul_eq_smul_one` (alternativity) gives, for every `x`, + + `d(x, y) • x = μ(x, y) • 1`, where `d` is the trace defect. + +Two facts turn this into `d = 0`. + +* **`1` is unimodular** (`GPR 16.7`, via `GPR 11.15`). Over a projective module a quadratic form + is `b(x, x)` for some bilinear `b` (`QuadraticMap.bilinRepr`), and then `λ := b(1, ·)` has + `λ 1 = n 1 = 1`. Applying `λ` to the displayed identity evaluates `μ(x, y) = d(x, y) λ(x)`, so + + `d(x, y) • (x - λ(x) • 1) = 0`. + + In other words `d(·, y)` **annihilates its own argument** on `N := ker λ`. +* **A self-annihilating functional on a finitely generated projective module vanishes** + (`LinearMap.eq_zero_of_smul_self_eq_zero`, `Module/SelfAnnihilating.lean`). `N` is a direct + summand of `A`, hence finitely generated projective, so `d(·, y)` vanishes on `N`; and `A` is + `k · 1 + N` with `d(1, y) = 0`, so `d` vanishes identically. + +This is `GPR 16.14(b)` — flexibility plus projectivity gives norm-associativity — specialized to +what the conjugation needs. Only flexibility is used, which alternativity supplies. + +## Main results + +* `ConicAlgebra.isUnimodular_one` : **`GPR 16.7`**. +* `ConicAlgebra.norm_eq_of_projective` : uniqueness of a conic norm on a finite projective + algebra, **`GPR 16.16`**. +* `ConicAlgebra.traceDefect_eq_zero_of_projective` : **`GPR 16.14(b)`** for the trace defect. +* `ConicAlgebra.conj_mul_of_projective` : conjugation is an anti-homomorphism. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.15, 16.7, + 16.14(b), 16.16, 17.6. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + +/-! ### The trace defect as a linear form -/ + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +theorem traceDefect_add_left (x x' y : A) : + C.traceDefect (x + x') y = C.traceDefect x y + C.traceDefect x' y := by + simp only [traceDefect, map_add, QuadraticMap.polar_add_left, add_mul] + ring + +variable (y : A) in +omit [SMulCommClass k A A] in +/-- The trace defect as a linear form in its first argument. -/ +def traceDefectLeft : A →ₗ[k] k where + toFun x := C.traceDefect x y + map_add' x x' := C.traceDefect_add_left x x' y + map_smul' c x := by simpa using C.traceDefect_smul_left c x y + +omit [SMulCommClass k A A] in +@[simp] theorem traceDefectLeft_apply (x y : A) : C.traceDefectLeft y x = C.traceDefect x y := rfl + +/-! ### `GPR 16.7`: the unit is unimodular -/ + +section Projective + +variable [Module.Finite k A] [Module.Projective k A] + +/-- The linear form `b(1, ·)` for a bilinear form `b` representing the norm. It sends `1` to `1` +(`ConicAlgebra.unitForm_one`), which is what makes the unit unimodular. -/ +noncomputable def unitForm : A →ₗ[k] k := QuadraticMap.bilinRepr C.norm 1 + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem unitForm_one : C.unitForm (1 : A) = 1 := by + rw [unitForm, QuadraticMap.bilinRepr_apply_self, C.norm_one] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +include C in +/-- **`GPR 16.7`.** In a conic algebra that is finitely generated projective as a module, the unit +is unimodular. This is `GPR 11.15` for the pointed quadratic module `(A, n, 1)`: over a projective +module the norm is `b(x, x)` for a bilinear `b`, and `b(1, ·)` sends `1` to `n 1 = 1`. -/ +theorem isUnimodular_one : Module.IsUnimodular k (1 : A) := + Module.isUnimodular_of_apply_eq_one (f := C.unitForm) C.unitForm_one + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- **Uniqueness of the conic norm on a finitely generated projective algebra** (`GPR 16.16`). + +Multiplicativity and non-degeneracy are not needed: projectivity makes `1` unimodular, which is +the exact module-theoretic input consumed by the proof. -/ +theorem norm_eq_of_projective (C D : ConicAlgebra k A) : C.norm = D.norm := by + let d : A →ₗ[k] k := C.trace - D.trace + have hd (x : A) : d x • x = (C.norm x - D.norm x) • (1 : A) := by + change (C.trace x - D.trace x) • x = _ + have hC : C.trace x • x = x * x + C.norm x • (1 : A) := by + calc + _ = (C.trace x • x - C.norm x • (1 : A)) + C.norm x • 1 := by module + _ = _ := by rw [← C.mul_self_eq] + have hD : D.trace x • x = x * x + D.norm x • (1 : A) := by + calc + _ = (D.trace x • x - D.norm x • (1 : A)) + D.norm x • 1 := by module + _ = _ := by rw [← D.mul_self_eq] + rw [sub_smul, hC, hD] + module + have hdnorm (x : A) : C.norm x - D.norm x = d x * C.unitForm x := by + have h := congrArg C.unitForm (hd x) + simp only [map_smul, C.unitForm_one, smul_eq_mul, mul_one] at h + exact h.symm + set N : Submodule k A := LinearMap.ker C.unitForm with hN + set p : A →ₗ[k] N := LinearMap.codRestrict N + (LinearMap.id - LinearMap.toSpanSingleton k A 1 ∘ₗ C.unitForm) (fun z ↦ by + simp [hN, LinearMap.mem_ker, LinearMap.toSpanSingleton_apply]) with hp + have hpi : p ∘ₗ N.subtype = LinearMap.id := by + refine LinearMap.ext fun z ↦ Subtype.ext ?_ + have hz : C.unitForm (z : A) = 0 := z.2 + simp [hp, hz, LinearMap.toSpanSingleton_apply] + have : Module.Finite k N := + Module.Finite.of_surjective p fun z ↦ ⟨(z : A), DFunLike.congr_fun hpi z⟩ + have : Module.Projective k N := Module.Projective.of_split N.subtype p hpi + have hdN : d.comp N.subtype = 0 := by + refine LinearMap.eq_zero_of_smul_self_eq_zero _ fun z ↦ ?_ + refine Subtype.ext ?_ + have hz : C.unitForm (z : A) = 0 := z.2 + have h := hd (z : A) + rw [hdnorm, hz, mul_zero, zero_smul] at h + simpa using h + have hd1 : d (1 : A) = 0 := by + simp [d, ConicAlgebra.trace_one] + have hd0 : d = 0 := by + ext x + have hx : x - C.unitForm x • (1 : A) ∈ N := by + simp [hN, LinearMap.mem_ker, C.unitForm_one] + have hker := DFunLike.congr_fun hdN ⟨x - C.unitForm x • (1 : A), hx⟩ + have hsplit : x = (x - C.unitForm x • (1 : A)) + C.unitForm x • (1 : A) := by + module + rw [hsplit, map_add, map_smul, hd1, smul_eq_mul, mul_zero, add_zero] + simpa using hker + ext x + have h := hd x + rw [DFunLike.congr_fun hd0 x] at h + change (0 : k) • x = _ at h + rw [zero_smul] at h + have hform := congrArg C.unitForm h + have : C.norm x - D.norm x = 0 := by simpa [C.unitForm_one] using hform.symm + exact sub_eq_zero.mp this + +/-! ### `GPR 16.14(b)`: the trace defect vanishes -/ + +variable [IsAlternative A] + +/-- The trace defect annihilates the "traceless part" `x - λ(x) • 1` of its own argument. + +Applying `λ = ConicAlgebra.unitForm` to `d(x, y) • x = μ(x, y) • 1` +(`ConicAlgebra.traceDefect_smul_eq_smul_one`) computes the right-hand scalar as +`μ(x, y) = d(x, y) λ(x)`, and the identity becomes this. -/ +theorem traceDefect_smul_sub_smul_one (x y : A) : + C.traceDefect x y • (x - C.unitForm x • (1 : A)) = 0 := by + have hid := C.traceDefect_smul_eq_smul_one x y + have hμ := congrArg C.unitForm hid + rw [map_smul, map_smul, C.unitForm_one, smul_eq_mul, smul_eq_mul, mul_one] at hμ + rw [smul_sub, hid, ← hμ, smul_smul, sub_self] + +/-- **`GPR 16.14(b)`, for the trace defect.** In an alternative conic algebra whose module is +finitely generated projective, the trace defect vanishes: `t(xy) = t(x)t(y) - n(x, y)`. + +⚠ Projectivity is essential — see `Conic/TraceDefectCounterexample.lean` for an associative +conic algebra over `ℤ/4`, on a non-projective module, whose trace defect is `2`. -/ +theorem traceDefect_eq_zero_of_projective (x y : A) : C.traceDefect x y = 0 := by + -- the kernel of `λ`, a direct summand of `A` and so finitely generated projective + set N : Submodule k A := LinearMap.ker C.unitForm with hN + set p : A →ₗ[k] N := LinearMap.codRestrict N (LinearMap.id - (LinearMap.toSpanSingleton k A 1) + ∘ₗ C.unitForm) (fun z ↦ by + simp [hN, LinearMap.mem_ker, LinearMap.toSpanSingleton_apply]) with hp + have hpi : p ∘ₗ N.subtype = LinearMap.id := by + refine LinearMap.ext fun z ↦ Subtype.ext ?_ + have hz : C.unitForm (z : A) = 0 := z.2 + simp [hp, hz, LinearMap.toSpanSingleton_apply] + have : Module.Finite k N := + Module.Finite.of_surjective p fun z ↦ ⟨(z : A), DFunLike.congr_fun hpi z⟩ + have : Module.Projective k N := Module.Projective.of_split N.subtype p hpi + -- the trace defect restricted to `N` annihilates its own argument + have hzero : (C.traceDefectLeft y).comp N.subtype = 0 := by + refine LinearMap.eq_zero_of_smul_self_eq_zero _ fun z ↦ ?_ + refine Subtype.ext ?_ + have hz : C.unitForm (z : A) = 0 := z.2 + have := C.traceDefect_smul_sub_smul_one (z : A) y + rw [hz, zero_smul, sub_zero] at this + simpa using this + -- and `A = k · 1 + N` + have hsplit : x - C.unitForm x • (1 : A) ∈ N := by + simp [hN, LinearMap.mem_ker, C.unitForm_one] + have hx : C.traceDefect (x - C.unitForm x • (1 : A)) y = 0 := by + have h := congrArg (fun f ↦ f ⟨x - C.unitForm x • (1 : A), hsplit⟩) hzero + simpa using h + have hsum : C.traceDefect x y = C.traceDefect (x - C.unitForm x • (1 : A)) y + + C.traceDefect (C.unitForm x • (1 : A)) y := by + rw [← C.traceDefect_add_left] + congr 1 + abel + rw [hsum, hx, C.traceDefect_smul_left, C.traceDefect_one_left, mul_zero, add_zero] + +/-- The trace is "multiplicative up to the norm": `t(xy) = t(x)t(y) - n(x, y)`. -/ +theorem trace_mul_of_projective (x y : A) : + C.trace (x * y) = C.trace x * C.trace y - QuadraticMap.polar C.norm x y := by + have h := C.traceDefect_eq_zero_of_projective x y + rw [traceDefect] at h + linear_combination -h + +/-- **Conjugation is an algebra anti-homomorphism** for an alternative conic algebra that is +finitely generated projective as a module (`GPR 16.14(b)`, `GPR 17.6`). -/ +theorem conj_mul_of_projective (x y : A) : C.conj (x * y) = C.conj y * C.conj x := + C.conj_mul_of_traceDefect_eq_zero (C.traceDefect_eq_zero_of_projective x y) + +/-- The conjugation of an alternative conic algebra on a finitely generated projective module is +an involution (`GPR 16.14(b)`). -/ +theorem conjIsInvolution_of_projective : C.ConjIsInvolution := C.conj_mul_of_projective + +end Projective + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/QuadraticAlgebra.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/QuadraticAlgebra.lean new file mode 100644 index 0000000000..fb9f7c6b20 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/QuadraticAlgebra.lean @@ -0,0 +1,198 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.Module.Invertible +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import Mathlib.LinearAlgebra.Dual.Lemmas +public import Mathlib.RingTheory.Finiteness.Cardinality +public import Mathlib.RingTheory.Finiteness.Nakayama +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +public import Mathlib.RingTheory.Support + +/-! +# Quadratic algebras are conic (`GPR 16.4`) + +`GPR 16.4` calls a `k`-algebra **quadratic** if it is unital and projective of rank `2` as a +`k`-module, and shows that a quadratic algebra is conic. This file proves that, for a unital +algebra that is finitely generated projective of constant rank `2` over an arbitrary commutative +ring, with no hypothesis on `2`. + +## The construction + +`GPR` deduces conicness from the Cayley–Hamilton theorem, with norm `det(Lₓ)`; that needs a +determinant for projective modules. The argument here is global instead. + +* **`1` is unimodular** (`ConicAlgebra.isUnimodular_one_of_rankAtStalk_ne_zero`, as in `GPR 16.4`). + Otherwise every functional sends `1` into some maximal ideal `𝔪`, so `1 ∈ 𝔪 R`, hence `R = 𝔪 R`, + and Nakayama makes `R` vanish at `𝔪` — but its rank there is `2`. +* So `R = k·1 ⊕ L` with `L` projective of rank one (`LinearMap.equivProdKerOfApplyEqOne`). For + `a, b ∈ L` write `a b = ν(a, b)·1 + μ(a, b)` with `μ(a, b) ∈ L`. +* On a module of rank one every endomorphism is a scalar: with a finite dual basis `(fⱼ, lⱼ)` of + `L`, put `α(a) = Σⱼ fⱼ(μ(a, lⱼ))`. The rank-one identity `φ(x) y = φ(y) x` + (`Module.IsLocallyFreeRankOne.isRankOnePairing`) gives `μ(a, a) = α(a) a`. +* Then `n(λ·1 + a) = λ² + λ α(a) - ν(a, a)` is a quadratic form with `n(1) = 1`, its trace is + `t(λ·1 + a) = 2λ + α(a)`, and `x² = t(x) x - n(x)·1`. + +By `ConicAlgebra.norm_eq_of_projective` (`GPR 16.16`) the conic norm is then unique, so the +choice made here is immaterial. + +## Main results + +* `ConicAlgebra.isUnimodular_one_of_rankAtStalk_ne_zero` : `1` is unimodular in a unital finitely + generated projective algebra whose rank vanishes nowhere. +* `ConicAlgebra.nonempty_of_rankAtStalk_eq_two` : **`GPR 16.4`**, a quadratic algebra carries a + conic structure. +* `ConicAlgebra.ofRankTwo` : a chosen conic structure on a quadratic algebra; by `GPR 16.16` it is + the only one. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.17, 16.4, 16.16. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {R : Type v} [CommRing k] [NonAssocRing R] [Module k R] + [SMulCommClass k R R] [IsScalarTower k R R] [Module.Finite k R] [Module.Projective k R] + +omit [IsScalarTower k R R] in +/-- **`1` is unimodular** in a unital finitely generated projective algebra whose rank vanishes at +no prime (`GPR 16.4`, via `GPR 9.17`). If no functional takes `1` to a unit, the values at `1` +lie in a maximal ideal `𝔪`; the dual basis then puts `1`, and hence every `x = x · 1`, in `𝔪 R`, +and Nakayama kills `R` at `𝔪`. -/ +theorem isUnimodular_one_of_rankAtStalk_ne_zero + (hR : ∀ p : PrimeSpectrum k, Module.rankAtStalk (R := k) R p ≠ 0) : + Module.IsUnimodular k (1 : R) := by + let I : Ideal k := LinearMap.range (Module.Dual.eval k R 1) + by_contra hne + have hI : I ≠ ⊤ := fun h ↦ hne <| by + obtain ⟨φ, hφ⟩ : (1 : k) ∈ I := h ▸ Submodule.mem_top + exact Module.isUnimodular_of_apply_eq_one hφ + obtain ⟨m, hm, hIm⟩ := Ideal.exists_le_maximal I hI + obtain ⟨s, hs⟩ := ‹Module.Projective k R›.out + -- The dual basis puts `1` in `𝔪 R`. + have h1 : (1 : R) ∈ m • (⊤ : Submodule k R) := by + rw [← hs 1, Finsupp.linearCombination_apply] + exact Submodule.sum_mem _ fun j _ ↦ + Submodule.smul_mem_smul (hIm ⟨Finsupp.lapply j ∘ₗ s, rfl⟩) trivial + -- Hence every `x = x · 1` is in `𝔪 R`. + have htop : (⊤ : Submodule k R) ≤ m • ⊤ := fun x _ ↦ by + have hx := Submodule.mem_map_of_mem (f := LinearMap.mulLeft k x) h1 + rw [Submodule.map_smul'', LinearMap.mulLeft_apply, mul_one] at hx + exact Submodule.smul_mono le_rfl le_top hx + obtain ⟨r, hr1, hr⟩ := Submodule.exists_sub_one_mem_and_smul_eq_zero_of_fg_of_le_smul m ⊤ + (Module.finite_def.mp inferInstance) htop + have hrm : r ∉ m := fun h ↦ hm.ne_top ((Ideal.eq_top_iff_one _).mpr (by + simpa using m.sub_mem h hr1)) + refine hR ⟨m, hm.isPrime⟩ ((Module.rankAtStalk_eq_zero_iff_notMem_support _).mpr ?_) + rw [Module.mem_support_iff_of_finite] + exact fun h ↦ hrm (h (Module.mem_annihilator.mpr fun x ↦ hr x trivial)) + +/-- **`GPR 16.4`: a quadratic algebra is conic.** A unital algebra that is finitely generated +projective of constant rank `2` over a commutative ring carries a conic structure. See the module +docstring for the construction: `R = k·1 ⊕ L` with `L` of rank one, and the norm of `λ·1 + a` is +`λ² + λ α(a) - ν(a, a)`, where `a² = ν(a, a)·1 + α(a) a`. -/ +theorem nonempty_of_rankAtStalk_eq_two (hR : Module.rankAtStalk (R := k) R = fun _ ↦ 2) : + Nonempty (ConicAlgebra k R) := by + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp + (isUnimodular_one_of_rankAtStalk_ne_zero (R := R) fun p ↦ by rw [hR]; norm_num) + -- The splitting `R = k·1 ⊕ L`. + let L := LinearMap.ker l + let π : R →ₗ[k] L := + (LinearMap.id - (LinearMap.toSpanSingleton k R 1) ∘ₗ l).codRestrict L fun x ↦ + LinearMap.mem_ker.mpr (by simp [LinearMap.toSpanSingleton_apply, hl]) + have hπ (x : R) : (π x : R) = x - l x • (1 : R) := by + simp [π, LinearMap.toSpanSingleton_apply] + have hdecomp (x : R) : x = l x • (1 : R) + (π x : R) := by rw [hπ]; abel + have hπL (y : L) : π y = y := Subtype.ext (by + rw [hπ, LinearMap.mem_ker.mp y.2, zero_smul, sub_zero]) + have hπ1 : π 1 = 0 := Subtype.ext (by rw [hπ, hl, one_smul, sub_self]; rfl) + have : Module.Finite k L := Module.Finite.of_surjective π fun y ↦ ⟨y, hπL y⟩ + have : Module.Projective k L := + Module.Projective.of_split (M := R) L.subtype π (LinearMap.ext hπL) + -- `L` has rank one. + let e : R ≃ₗ[k] k × L := LinearMap.equivProdKerOfApplyEqOne l 1 hl + have hLrank : Module.rankAtStalk (R := k) L = 1 := by + funext p + have : Nontrivial k := ⟨⟨0, 1, fun h ↦ p.isPrime.ne_top + ((Ideal.eq_top_iff_one _).mpr (h ▸ p.asIdeal.zero_mem))⟩⟩ + have h := congrFun hR p + rw [Module.rankAtStalk_eq_of_equiv e, Module.rankAtStalk_prod, Pi.add_apply, + Module.rankAtStalk_self, Pi.one_apply] at h + rw [Pi.one_apply] + omega + -- On a module of rank one, `φ(x) y = φ(y) x`. + have hpair := (show Module.IsLocallyFreeRankOne k L from + ⟨inferInstance, inferInstance, hLrank⟩).isRankOnePairing + have hrk (φ : Module.Dual k L) (x y : L) : φ x • y = φ y • x := by + rw [← sub_eq_zero, ← Module.forall_dual_apply_eq_zero_iff k] + intro ψ + rw [map_sub, map_smul, map_smul, smul_eq_mul, smul_eq_mul, hpair φ ψ x y, sub_self] + -- A finite dual basis of `L`. + obtain ⟨n, f, hf⟩ := Module.Finite.exists_fin' k L + obtain ⟨g, hg⟩ := Module.projective_lifting_property f LinearMap.id hf + have hexp (a : L) : a = ∑ j, g a j • f (Pi.single j 1) := by + conv_lhs => rw [← LinearMap.id_apply (R := k) a, ← hg, LinearMap.comp_apply, + pi_eq_sum_univ (g a)] + simp only [map_sum, map_smul] + refine Finset.sum_congr rfl fun j _ ↦ ?_ + congr 2 + funext i + simp [Pi.single_apply, eq_comm] + -- The two components of multiplication on `L`, and the scalar `α`. + let mulL : L →ₗ[k] L →ₗ[k] R := (LinearMap.mul k R).compl₁₂ L.subtype L.subtype + let μ : L →ₗ[k] L →ₗ[k] L := mulL.compr₂ π + let ν : L →ₗ[k] L →ₗ[k] k := mulL.compr₂ l + have hmulL (a b : L) : (a : R) * b = ν a b • (1 : R) + (μ a b : R) := hdecomp _ + let α : L →ₗ[k] k := ∑ j, (LinearMap.proj j ∘ₗ g) ∘ₗ μ.flip (f (Pi.single j 1)) + have hμ (a : L) : μ a a = α a • a := by + rw [show μ a a = μ a (∑ j, g a j • f (Pi.single j 1)) from congrArg (μ a) (hexp a)] + simp only [map_sum, map_smul, α, LinearMap.sum_apply, Finset.sum_smul, LinearMap.comp_apply, + LinearMap.flip_apply] + refine Finset.sum_congr rfl fun j _ ↦ ?_ + exact hrk (LinearMap.proj j ∘ₗ g) a (μ a (f (Pi.single j 1))) + -- The norm. + let B : LinearMap.BilinMap k R k := + (LinearMap.mul k k).compl₁₂ l l + (LinearMap.mul k k).compl₁₂ l (α ∘ₗ π) - + ν.compl₁₂ π π + have hB (x y : R) : B x y = l x * l y + l x * α (π y) - ν (π x) (π y) := rfl + let N : QuadraticForm k R := B.toQuadraticMap + have hN (x : R) : N x = l x * l x + l x * α (π x) - ν (π x) (π x) := rfl + have hpolar (x : R) : QuadraticMap.polar N 1 x = 2 * l x + α (π x) := by + rw [LinearMap.BilinMap.polar_toQuadraticMap, hB, hB, hπ1, hl] + simp only [map_zero, LinearMap.zero_apply, mul_one, one_mul, mul_zero, sub_zero] + ring + refine ⟨{ norm := N, norm_one := ?_, mul_self := fun x ↦ ?_ }⟩ + · rw [hN, hπ1, hl] + simp + · rw [hpolar, hN] + set c := l x + set a := π x + have hx : x = c • (1 : R) + (a : R) := hdecomp x + rw [hx] + simp only [add_mul, mul_add, smul_mul_assoc, mul_smul_comm, one_mul, mul_one, hmulL, hμ, + Submodule.coe_smul] + module + +/-- A chosen conic structure on a quadratic algebra (`GPR 16.4`). By `GPR 16.16` it is the only +one (`ConicAlgebra.eq_ofRankTwo`). -/ +noncomputable def ofRankTwo (hR : Module.rankAtStalk (R := k) R = fun _ ↦ 2) : + ConicAlgebra k R := + Classical.choice (nonempty_of_rankAtStalk_eq_two hR) + +/-- Every conic structure on a quadratic algebra is the chosen one: conic norms on a finitely +generated projective algebra are unique (`GPR 16.16`). -/ +theorem eq_ofRankTwo (hR : Module.rankAtStalk (R := k) R = fun _ ↦ 2) (C : ConicAlgebra k R) : + C = ofRankTwo hR := + ConicAlgebra.ext (norm_eq_of_projective C (ofRankTwo hR)) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Recognition.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Recognition.lean new file mode 100644 index 0000000000..1cd8f30278 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Recognition.lean @@ -0,0 +1,303 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.RingTheory.TwoSidedIdeal.Basic +public import LeanPool.CompositionAlgebrasOverRings.Conic.Kirmse +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective + +/-! +# Recognizing a conic algebra by a multiplicative norm (`GPR 19.3`) + +`GPR 19.3` starts from a *pre-composition algebra* (`GPR 19.1`): a unital algebra `A` over a +commutative ring `k`, projective as a `k`-module, carrying a quadratic form `n` that is +non-degenerate in `GPR`'s sense (`QuadraticMap.radical n = ⊥`, i.e. +`QuadraticForm.IsGPRNondegenerate`) and permits composition, `n 1 = 1` and `n(xy) = n(x) n(y)`. +It concludes: + +1. `A` is a conic algebra with norm `n`; +2. `A` is alternative; +3. `n` is the unique conic norm on `A`; +4. the polar radical `A⊥ = {x | n(x, y) = 0 for all y}` (`GPR`'s `C⊥`) is an ideal contained in + the centre, and `2 A⊥ = n(x, y) A⊥ = 0` for all `x, y`. + +This file proves all four. Throughout, `n(x, y)` is the **un-halved** polar form +`QuadraticMap.polar n x y` (overview §6(a)), and nothing is assumed about `2`. + +## Relation to `Conic/Kirmse.lean` + +`Conic/Kirmse.lean` proves the alternativity statement of `GPR 19.3` +(`ConicAlgebra.IsMultiplicative.isAlternative`) with the conic structure, i.e. the degree-two +identity `x² = t(x) x - n(x) 1`, as an *input*. Clause 1 removes that input: +`ConicAlgebra.ofMultiplicative` builds the conic structure from the bare form, and +`ConicAlgebra.isAlternative_ofMultiplicative` feeds it to the Kirmse theorem. Clause 2 thus +uses `GPR`'s argument in two halves, the degree-two identity here and Kirmse's identities there. + +## Proof outline + +*Clause 1* follows `GPR`. Linearizing `n(xy) = n(x) n(y)` gives `(19.1.3)`–`(19.1.5)` using +only distributivity (`QuadraticForm.polar_mul_mul_left_of_map_mul` and its companions in +`Conic/Multiplicative.lean`); with `t(y) := n(1, y)` they give `n(xy, x) = n(x) t(y)` `(19.3.1)` and +`t(x²) = t(x)² - 2 n(x)` `(19.3.2)`. Then `w := x² - t(x) x + n(x) 1` satisfies `n(w, y) = 0` for +all `y` and `n(w) = 0`, so `w` lies in the radical of `n`, which is zero. + +*Clause 4*: the ideal property is norm-associativity (`GPR (16.12.3)`, `(16.12.4)`). On `A⊥` the +form `n` is additive, and its zeros there form the radical, so `n` is injective on `A⊥`; this +gives centrality (`(xy)z` and `x(yz)` lie in `A⊥` and have the same norm) and `2 A⊥ = 0` exactly +as in `GPR`. For `n(x, y) A⊥ = 0` the proof departs from `GPR`, which uses that conjugation fixes +`A⊥` together with `GPR (16.12.5)`. Here `(19.1.4)` gives `n(x, y) n(z) = n(xz, yz) = 0` for +`z ∈ A⊥`, since `xz ∈ A⊥`. Hence `n(n(x, y) z) = n(x, y)² n(z) = 0`, and `n(x, y) z ∈ A⊥`, so it +lies in the radical. + +## Main definitions + +* `ConicAlgebra.ofMultiplicative` : the conic algebra with norm `n`, from `n 1 = 1`, + `n(xy) = n(x) n(y)` and `n.IsGPRNondegenerate` (`GPR 19.3`, first assertion). +* `ConicAlgebra.IsMultiplicative.polarRadical` : the polar radical `A⊥` of a multiplicative conic + algebra, as a two-sided ideal. + +## Main results + +* `QuadraticForm.mul_self_sub_polar_smul_add_smul_mem_radical_of_map_mul`, + `QuadraticForm.mul_self_eq_of_map_mul` : the degree-two identity, up to the radical and exactly. +* `ConicAlgebra.isMultiplicative_ofMultiplicative`, `ConicAlgebra.isAlternative_ofMultiplicative` : + the constructed conic algebra is multiplicative and alternative (`GPR 19.3`). +* `ConicAlgebra.eq_ofMultiplicative` : on a finitely generated projective algebra, every conic + structure is the constructed one; in particular its norm is `n` (`GPR 19.3`, via `GPR 16.16`). +* `ConicAlgebra.IsMultiplicative.mul_mem_ker_polarBilin_left`, + `ConicAlgebra.IsMultiplicative.mul_mem_ker_polarBilin_right` : `A⊥` is an ideal. +* `QuadraticMap.injOn_ker_polarBilin` (in `QuadraticForm/Regularity.lean`) : a form with + vanishing radical is injective on `A⊥`. +* `ConicAlgebra.IsMultiplicative.mem_center_of_mem_ker_polarBilin` : `A⊥` is central. +* `QuadraticMap.two_smul_eq_zero_of_mem_ker_polarBilin` (in `QuadraticForm/Regularity.lean`) : + `2 A⊥ = 0`. +* `ConicAlgebra.IsMultiplicative.polar_smul_eq_zero_of_mem_ker_polarBilin` : `n(x, y) A⊥ = 0`. + +## Implementation notes + +**Hypotheses.** `GPR` assumes `A` projective throughout. Clauses 1, 2 and 4 need no hypothesis +on the module, and are stated without one (overview §2). Clause 4 is stated for an arbitrary +multiplicative conic algebra `C`, with `C.norm.IsGPRNondegenerate` only where it is consumed; the +ideal property needs no regularity at all. It applies to `ConicAlgebra.ofMultiplicative n …`, +whose norm is `n` by definition. + +⚠ **Clause 3 assumes finite generation, which `GPR` does not.** `GPR 16.16` asks only that the +algebra be projective; the project's `ConicAlgebra.norm_eq_of_projective`, which is used here, +also assumes `Module.Finite`. + +⚠ **`A⊥` is the kernel of the polar form, not the radical of `n`.** `GPR` writes `Rad(Dn)` for the +former and `Rad(n)` for the latter; they are `LinearMap.ker (QuadraticMap.polarBilin n)` and +`QuadraticMap.radical n` in mathlib. The radical is zero by hypothesis, but `A⊥` need not be: +`x ↦ x²` on `𝔽₂` has zero polar form. When `2 ∈ kˣ` the two agree +(`QuadraticMap.radical_eq_ker_polarBilin`), so clause 4 has content only when `2` is not a unit. + +The linearizations of multiplicativity are needed for a bare quadratic form, because the conic +structure is not yet available; `Conic/Multiplicative.lean` proves them in that form and derives +the conic versions from them. The facts about the kernel of the polar form use no algebra +structure and live in `QuadraticForm/Regularity.lean`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.4, 16.12, 16.16, + 19.1, 19.3. +-/ + +@[expose] public section + +universe u v + +open QuadraticMap + +/-! ### The degree-two identity from a multiplicative form -/ + +namespace QuadraticForm + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + {Q : QuadraticForm k A} + +/-- `GPR (19.3.1)`: `n(xy, x) = n(x) t(y)` with `t(y) = n(1, y)`; `(19.1.3)` at `z = 1`. -/ +private theorem polar_mul_self_of_map_mul (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) (x y : A) : + polar Q (x * y) x = Q x * polar Q 1 y := by + have h := polar_mul_mul_left_of_map_mul hmul x y 1 + rwa [mul_one, polar_comm Q y 1] at h + +/-- `GPR (19.3.2)`: `t(x²) = t(x)² - 2 n(x)`; `(19.1.5)` at `y = x`, `w = z = 1` (in `GPR`'s +variables). -/ +private theorem polar_mul_self_one_of_map_mul (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) + (x : A) : polar Q (x * x) 1 = polar Q 1 x ^ 2 - 2 * Q x := by + have h := polar_mul_add_polar_mul_of_map_mul hmul x 1 x 1 + rw [mul_one, mul_one, one_mul, polar_self, polar_comm Q x 1, nsmul_eq_mul] at h + push_cast at h + linear_combination h + +/-- **The degree-two defect lies in the radical** (`GPR 19.3`, proof): if `Q` permits +composition and `Q 1 = 1`, then `w = x² - t(x) x + Q(x) 1`, with `t(x) = n(1, x)`, satisfies +`n(w, y) = 0` for all `y` and `Q w = 0`. The first is `(19.1.5)` at `z = x`, `w = 1` (in `GPR`'s +variables), combined with `(19.3.1)`; the second expands `Q w` into six terms, which cancel by +`(19.3.1)` at `y = x` and `(19.3.2)`. No regularity, no hypothesis on `2`, and none on the +module. -/ +theorem mul_self_sub_polar_smul_add_smul_mem_radical_of_map_mul (hone : Q 1 = 1) + (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) (x : A) : + x * x - polar Q 1 x • x + Q x • (1 : A) ∈ Q.radical := by + have hsub (a b : A) : Q (a - b) = Q a + Q b - polar Q a b := by + rw [sub_eq_add_neg, QuadraticMap.map_add Q, polar_neg_right, QuadraticMap.map_neg] + ring + refine ⟨?_, LinearMap.ext fun y ↦ ?_⟩ + · rw [QuadraticMap.map_add Q, hsub] + simp only [hmul, QuadraticMap.map_smul, hone, polar_sub_left, polar_smul_left, + polar_smul_right, polar_mul_self_of_map_mul hmul, polar_mul_self_one_of_map_mul hmul, + polar_comm Q x 1, smul_eq_mul] + ring + · have h := polar_mul_add_polar_mul_of_map_mul hmul x 1 y x + rw [one_mul, one_mul, polar_mul_self_of_map_mul hmul, polar_comm Q x 1, + polar_comm Q y x] at h + rw [polarBilin_apply_apply, LinearMap.zero_apply, polar_add_left, polar_sub_left, + polar_smul_left, polar_smul_left, smul_eq_mul, smul_eq_mul] + linear_combination h + +/-- **The degree-two identity from a multiplicative norm** (`GPR 19.3`): if `Q 1 = 1`, +`Q (xy) = Q x * Q y`, and `Q` is non-degenerate in `GPR`'s sense (`Q.radical = ⊥`), then +`x² = t(x) x - Q(x) 1` with `t(x) = n(1, x)`. This is the axiom `ConicAlgebra.mul_self`. -/ +theorem mul_self_eq_of_map_mul (hone : Q 1 = 1) (hmul : ∀ x y : A, Q (x * y) = Q x * Q y) + (hrad : Q.IsGPRNondegenerate) (x : A) : + x * x = polar Q 1 x • x - Q x • (1 : A) := by + have hw := mul_self_sub_polar_smul_add_smul_mem_radical_of_map_mul hone hmul x + rw [show Q.radical = ⊥ from hrad, Submodule.mem_bot] at hw + rw [← sub_eq_zero, ← hw] + abel + +end QuadraticForm + +/-! ### The conic structure -/ + +namespace ConicAlgebra + +section OfMultiplicative + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + +/-- **`GPR 19.3`, first assertion: a quadratic form permitting composition makes the algebra +conic.** Given a quadratic form `n` with `n 1 = 1` and `n(xy) = n(x) n(y)` whose radical vanishes +(`GPR`'s non-degeneracy, `QuadraticForm.IsGPRNondegenerate`), this is the conic algebra with norm +`n`; the degree-two identity is `QuadraticForm.mul_self_eq_of_map_mul`. + +`GPR` assumes the algebra projective (a pre-composition algebra, `GPR 19.1`); the construction +does not need it. -/ +def ofMultiplicative (n : QuadraticForm k A) (hone : n 1 = 1) + (hmul : ∀ x y : A, n (x * y) = n x * n y) (hrad : n.IsGPRNondegenerate) : + ConicAlgebra k A where + norm := n + norm_one := hone + mul_self := QuadraticForm.mul_self_eq_of_map_mul hone hmul hrad + +variable (n : QuadraticForm k A) (hone : n 1 = 1) (hmul : ∀ x y : A, n (x * y) = n x * n y) + (hrad : n.IsGPRNondegenerate) + +@[simp] theorem ofMultiplicative_norm : (ofMultiplicative n hone hmul hrad).norm = n := rfl + +/-- The conic algebra `ConicAlgebra.ofMultiplicative n …` is multiplicative: its norm is `n`. -/ +theorem isMultiplicative_ofMultiplicative : + (ofMultiplicative n hone hmul hrad).IsMultiplicative := + hmul + +include hone hmul hrad in +/-- **`GPR 19.3`, alternativity: an algebra with a non-degenerate quadratic form permitting +composition is alternative.** Here non-degenerate is `GPR`'s sense, `n.radical = ⊥`. The conic +structure is `ConicAlgebra.ofMultiplicative`, and alternativity is then Kirmse's theorem +`ConicAlgebra.IsMultiplicative.isAlternative`. No hypothesis on the module and none on `2`. -/ +theorem isAlternative_ofMultiplicative [SMulCommClass k A A] [IsScalarTower k A A] : + IsAlternative A := + (isMultiplicative_ofMultiplicative n hone hmul hrad).isAlternative hrad + +/-- **`GPR 19.3`, uniqueness of the norm.** On a finitely generated projective algebra, every +conic structure `D` is `ConicAlgebra.ofMultiplicative n …`; in particular `D.norm = n`, and `n` is +the only non-degenerate quadratic form permitting composition. This is `GPR 16.16` +(`ConicAlgebra.norm_eq_of_projective`). + +⚠ `GPR 16.16` assumes only projectivity; `ConicAlgebra.norm_eq_of_projective` also assumes finite +generation, and so does this theorem. -/ +theorem eq_ofMultiplicative [Module.Finite k A] [Module.Projective k A] (D : ConicAlgebra k A) : + D = ofMultiplicative n hone hmul hrad := + ConicAlgebra.ext (norm_eq_of_projective D _) + +end OfMultiplicative + +/-! ### The polar radical of a multiplicative conic algebra -/ + +namespace IsMultiplicative + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] {C : ConicAlgebra k A} + +omit [SMulCommClass k A A] in +/-- **The polar radical is a left ideal** (`GPR 19.3`): if `n(z, ·) = 0` then `n(xz, ·) = 0`, by +norm-associativity `n(xz, y) = n(z, (conj x) y)` (`GPR (16.12.4)`). No regularity is needed. -/ +theorem mul_mem_ker_polarBilin_left (h : C.IsMultiplicative) (x : A) {z : A} + (hz : z ∈ LinearMap.ker C.norm.polarBilin) : x * z ∈ LinearMap.ker C.norm.polarBilin := + mem_ker_polarBilin_iff.mpr fun y ↦ by + rw [h.polar_mul_left, mem_ker_polarBilin_iff.mp hz] + +omit [IsScalarTower k A A] in +/-- **The polar radical is a right ideal** (`GPR 19.3`): if `n(z, ·) = 0` then `n(zx, ·) = 0`, by +norm-associativity `n(zx, y) = n(z, y (conj x))` (`GPR (16.12.3)`). No regularity is needed. -/ +theorem mul_mem_ker_polarBilin_right (h : C.IsMultiplicative) {z : A} + (hz : z ∈ LinearMap.ker C.norm.polarBilin) (x : A) : z * x ∈ LinearMap.ker C.norm.polarBilin := + mem_ker_polarBilin_iff.mpr fun y ↦ by + rw [h.polar_mul_right, mem_ker_polarBilin_iff.mp hz] + +/-- The **polar radical** `C⊥ = Rad(D n_C) = {x | n(x, y) = 0 for all y}` of a multiplicative +conic algebra, as a two-sided ideal (`GPR 19.3`). Its carrier is the kernel of the polar form +`LinearMap.ker C.norm.polarBilin`, which is also a `k`-submodule. ⚠ It is not the radical +`QuadraticMap.radical C.norm` of the norm; see the module docstring. -/ +def polarRadical (h : C.IsMultiplicative) : TwoSidedIdeal A := + TwoSidedIdeal.mk' (LinearMap.ker C.norm.polarBilin) (zero_mem _) add_mem neg_mem + (fun hy ↦ h.mul_mem_ker_polarBilin_left _ hy) (fun hx ↦ h.mul_mem_ker_polarBilin_right hx _) + +@[simp] theorem mem_polarRadical (h : C.IsMultiplicative) {z : A} : + z ∈ h.polarRadical ↔ z ∈ LinearMap.ker C.norm.polarBilin := + TwoSidedIdeal.mem_mk' .. + +/-- **The polar radical is central** (`GPR 19.3`): for a multiplicative conic algebra whose norm +has vanishing radical, every `z` with `n(z, ·) = 0` lies in the centre `Set.center A` (`GPR 8.4`: +it commutes with everything and associates in every position). The elements `(xy)z` and `x(yz)` +lie in the polar radical and have the same norm `n(x) n(y) n(z)`, so they are equal because the +norm is injective there (`QuadraticMap.injOn_ker_polarBilin`); likewise for the other positions +and for `xz = zx`. -/ +theorem mem_center_of_mem_ker_polarBilin (h : C.IsMultiplicative) + (hrad : C.norm.IsGPRNondegenerate) {z : A} (hz : z ∈ LinearMap.ker C.norm.polarBilin) : + z ∈ Set.center A := by + have hinj := injOn_ker_polarBilin (show C.norm.radical = ⊥ from hrad) + rw [Set.mem_center_iff] + refine ⟨fun a ↦ ?_, fun b c ↦ ?_, fun a b ↦ ?_⟩ + · exact hinj (h.mul_mem_ker_polarBilin_right hz a) (h.mul_mem_ker_polarBilin_left a hz) + (by rw [h.norm_mul, h.norm_mul, mul_comm]) + · exact hinj (h.mul_mem_ker_polarBilin_right hz _) + (h.mul_mem_ker_polarBilin_right (h.mul_mem_ker_polarBilin_right hz b) c) + (by simp only [h.norm_mul]; ring) + · exact hinj (h.mul_mem_ker_polarBilin_left _ hz) + (h.mul_mem_ker_polarBilin_left a (h.mul_mem_ker_polarBilin_left b hz)) + (by simp only [h.norm_mul]; ring) + +omit [SMulCommClass k A A] in +/-- **The polar form kills the polar radical** (`GPR 19.3`: `n(x, y) C⊥ = 0`). For `z` with +`n(z, ·) = 0`, `GPR (19.1.4)` gives `n(x, y) n(z) = n(xz, yz) = 0`, since `xz` is again in the +polar radical. So `n(n(x, y) z) = n(x, y)² n(z) = 0`, and `n(x, y) z` lies in the radical of the +norm, which vanishes. The argument differs from `GPR`'s, which goes through `GPR (16.12.5)` and +the fact that conjugation fixes the polar radical. -/ +theorem polar_smul_eq_zero_of_mem_ker_polarBilin (h : C.IsMultiplicative) + (hrad : C.norm.IsGPRNondegenerate) (x y : A) {z : A} + (hz : z ∈ LinearMap.ker C.norm.polarBilin) : polar C.norm x y • z = 0 := by + have h0 : polar C.norm x y * C.norm z = 0 := by + rw [← h.polar_mul_mul_right x y z] + exact mem_ker_polarBilin_iff.mp (h.mul_mem_ker_polarBilin_left x hz) (y * z) + have hmem : polar C.norm x y • z ∈ C.norm.radical := + ⟨by rw [QuadraticMap.map_smul, smul_eq_mul, mul_assoc, h0, mul_zero], + LinearMap.mem_ker.mp (Submodule.smul_mem _ _ hz)⟩ + rwa [show C.norm.radical = ⊥ from hrad, Submodule.mem_bot] at hmem + +end IsMultiplicative + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Subalgebra.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Subalgebra.lean new file mode 100644 index 0000000000..90836c581a --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Subalgebra.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Subalgebra + +/-! +# Restricting a conic structure to a subalgebra + +A unital subalgebra `B` of a conic algebra `(A, n)` is again a conic algebra, with the restricted +norm `n|_B`. Nothing has to be checked beyond the two axioms of `GPR 16.1`, both of which are +inherited: `n(1) = 1` because `B` contains the ambient unit, and the degree-two identity because it +is an identity in `A` between elements of `B`. + +Trace, conjugation and multiplicativity are likewise the ambient ones restricted, which is what +makes the subalgebra usable as an input to the Cayley–Dickson construction. + +## Main definitions + +* `ConicAlgebra.restrict` : the conic algebra `B` carved out of `C : ConicAlgebra k A`. + +## Main results + +* `ConicAlgebra.restrict_norm_apply`, `ConicAlgebra.restrict_trace_apply`, + `ConicAlgebra.coe_restrict_conj` : norm, trace and conjugation restrict. +* `ConicAlgebra.IsMultiplicative.restrict` : so does multiplicativity of the norm. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.1. +-/ + +@[expose] public section + +universe u v + +namespace ConicAlgebra + +variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] + [SMulCommClass k A A] [IsScalarTower k A A] (C : ConicAlgebra k A) + (B : NonAssocSubalgebra k A) + +/-- The norm of `C` restricted to a unital subalgebra. -/ +def normRestrict : QuadraticForm k B := + C.norm.comp B.toNonUnitalSubalgebra.toSubmodule.subtype + +variable {C B} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem normRestrict_apply (b : B) : C.normRestrict B b = C.norm (b : A) := rfl + +variable (C B) + +/-- **A unital subalgebra of a conic algebra is a conic algebra**, with the restricted norm. + +Both axioms are inherited verbatim; in particular no regularity, projectivity or rank hypothesis is +involved, and the subalgebra need not be associative. -/ +def restrict : ConicAlgebra k B where + norm := C.normRestrict B + norm_one := C.norm_one + mul_self b := by + apply Subtype.ext + simp only [AddSubgroupClass.coe_sub, SetLike.val_smul, OneMemClass.coe_one, + MulMemClass.coe_mul] + exact C.mul_self (b : A) + +variable {C B} + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem restrict_norm_apply (b : B) : (C.restrict B).norm b = C.norm (b : A) := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem restrict_trace_apply (b : B) : (C.restrict B).trace b = C.trace (b : A) := rfl + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +@[simp] theorem coe_restrict_conj (b : B) : ((C.restrict B).conj b : A) = C.conj (b : A) := by + rw [conj_apply, conj_apply] + simp only [AddSubgroupClass.coe_sub, SetLike.val_smul, OneMemClass.coe_one, + restrict_trace_apply] + +omit [SMulCommClass k A A] [IsScalarTower k A A] in +/-- Multiplicativity of the norm is inherited by every unital subalgebra. -/ +theorem IsMultiplicative.restrict (h : C.IsMultiplicative) : (C.restrict B).IsMultiplicative := + fun x y ↦ h (x : A) (y : A) + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/TraceDefectCounterexample.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/TraceDefectCounterexample.lean new file mode 100644 index 0000000000..b72a3b4f82 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/TraceDefectCounterexample.lean @@ -0,0 +1,247 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic + +/-! +# An associative conic algebra whose conjugation is not an anti-homomorphism + +Over a **field**, the conjugation of an alternative conic algebra is an algebra anti-homomorphism +(`ConicAlgebra.conj_mul`). This file shows that over a general commutative ring it is not — not +even for an **associative** conic algebra — so that the hypotheses of `ConicAlgebra.conj_mul` are +not decoration and cannot be dropped in the ring-theoretic layers. + +## The example + +Let `k = ℤ/4`, let `M = (ℤ/2)²` regarded as a `k`-module, and let `β : M × M → k` be the +`k`-bilinear form `β(m, p) = 2 m₁ p₂` (this is well defined because `2 · x` in `ℤ/4` depends only +on `x` mod `2`). On `A = k × M` put + + `(a, m) * (b, p) = (ab + β(m, p), a • p + b • m)`, `1 = (1, 0)`, + `n (a, m) = a² - β(m, m)`. + +Then: + +* `A` is an associative unital `k`-algebra (`TraceDefectCounterexample.Carrier.mul_assoc`) — + associativity + of the `M`-component asks `β(m, p) • q = β(p, q) • m`, and both sides lie in `2 · M = 0`; +* `(A, n)` is a conic algebra (`TraceDefectCounterexample.conic`), with trace `t (a, m) = 2a`; +* but `t(xy) ≠ t(x)t(y) - n(x, y)` for `x = m₁`, `y = m₂` + (`TraceDefectCounterexample.traceDefect_ne_zero`), and therefore + `conj (xy) ≠ conj y * conj x` (`TraceDefectCounterexample.conj_mul_ne`). + +Concretely `m₁ m₂ = 2 · 1` while `m₂ m₁ = 0`, and `conj (m₁ m₂) = 2 · 1` while +`conj m₂ * conj m₁ = m₂ m₁ = 0`. + +`A` is finitely generated but **not projective** over `k`, and that is exactly what fails: the +proof of `ConicAlgebra.traceDefect_eq_zero` over a field uses that a vector outside `k · 1` +generates a free direct summand, and `ConicAlgebra.traceDefect_smul_eq_smul_one` — which does hold +here, alternativity being all it needs — is powerless when `traceDefect x y • x` can vanish for a +nonzero scalar. Here `traceDefect m₁ m₂ = -2 = 2` and `2 • m₁ = 0`. + +## Relation to the literature + +None of this contradicts `GPR`, which is careful about it throughout: `GPR 16.10(a)` states that +the conjugation of a conic algebra is an involution **iff** `t(x, y) - n(x, conj y) ∈ Ann(C)` — the +trace defect up to sign, and `Ann(A) = 0` here — while the theorems that do give an involution, +`GPR 16.14(b)` and `GPR 17.6`, carry a projectivity hypothesis on the module. `GPR 17.4` flags the +tempting false claim in as many words and points at `GPR Exc. 17.8` (due to McCrimmon) for a +counterexample. + +That exercise is essentially this example, and this file is a smaller variant of it. There `k` is +the dual numbers `k₀[ε]`, `ε² = 0`, and `C = k ⊕ k₀³` with `(a, u)(b, v) = (ab, a·v + b·u + [u, v])` +and `n_z(a, u) = a² + (a zᵀu)ε`; conditions (i)–(iv) of the exercise say that the conjugation is an +involution iff `zᵀ[u, v] = 0`. Here `ℤ/4` plays the part of `k₀[ε]` with `2` as `ε` and `ℤ/2` that +of `k₀`; rank `2` suffices instead of `3` because the non-symmetric `β` is imposed directly rather +than obtained as a commutator. + +## Implementation notes + +The axioms are checked in coordinates. The only finite checks about the structure itself concern +`β` on the four-element module `M`: it is additive and `ℤ/4`-linear in each slot, and its values +annihilate `M` (`Carrier.beta_add_left`, …, `Carrier.beta_smul`), each closed by `decide` over at +most `64` cases. Distributivity, associativity, the scalar laws, bilinearity of the companion form +and the quadratic-form axioms then follow by `ring` and `module` on the coordinates, and +alternativity follows from associativity. The degree-two identity and the statements about `m₁` +and `m₂` are closed by `decide`. No `native_decide` (overview §5). + +Closing every axiom by `decide` over all `16³` triples of `A` also works, but takes about ten +times as long to elaborate. + +The instance `Module (ℤ/4) (ℤ/2)` is `local`: it is needed to build the example and must not +escape into the rest of the development. + +## References + +* The ⚠ paragraph in `CompositionAlgebras/Conic/Basic.lean`, which this file substantiates. +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 16.10, 16.14, 17.4, + 17.6, and Exc. 17.8. +* K. McCrimmon, the source of `GPR Exc. 17.8` (`GPR`'s reference [189]). +-/ + +@[expose] public section + +namespace ConicAlgebra + +namespace TraceDefectCounterexample + +open scoped ZMod + +/-- The `ZMod 4`-module structure on `ZMod 2` induced by reduction modulo `2`. -/ +local instance : Module (ZMod 4) (ZMod 2) := + Module.compHom (ZMod 2) (ZMod.castHom (by norm_num) (ZMod 2)) + +/-- The carrier `k · 1 ⊕ M` of the counterexample, with `k = ℤ/4` and `M = (ℤ/2)²`. -/ +def Carrier := ZMod 4 × ZMod 2 × ZMod 2 + +namespace Carrier + +instance : AddCommGroup Carrier := inferInstanceAs (AddCommGroup (ZMod 4 × ZMod 2 × ZMod 2)) +instance : DecidableEq Carrier := inferInstanceAs (DecidableEq (ZMod 4 × ZMod 2 × ZMod 2)) +instance : Fintype Carrier := inferInstanceAs (Fintype (ZMod 4 × ZMod 2 × ZMod 2)) +instance : Module (ZMod 4) Carrier := + inferInstanceAs (Module (ZMod 4) (ZMod 4 × ZMod 2 × ZMod 2)) + +/-- The `ℤ/4`-bilinear form `β(m, p) = 2 m₁ p₂` on `(ℤ/2)²`. It is *not* symmetric, which is the +whole point: the trace defect of the resulting conic algebra is `β(p, m) - β(m, p)`. -/ +def beta (m p : ZMod 2 × ZMod 2) : ZMod 4 := ((2 * m.1.val * p.2.val : ℕ) : ZMod 4) + +/-! ### `β` is bilinear, and its values annihilate `M` + +These are the only finite checks about the structure; each runs over at most `64` cases. -/ + +theorem beta_add_left (m m' p : ZMod 2 × ZMod 2) : beta (m + m') p = beta m p + beta m' p := by + revert m m' p; decide + +theorem beta_add_right (m p p' : ZMod 2 × ZMod 2) : beta m (p + p') = beta m p + beta m p' := by + revert m p p'; decide + +theorem beta_smul_left (a : ZMod 4) (m p : ZMod 2 × ZMod 2) : beta (a • m) p = a * beta m p := by + revert a m p; decide + +theorem beta_smul_right (a : ZMod 4) (m p : ZMod 2 × ZMod 2) : beta m (a • p) = a * beta m p := by + revert a m p; decide + +/-- The values of `β` lie in `2 · ℤ/4`, which annihilates `M`. This is what makes the +multiplication associative. -/ +theorem beta_smul (m p q : ZMod 2 × ZMod 2) : beta m p • q = 0 := by + revert m p q; decide + +theorem beta_zero_left (p : ZMod 2 × ZMod 2) : beta 0 p = 0 := by revert p; decide + +theorem beta_zero_right (m : ZMod 2 × ZMod 2) : beta m 0 = 0 := by revert m; decide + +instance : Mul Carrier := ⟨fun x y ↦ (x.1 * y.1 + beta x.2 y.2, x.1 • y.2 + y.1 • x.2)⟩ +instance : One Carrier := ⟨(1, 0)⟩ + +/-! ### Coordinates -/ + +theorem ext {x y : Carrier} (h₁ : x.1 = y.1) (h₂ : x.2 = y.2) : x = y := Prod.ext h₁ h₂ + +@[simp] theorem fst_add (x y : Carrier) : (x + y).1 = x.1 + y.1 := rfl +@[simp] theorem snd_add (x y : Carrier) : (x + y).2 = x.2 + y.2 := rfl +@[simp] theorem fst_zero : (0 : Carrier).1 = 0 := rfl +@[simp] theorem snd_zero : (0 : Carrier).2 = 0 := rfl +@[simp] theorem fst_one : (1 : Carrier).1 = 1 := rfl +@[simp] theorem snd_one : (1 : Carrier).2 = 0 := rfl +@[simp] theorem fst_smul (a : ZMod 4) (x : Carrier) : (a • x).1 = a * x.1 := rfl +@[simp] theorem snd_smul (a : ZMod 4) (x : Carrier) : (a • x).2 = a • x.2 := rfl +@[simp] theorem fst_mul (x y : Carrier) : (x * y).1 = x.1 * y.1 + beta x.2 y.2 := rfl +@[simp] theorem snd_mul (x y : Carrier) : (x * y).2 = x.1 • y.2 + y.1 • x.2 := rfl + +/-! ### The algebra structure -/ + +instance : NonAssocRing Carrier := + { (inferInstance : AddCommGroup Carrier), (inferInstance : Mul Carrier), + (inferInstance : One Carrier) with + left_distrib x y z := ext (by simp only [fst_mul, fst_add, snd_add, beta_add_right]; ring) + (by simp only [snd_mul, fst_add, snd_add]; module) + right_distrib x y z := ext (by simp only [fst_mul, fst_add, snd_add, beta_add_left]; ring) + (by simp only [snd_mul, fst_add, snd_add]; module) + zero_mul x := ext (by simp [beta_zero_left]) (by simp) + mul_zero x := ext (by simp [beta_zero_right]) (by simp) + one_mul x := ext (by simp [beta_zero_left]) (by simp) + mul_one x := ext (by simp [beta_zero_right]) (by simp) } + +instance : SMulCommClass (ZMod 4) Carrier Carrier where + smul_comm a x y := by + change a • (x * y) = x * (a • y) + exact ext (by simp only [fst_smul, fst_mul, snd_smul, beta_smul_right]; ring) + (by simp only [snd_smul, snd_mul, fst_smul]; module) + +instance : IsScalarTower (ZMod 4) Carrier Carrier where + smul_assoc a x y := by + change (a • x) * y = a • (x * y) + exact ext (by simp only [fst_smul, fst_mul, snd_smul, beta_smul_left]; ring) + (by simp only [snd_smul, snd_mul, fst_smul]; module) + +/-- The multiplication is **associative**: the two sides of associativity differ only in the +`M`-component, where they are `β(m, p) • q` and `β(p, q) • m`, both in `2 · M = 0` +(`Carrier.beta_smul`). -/ +theorem mul_assoc (x y z : Carrier) : x * y * z = x * (y * z) := + ext (by + simp only [fst_mul, snd_mul, beta_add_left, beta_add_right, beta_smul_left, beta_smul_right] + ring) + (by + simp only [fst_mul, snd_mul, add_smul, beta_smul, add_zero] + module) + +instance : IsAlternative Carrier := + ⟨fun a b ↦ (mul_assoc a a b).symm, fun a b ↦ mul_assoc b a a⟩ + +/-- The companion bilinear form of the norm: `n(x, y) = 2 a b - β(m, p) - β(p, m)`. -/ +def polarForm : Carrier →ₗ[ZMod 4] Carrier →ₗ[ZMod 4] ZMod 4 := + LinearMap.mk₂ (ZMod 4) (fun x y ↦ 2 * x.1 * y.1 - beta x.2 y.2 - beta y.2 x.2) + (fun x x' y ↦ by simp only [fst_add, snd_add, beta_add_left, beta_add_right]; ring) + (fun a x y ↦ by + simp only [fst_smul, snd_smul, beta_smul_left, beta_smul_right, smul_eq_mul]; ring) + (fun x y y' ↦ by simp only [fst_add, snd_add, beta_add_left, beta_add_right]; ring) + (fun a x y ↦ by + simp only [fst_smul, snd_smul, beta_smul_left, beta_smul_right, smul_eq_mul]; ring) + +/-- The norm `n (a, m) = a² - β(m, m)`. -/ +def norm : QuadraticForm (ZMod 4) Carrier where + toFun x := x.1 * x.1 - beta x.2 x.2 + toFun_smul a x := by + simp only [fst_smul, snd_smul, beta_smul_left, beta_smul_right, smul_eq_mul]; ring + exists_companion' := ⟨polarForm, fun x y ↦ by + simp only [polarForm, LinearMap.mk₂_apply, fst_add, snd_add, beta_add_left, beta_add_right] + ring⟩ + +end Carrier + +/-- The conic algebra structure: `n 1 = 1` and `x² = t(x) • x - n(x) • 1`. -/ +def conic : ConicAlgebra (ZMod 4) Carrier where + norm := Carrier.norm + norm_one := by decide + mul_self := by decide + +/-- The first basis vector of `M`, as an element of the algebra. -/ +def m₁ : Carrier := (0, 1, 0) + +/-- The second basis vector of `M`, as an element of the algebra. -/ +def m₂ : Carrier := (0, 0, 1) + +theorem m₁_mul_m₂ : m₁ * m₂ = (2 : ZMod 4) • (1 : Carrier) := by decide + +theorem m₂_mul_m₁ : m₂ * m₁ = 0 := by decide + +/-- **The trace defect of an associative conic algebra can be nonzero**: here it is `-2 = 2`. -/ +theorem traceDefect_eq : conic.traceDefect m₁ m₂ = 2 := by decide + +theorem traceDefect_ne_zero : conic.traceDefect m₁ m₂ ≠ 0 := by decide + +/-- **Conjugation need not be an anti-homomorphism**, even for an associative conic algebra: over +`ℤ/4`, `conj (m₁ m₂) = 2 · 1` but `conj m₂ * conj m₁ = 0`. + +Contrast `ConicAlgebra.conj_mul`, which gives the anti-homomorphism property for alternative conic +algebras over a *field*. -/ +theorem conj_mul_ne : conic.conj (m₁ * m₂) ≠ conic.conj m₂ * conic.conj m₁ := by decide + +end TraceDefectCounterexample + +end ConicAlgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/Imports.lean b/LeanPool/CompositionAlgebrasOverRings/Imports.lean new file mode 100644 index 0000000000..8e4ebec134 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Imports.lean @@ -0,0 +1,113 @@ +/- +Copyright (c) 2026 Lean Pool contributors. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Lean Pool contributors +-/ +module -- shake: keep-all --deprecated_module: ignore + +-- Generated project imports; run `lake exe mk_all`. +public import LeanPool.CompositionAlgebrasOverRings +public import LeanPool.CompositionAlgebrasOverRings.Composition.Alternative +public import LeanPool.CompositionAlgebrasOverRings.Composition.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Composition.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Composition.CayleyDicksonIff +public import LeanPool.CompositionAlgebrasOverRings.Composition.ComplexQuaternion +public import LeanPool.CompositionAlgebrasOverRings.Composition.Defs +public import LeanPool.CompositionAlgebrasOverRings.Composition.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Composition.Examples +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Basic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Finite +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.FractionField +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.Real +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.SepClosed +public import LeanPool.CompositionAlgebrasOverRings.Composition.Fields.SurjectiveNorm +public import LeanPool.CompositionAlgebrasOverRings.Composition.Inseparable +public import LeanPool.CompositionAlgebrasOverRings.Composition.InseparableAnisotropic +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormClassification +public import LeanPool.CompositionAlgebrasOverRings.Composition.NormEquivalence +public import LeanPool.CompositionAlgebrasOverRings.Composition.Octonion +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticEtale +public import LeanPool.CompositionAlgebrasOverRings.Composition.QuadraticSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankDichotomy +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankOneTwoFourEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.RankTwoSubalgebra +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Capstone +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Classification +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Defs +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Orientation +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.OrientedRankEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankEight +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.RankTwo +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Reducedness +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Split +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Splitness +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedMatrix +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.TwistedZorn +public import LeanPool.CompositionAlgebrasOverRings.Composition.Reduced.Zorn +public import LeanPool.CompositionAlgebrasOverRings.Composition.Sedenion +public import LeanPool.CompositionAlgebrasOverRings.Composition.Tower +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChange +public import LeanPool.CompositionAlgebrasOverRings.Conic.BaseChangeMultiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Basic +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAlternative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonAssociative +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonConverse +public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDicksonMultiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Defs +public import LeanPool.CompositionAlgebrasOverRings.Conic.Division +public import LeanPool.CompositionAlgebrasOverRings.Conic.Doubling +public import LeanPool.CompositionAlgebrasOverRings.Conic.Kirmse +public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative +public import LeanPool.CompositionAlgebrasOverRings.Conic.Projective +public import LeanPool.CompositionAlgebrasOverRings.Conic.QuadraticAlgebra +public import LeanPool.CompositionAlgebrasOverRings.Conic.Recognition +public import LeanPool.CompositionAlgebrasOverRings.Conic.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.Conic.TraceDefectCounterexample +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ConstantRank +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import LeanPool.CompositionAlgebrasOverRings.LGRing.DirectLimit +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Examples +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Jacobson +public import LeanPool.CompositionAlgebrasOverRings.LGRing.NonExamples +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Products +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Semilocal +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ValueIdeal +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ZeroDimensional +public import LeanPool.CompositionAlgebrasOverRings.Module.AlternatingBaseChange +public import LeanPool.CompositionAlgebrasOverRings.Module.ExteriorPower +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentDecomposition +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentFactor +public import LeanPool.CompositionAlgebrasOverRings.Module.Invertible +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition +public import LeanPool.CompositionAlgebrasOverRings.Module.SelfAnnihilating +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.Module.VectorProduct +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Artin +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Moufang +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Peirce +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.PowerAssociative +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Associator +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Division +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Subalgebra +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Cancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.FiniteField +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.HyperbolicPair +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Isotropic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.NonsingularOverFields +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.OrthogonalComplement +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneCancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneSplitting +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneTransitivity +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Polynomial +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Real +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Representation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.WittCancellation diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/ConstantRank.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/ConstantRank.lean new file mode 100644 index 0000000000..42ad6cbbc5 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/ConstantRank.lean @@ -0,0 +1,141 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Unimodular +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus + +/-! +# Constant-rank projective modules over an LG-ring are free (`GN 2.6(b)`, `GPR 11.24`) + +This is *the* motto of LG-rings, made precise: over an LG-ring, a finitely generated projective +module whose rank is the same at every prime is free. + +## Main results + +* `Module.nontrivial_quotient_tensor_of_rankAtStalk_pos` : positive rank at a maximal ideal makes + the residue-field fibre nonzero — the bridge from `Module.rankAtStalk` to the hypothesis of + `IsLGRing.exists_isUnimodular`. +* `Module.free_of_isLGRing_of_rankAtStalk_eq` : **`GN 2.6(b)`**, by induction on the rank. + +## Proof idea + +Induct on the common rank `d`, with `M` generalized. + +At `d = 0` the module is a subsingleton (`Module.rankAtStalk_eq_zero_iff_subsingleton`), hence +free. At `d + 1` the rank is positive at every prime, so every residue-field fibre is nonzero and +`GN 2.6(a)` (`IsLGRing.exists_isUnimodular`, `LGRing/Unimodular.lean`) produces a unimodular +`m ∈ M`. That splits `M ≃ R × ker l` (`LinearMap.equivProdKerOfApplyEqOne`), and +`Module.rankAtStalk_prod` together with `Module.rankAtStalk_self` turns the rank equation into +`rankAtStalk (ker l) = d` — constant again, one lower. The induction hypothesis makes `ker l` +free, and `R × ker l` is then free, hence so is `M`. + +The complement is `ker l`, a `Submodule R M`: it lives in the same universe as `M`, which is what +lets the induction quantify over a single `Type v`. + +## Implementation notes + +The rank is `Module.rankAtStalk`, mathlib's rank of the localization at a prime. Everything the +induction needs — additivity over products, invariance under equivalence, the value at `R`, and +vanishing exactly on subsingletons — is already in +`Mathlib.RingTheory.Spectrum.Prime.FreeLocus`, so this file adds no rank theory of its own. + +The one genuinely new bridge is `Module.nontrivial_quotient_tensor_of_rankAtStalk_pos`: the LG +axiom speaks about residue fields `R ⧸ 𝔪`, whereas `rankAtStalk` is defined through localizations +`R_𝔪`. `Module.rankAtStalk_baseChange` relates them — base changing `M` to the field `R ⧸ 𝔪` and +reading the rank at that field's unique prime `⊥` gives back the rank of `M` at `𝔪`, because +`⊥` pulls back along `R → R ⧸ 𝔪` to `𝔪`. Over a field every module is free, so that rank is a +`finrank`, and a positive `finrank` forces nontriviality. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Lemma 2.6(b), + also stated as 2.1(c). +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.24. +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-- A module that splits off a free rank-one summand from a finitely generated module is itself +finitely generated. -/ +theorem Module.Finite.of_linearEquiv_prod {N : Type v} [AddCommGroup N] [Module R N] + [Module.Finite R M] (e : M ≃ₗ[R] R × N) : Module.Finite R N := + haveI : Module.Finite R (R × N) := Module.Finite.equiv e + Module.Finite.of_surjective (LinearMap.snd R R N) Prod.snd_surjective + +/-- A module that splits off a free rank-one summand from a projective module is itself +projective. -/ +theorem Module.Projective.of_linearEquiv_prod {N : Type v} [AddCommGroup N] [Module R N] + [Module.Projective R M] (e : M ≃ₗ[R] R × N) : Module.Projective R N := + haveI : Module.Projective R (R × N) := Module.Projective.of_equiv' e + Module.Projective.of_split (LinearMap.inr R R N) (LinearMap.snd R R N) (by ext x; simp) + +/-- Positive rank at a maximal ideal makes the residue-field fibre nonzero. + +This is the bridge from `Module.rankAtStalk`, which is defined through the localization `R_𝔪`, to +the hypothesis of `IsLGRing.exists_isUnimodular`, which — like the LG axiom itself — speaks about +the residue field `R ⧸ 𝔪`. See the module docstring. -/ +theorem Module.nontrivial_quotient_tensor_of_rankAtStalk_pos [Module.Finite R M] + [Module.Projective R M] (𝔪 : Ideal R) (h𝔪 : 𝔪.IsMaximal) + (h : 0 < Module.rankAtStalk (R := R) M ⟨𝔪, h𝔪.isPrime⟩) : + Nontrivial ((R ⧸ 𝔪) ⊗[R] M) := by + let : Field (R ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + refine Module.nontrivial_of_finrank_pos (R := R ⧸ 𝔪) ?_ + have hcomap : (PrimeSpectrum.comap (algebraMap R (R ⧸ 𝔪)) ⊥ : PrimeSpectrum R) = + ⟨𝔪, h𝔪.isPrime⟩ := by + refine PrimeSpectrum.ext ?_ + change Ideal.comap (algebraMap R (R ⧸ 𝔪)) ⊥ = 𝔪 + rw [← RingHom.ker_eq_comap_bot, Ideal.Quotient.algebraMap_eq] + exact Ideal.mk_ker + have := Module.rankAtStalk_baseChange (R := R) (M := M) (S := R ⧸ 𝔪) ⊥ + rw [hcomap, Module.rankAtStalk_eq_finrank_of_free] at this + simp only [Pi.natCast_apply, Nat.cast_id] at this + omega + +/-- **`GN 2.6(b)`, `GPR 11.24`.** Over an LG-ring, a finitely generated projective module of +constant rank is free. + +The rank is `Module.rankAtStalk`, and "constant" means literally the constant function `d`. See +the module docstring for the induction. -/ +theorem Module.free_of_isLGRing_of_rankAtStalk_eq (hLG : IsLGRing R) (d : ℕ) : + ∀ (M : Type v) [AddCommGroup M] [Module R M] [Module.Finite R M] [Module.Projective R M], + Module.rankAtStalk (R := R) M = (fun _ ↦ d) → Module.Free R M := by + induction d with + | zero => + intro M _ _ _ _ h + have : Subsingleton M := Module.rankAtStalk_eq_zero_iff_subsingleton.mp h + exact Module.Free.of_subsingleton R M + | succ d ih => + intro M _ _ _ _ h + rcases subsingleton_or_nontrivial R with hR | hR + · have : Subsingleton M := Module.subsingleton R M + exact Module.Free.of_subsingleton R M + -- Positive rank everywhere, so `GN 2.6(a)` produces a unimodular element. + obtain ⟨m, hm⟩ := hLG.exists_isUnimodular (M := M) fun 𝔪 h𝔪 ↦ + Module.nontrivial_quotient_tensor_of_rankAtStalk_pos 𝔪 h𝔪 (by + rw [h]; exact Nat.succ_pos d) + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hm + set e := LinearMap.equivProdKerOfApplyEqOne l m hl with he + have : Module.Finite R (LinearMap.ker l) := Module.Finite.of_linearEquiv_prod e + have : Module.Projective R (LinearMap.ker l) := Module.Projective.of_linearEquiv_prod e + -- The complement has constant rank `d`, one lower. + have hker : Module.rankAtStalk (R := R) (LinearMap.ker l) = (fun _ ↦ d) := by + have hprod := Module.rankAtStalk_prod (R := R) R (LinearMap.ker l) + have hM := Module.rankAtStalk_eq_of_equiv e + rw [hprod, Module.rankAtStalk_self] at hM + funext p + have := congrFun (hM.symm.trans h) p + simp only [Pi.add_apply, Pi.one_apply] at this + omega + have := ih (LinearMap.ker l) hker + exact Module.Free.of_equiv (R := R) (M := R × (LinearMap.ker l)) e.symm diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Defs.lean new file mode 100644 index 0000000000..dda100485d --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Defs.lean @@ -0,0 +1,169 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.MvPolynomial.Eval +public import Mathlib.RingTheory.Ideal.Quotient.Operations +public import Mathlib.Tactic.FieldSimp + +/-! +# LG rings + +Defines `IsLGRing R` (`GPR 11.20`, `GN 2.1`): a commutative ring `R` is an **LG-ring** +("local–global ring") if, for every `n` and every `f ∈ R[X₁,…,Xₙ]`, `f` represents a unit over +`R` iff `f` represents a unit over every residue field `R/𝔪`, `𝔪` maximal. LG rings are the class +of commutative rings where most results of undergraduate linear algebra for vector spaces also +hold for finitely generated projective modules — see the overview's "Why LG rings" section. + +## Main definitions + +* `MvPolynomial.RepresentsUnit p S` : `p`, viewed as a polynomial over the `R`-algebra `S`, + evaluates to a unit at some point of `S`. +* `IsLGRing R` : `GPR 11.20`. + +## Main results + +* `MvPolynomial.aeval_map_comm` : evaluation transports along a commuting square of ring + homomorphisms. This is the workhorse behind every change-of-ring argument in this directory. +* `exists_isUnit_of_isUnit_quotient` : if `R` is LG, then for every `b : R`, every unit of + `R ⧸ (b)` lifts to a unit of `R`. This is the key structural consequence used to build + non-examples (`LGRing/NonExamples.lean`): a ring where `Rˣ → (R ⧸ (b))ˣ` fails to be surjective, + for some choice of `b`, cannot be LG. + +## Implementation notes + +`GPR 11.20` states the defining biconditional using residue fields, and remarks that it is +equivalent to use the localization `R_𝔪` instead. `GN 2.1` adds a third equivalent formulation, +"represents a unit over every field `F ∈ R`-alg" — but this project does not reprove that +three-way equivalence, and an earlier version of this file took that third formulation as the +*definition*, which turned out to make `GPR 11.21` (`R` LG iff `R ⧸ Jac(R)` LG) genuinely harder +to prove: a field receiving `R` through a non-maximal prime need not have any relationship to a +residue field of `R`, so the bridge between the two rings' field-algebras breaks down. Residue +fields of `R` and of `R ⧸ Jac(R)` correspond exactly (every maximal ideal contains the Jacobson +radical), which is what makes `LGRing/Jacobson.lean` go through. So this file uses `GPR`'s own +formulation (residue fields), matching the primary source, not the alternative from `GN`. + +Constructing the `Field (R ⧸ 𝔪)` instance from `𝔪.IsMaximal` (via `Ideal.Quotient.field`) is a +well-known mathlib performance/diamond hazard when combined with other instances derived from the +same quotient in the same context. We avoid it entirely by working with the `Prop`-valued +`IsField (R ⧸ 𝔪)` (via `Ideal.Quotient.maximal_ideal_iff_isField_quotient`) instead of the bundled +`Field` structure wherever we need "nonzero ⇒ invertible" — `IsField` carries no data, so there is +nothing for two different derivations of it to disagree about. + +The forward direction of the biconditional (`RepresentsUnit p R → ∀ 𝔪, RepresentsUnit p (R ⧸ 𝔪)`) +holds for **any** commutative ring `R`, LG or not: `IsUnit` is preserved by every ring +homomorphism, so a witness over `R` pushes forward to a witness over any quotient. The entire +content of the LG axiom is in the converse. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.20. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §2.1. +-/ + +@[expose] public section + +universe u v + +/-- `p`, viewed as a polynomial over the `R`-algebra `S`, represents a unit: it evaluates to a +unit at some point of `S`. -/ +def MvPolynomial.RepresentsUnit {R : Type u} [CommRing R] {n : ℕ} (p : MvPolynomial (Fin n) R) + (S : Type v) [CommRing S] [Algebra R S] : Prop := + ∃ s : Fin n → S, IsUnit (MvPolynomial.aeval s p) + +/-- `R` is an **LG-ring** (`GPR 11.20`, "local–global ring"): a polynomial in finitely many +variables over `R` represents a unit over `R` iff it represents a unit over every residue field +`R ⧸ 𝔪`, `𝔪` maximal. See the implementation notes for why this formulation (rather than `GN`'s +"every field `F ∈ R`-alg" alternative) is taken as the definition. -/ +def IsLGRing (R : Type u) [CommRing R] : Prop := + ∀ (n : ℕ) (p : MvPolynomial (Fin n) R), + p.RepresentsUnit R ↔ ∀ (𝔪 : Ideal R) [𝔪.IsMaximal], p.RepresentsUnit (R ⧸ 𝔪) + +/-- If `ψ : S → S'` sits over `φ : R → R'` — that is, the square of structure maps commutes — +then evaluating `p` over `S` and transporting agrees with reducing `p`'s coefficients along `φ` +and evaluating over `S'`. Compare `aeval_map_quotient` in `LGRing/Jacobson.lean`, which is the +special case of reduction modulo an ideal. + +Every transport of `MvPolynomial.RepresentsUnit` in this directory is an instance of this square: +see `MvPolynomial.RepresentsUnit.mapOfComm` and `MvPolynomial.RepresentsUnit.ofMapOfComm` in +`LGRing/Products.lean`. -/ +theorem MvPolynomial.aeval_map_comm {R : Type*} [CommRing R] {R' : Type*} [CommRing R'] + (φ : R →+* R') {S : Type*} [CommRing S] [Algebra R S] {S' : Type*} [CommRing S'] + [Algebra R' S'] (ψ : S →+* S') + (hcomm : ψ.comp (algebraMap R S) = (algebraMap R' S').comp φ) + {n : ℕ} (s : Fin n → S) (p : MvPolynomial (Fin n) R) : + MvPolynomial.aeval (fun i ↦ ψ (s i)) (MvPolynomial.map φ p) + = ψ (MvPolynomial.aeval s p) := by + simp only [MvPolynomial.aeval_def] + rw [MvPolynomial.eval₂_map, MvPolynomial.hom_eval₂, hcomm] + +/-! ### Units lift along quotients by a principal ideal + +The test polynomial is `u + b·T` (one variable): linear, not quadratic, and the argument routes +entirely through the LG axiom rather than through any explicit field-case computation. -/ + +/-- The affine polynomial `u + b·T`, in one variable. -/ +noncomputable def linUC {R : Type u} [CommRing R] (u b : R) : MvPolynomial (Fin 1) R := + MvPolynomial.C u + MvPolynomial.C b * MvPolynomial.X 0 + +@[simp] +theorem aeval_linUC {R : Type u} [CommRing R] {S : Type v} [CommRing S] [Algebra R S] + (s : Fin 1 → S) (u b : R) : + MvPolynomial.aeval s (linUC u b) = algebraMap R S u + algebraMap R S b * s 0 := by + simp [linUC] + +/-- **If `R` is LG, every unit of `R ⧸ (b)` lifts to a unit of `R`.** + +Given `ū ∈ (R ⧸ (b))ˣ`, lift it (non-canonically) to `u, v : R` with `u ≡ ū`, `v ≡ ū⁻¹`, so that +`uv = 1 + bw` for some `w`. The polynomial `u + b·T` represents a unit over *every* residue field +`R ⧸ 𝔪`: if `b ↦ 0`, then `u ↦` a unit already (from `uv = 1 + bw` reducing to `uv = 1`), so +`T = 0` works; if `b ↦` something nonzero, `T = (1 - u)/b` gives `u + bT ↦ 1`. By the LG axiom this +descends to `R` itself: some `u + bt₀ ∈ Rˣ`, and it is `≡ u ≡ ū` mod `(b)`. -/ +theorem exists_isUnit_of_isUnit_quotient {R : Type u} [CommRing R] (hLG : IsLGRing R) (b : R) + (ū : (R ⧸ Ideal.span {b})ˣ) : + ∃ u' : Rˣ, Ideal.Quotient.mk (Ideal.span {b}) (u' : R) = (ū : R ⧸ Ideal.span {b}) := by + obtain ⟨u, hu⟩ := Ideal.Quotient.mk_surjective (ū : R ⧸ Ideal.span {b}) + obtain ⟨v, hv⟩ := Ideal.Quotient.mk_surjective (↑(ū⁻¹) : R ⧸ Ideal.span {b}) + have huv : Ideal.Quotient.mk (Ideal.span {b}) (u * v - 1) = 0 := by + rw [map_sub, map_mul, hu, hv, map_one] + exact_mod_cast sub_eq_zero.mpr ū.mul_inv + rw [Ideal.Quotient.eq_zero_iff_mem, Ideal.mem_span_singleton'] at huv + obtain ⟨w, hw⟩ := huv + have hkey : (linUC u b).RepresentsUnit R := by + apply (hLG 1 (linUC u b)).mpr + intro 𝔪 hmax + have hfield : IsField (R ⧸ 𝔪) := + (Ideal.Quotient.maximal_ideal_iff_isField_quotient 𝔪).mp hmax + by_cases hb : algebraMap R (R ⧸ 𝔪) b = 0 + · refine ⟨fun _ ↦ 0, ?_⟩ + rw [aeval_linUC, hb, zero_mul, add_zero] + have hune : algebraMap R (R ⧸ 𝔪) u ≠ 0 := by + intro hcontra + have heq : + algebraMap R (R ⧸ 𝔪) (u * v - 1) = algebraMap R (R ⧸ 𝔪) (w * b) := by + rw [hw] + simp only [map_sub, map_mul, map_one, hb, mul_zero, hcontra, zero_mul, zero_sub] at heq + exact one_ne_zero (neg_eq_zero.mp heq) + obtain ⟨c, hc⟩ := hfield.mul_inv_cancel hune + exact IsUnit.of_mul_eq_one c hc + · obtain ⟨c, hc⟩ := hfield.mul_inv_cancel hb + refine ⟨fun _ ↦ c * (1 - algebraMap R (R ⧸ 𝔪) u), ?_⟩ + rw [aeval_linUC] + have heq3 : algebraMap R (R ⧸ 𝔪) u + + algebraMap R (R ⧸ 𝔪) b * (c * (1 - algebraMap R (R ⧸ 𝔪) u)) = 1 := by + have hrw : algebraMap R (R ⧸ 𝔪) b * (c * (1 - algebraMap R (R ⧸ 𝔪) u)) = + (algebraMap R (R ⧸ 𝔪) b * c) * (1 - algebraMap R (R ⧸ 𝔪) u) := by ring + rw [hrw, hc, one_mul]; ring + rw [heq3] + exact isUnit_one + obtain ⟨s, hs⟩ := hkey + rw [aeval_linUC, Algebra.algebraMap_self_apply, Algebra.algebraMap_self_apply] at hs + refine ⟨hs.unit, ?_⟩ + rw [IsUnit.unit_spec, ← hu, Ideal.Quotient.eq] + have heq2 : u + b * s 0 - u = b * s 0 := by ring + rw [heq2] + exact Ideal.mem_span_singleton'.mpr ⟨s 0, mul_comm _ _⟩ diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/DirectLimit.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/DirectLimit.lean new file mode 100644 index 0000000000..1849431acc --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/DirectLimit.lean @@ -0,0 +1,182 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ValueIdeal +public import Mathlib.Algebra.Colimit.Ring +public import Mathlib.Data.Finset.Order + +/-! +# Direct limits of LG-rings + +`GN 2.2` (from `EG`): a filtered colimit of LG-rings is an LG-ring. + +## Main results + +* `MvPolynomial.representsUnit_of_map_of_valueIdeal_eq_top` : the transfer principle. If `p` comes + from a polynomial `q` over an LG-ring `A` along a ring map `A → R`, and `q.valueIdeal = ⊤`, then + `p` represents a unit over `R`. Both examples below are this lemma plus the work of producing + such a `q`. +* `isLGRing_of_directed_subring` : a ring that is the directed union of a family of LG subrings is + an LG-ring. +* `isLGRing_directLimit` : **`GN 2.2`**, the direct limit of a directed system of LG-rings is an + LG-ring. + +## Proof idea + +Everything rests on the *finitary* form of the LG axiom from `LGRing/ValueIdeal.lean`: `R` is LG +iff `p` represents a unit over `R` whenever the values of `p` generate the unit ideal, and that +hypothesis unwinds to one equation + + `1 = Σⱼ cⱼ · p(tⱼ)` + +in finitely many elements of `R`. A finitary condition is exactly what survives passage to a +filtered colimit: the coefficients of `p`, the `cⱼ` and the coordinates of the `tⱼ` are finitely +many elements of `R = colim Gᵢ`, so all of them already live in a single `G_M`; and the equation +between them, being a single equation, already holds in some `G_N` with `M ≤ N`. Then `G_N` is LG, +so the lifted polynomial takes a unit value there, and that unit maps forward to a unit of `R`. + +Note where the argument would break with the *definitional* form of the LG axiom: a maximal ideal +of `G_N` need not be the contraction of any maximal ideal of `R` (take `ℤ ⊆ ℚ`), so there is no way +to feed the residue fields of `R` back into the residue fields of the components. Passing through +the value ideal removes maximal ideals from the argument entirely, which is the whole point. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Example 2.2. +* [EG] Estes, Guralnick, *Module equivalences: local to global when primitive polynomials represent + units*, Journal of Algebra **77** (1982), 138–157. +-/ + +@[expose] public section + +universe u v + +namespace MvPolynomial + +variable {A : Type u} [CommRing A] {R : Type v} [CommRing R] {n k : ℕ} + +/-- A ring map carries a linear combination of values of `q` to the corresponding combination of +values of the reduced polynomial `map φ q`. This is the only computation the two examples share: +in `isLGRing_of_directed_subring` it is used with an injective `φ`, and in `isLGRing_directLimit` +with the structure map of a component. -/ +theorem map_sum_mul_aeval (φ : A →+* R) (q : MvPolynomial (Fin n) A) (c : Fin k → A) + (t : Fin k → Fin n → A) : + φ (∑ j, c j * aeval (t j) q) + = ∑ j, φ (c j) * aeval (fun x ↦ φ (t j x)) (MvPolynomial.map φ q) := by + rw [map_sum] + refine Finset.sum_congr rfl fun j _ ↦ ?_ + rw [map_mul, aeval_map_comm φ φ (by ext x; simp) (t j) q] + +/-- **Transfer along a ring map out of an LG-ring.** If `p` is the reduction of a polynomial `q` +over an LG-ring `A`, and the values of `q` already generate the unit ideal of `A`, then `p` +represents a unit over `R`. + +Only the *hypothesis* of the LG axiom has to be checked over `A`; the conclusion transports for +free, since ring maps preserve units. -/ +theorem representsUnit_of_map_of_valueIdeal_eq_top (φ : A →+* R) (hA : IsLGRing A) + {q : MvPolynomial (Fin n) A} {p : MvPolynomial (Fin n) R} (hq : MvPolynomial.map φ q = p) + (htop : q.valueIdeal = ⊤) : p.RepresentsUnit R := by + obtain ⟨s, hs⟩ := (isLGRing_iff_forall_valueIdeal_eq_top A).mp hA n q htop + refine ⟨fun x ↦ φ (s x), ?_⟩ + rw [← hq, aeval_map_comm φ φ (by ext x; simp) s q] + exact hs.map φ + +end MvPolynomial + +/-! ### Directed unions -/ + +/-- **A directed union of LG subrings is an LG-ring.** + +Given `1 = Σⱼ cⱼ · p(tⱼ)`, the coefficients of `p` together with the `cⱼ` and the coordinates of +the `tⱼ` form a finite subset of `R`, so directedness places all of them inside a single `S z`. +There the equation holds verbatim — `S z → R` is injective — so the lifted polynomial has value +ideal `⊤`, and `S z` being LG finishes it. -/ +theorem isLGRing_of_directed_subring {R : Type u} [CommRing R] {ι : Type v} [Nonempty ι] + (S : ι → Subring R) (hdir : Directed (· ≤ ·) S) (hcov : ∀ x : R, ∃ i, x ∈ S i) + (hLG : ∀ i, IsLGRing (S i)) : IsLGRing R := by + classical + rw [isLGRing_iff_forall_valueIdeal_eq_top] + intro n p htop + obtain ⟨k, c, t, hsum⟩ := MvPolynomial.exists_sum_mul_aeval_eq_one htop + choose idx hidx using hcov + set F : Finset R := p.coeffs ∪ Finset.image c Finset.univ ∪ + Finset.image (fun a : Fin k × Fin n ↦ t a.1 a.2) Finset.univ with hF + obtain ⟨z, hz⟩ := hdir.finset_le (F.image idx) + have hmem : ∀ x ∈ F, x ∈ S z := fun x hx ↦ + hz (idx x) (Finset.mem_image_of_mem idx hx) (hidx x) + have hcoeff : ∀ x ∈ (p.coeffs : Set R), x ∈ S z := fun x hx ↦ + hmem x (Finset.mem_union_left _ (Finset.mem_union_left _ (by exact_mod_cast hx))) + have hc : ∀ j, c j ∈ S z := fun j ↦ + hmem _ (Finset.mem_union_left _ + (Finset.mem_union_right _ (Finset.mem_image_of_mem c (Finset.mem_univ j)))) + have ht : ∀ j x, t j x ∈ S z := fun j x ↦ + hmem _ (Finset.mem_union_right _ (Finset.mem_image.mpr ⟨(j, x), Finset.mem_univ _, rfl⟩)) + obtain ⟨q, hq⟩ : p ∈ Set.range (MvPolynomial.map (S z).subtype) := by + rw [MvPolynomial.mem_range_map_iff_coeffs_subset] + exact fun x hx ↦ ⟨⟨x, hcoeff x hx⟩, rfl⟩ + refine MvPolynomial.representsUnit_of_map_of_valueIdeal_eq_top (S z).subtype (hLG z) hq + (MvPolynomial.valueIdeal_eq_top_of_sum_mul_aeval_eq_one (fun j ↦ ⟨c j, hc j⟩) + (fun j x ↦ ⟨t j x, ht j x⟩) ?_) + have key := MvPolynomial.map_sum_mul_aeval (S z).subtype q (fun j ↦ (⟨c j, hc j⟩ : S z)) + (fun j x ↦ (⟨t j x, ht j x⟩ : S z)) + rw [hq] at key + exact Subtype.coe_injective (key.trans hsum) + +/-! ### Direct limits -/ + +/-- **`GN 2.2`: a direct limit of LG-rings is an LG-ring.** + +The finitely many elements of `colim Gᵢ` appearing in `1 = Σⱼ cⱼ · p(tⱼ)` all come from a single +component `G_M` (`Ring.DirectLimit.exists_of`, plus directedness of `ι` to merge the finitely many +indices), which lets `p` be lifted to `q` over `G_M`. The lifted equation need not hold in `G_M` +itself — only its image in the colimit is known to be `1` — but the discrepancy dies somewhere +along the system (`Ring.DirectLimit.of.zero_exact`), so it does hold in `G_N` for some `N ≥ M`. +Then `G_N` is LG and `MvPolynomial.representsUnit_of_map_of_valueIdeal_eq_top` applies to +`of G _ N`. -/ +theorem isLGRing_directLimit {ι : Type v} [Preorder ι] [Nonempty ι] [IsDirectedOrder ι] + (G : ι → Type u) [∀ i, CommRing (G i)] (f : ∀ i j, i ≤ j → G i →+* G j) + [DirectedSystem G fun i j h ↦ f i j h] (hLG : ∀ i, IsLGRing (G i)) : + IsLGRing (Ring.DirectLimit G (f · · ·)) := by + classical + rw [isLGRing_iff_forall_valueIdeal_eq_top] + intro n p htop + obtain ⟨k, c, t, hsum⟩ := MvPolynomial.exists_sum_mul_aeval_eq_one htop + choose idx elt helt using fun z : Ring.DirectLimit G (f · · ·) ↦ + Ring.DirectLimit.exists_of (G := G) (f := (f · · ·)) z + set F : Finset (Ring.DirectLimit G (f · · ·)) := p.coeffs ∪ Finset.image c Finset.univ ∪ + Finset.image (fun a : Fin k × Fin n ↦ t a.1 a.2) Finset.univ with hF + obtain ⟨M, hM⟩ := (F.image idx).exists_le + have hrange : ∀ x ∈ F, ∃ y : G M, Ring.DirectLimit.of G (f · · ·) M y = x := fun x hx ↦ + ⟨f (idx x) M (hM _ (Finset.mem_image_of_mem idx hx)) (elt x), + (Ring.DirectLimit.of_f _ _).trans (helt x)⟩ + choose lift hlift using hrange + obtain ⟨q, hq⟩ : + p ∈ Set.range (MvPolynomial.map (Ring.DirectLimit.of G (f · · ·) M)) := by + rw [MvPolynomial.mem_range_map_iff_coeffs_subset] + exact fun x hx ↦ ⟨lift x (Finset.mem_union_left _ + (Finset.mem_union_left _ (by exact_mod_cast hx))), hlift x _⟩ + set c' : Fin k → G M := fun j ↦ lift (c j) (Finset.mem_union_left _ + (Finset.mem_union_right _ (Finset.mem_image_of_mem c (Finset.mem_univ j)))) with hc' + set t' : Fin k → Fin n → G M := fun j x ↦ lift (t j x) + (Finset.mem_union_right _ (Finset.mem_image.mpr ⟨(j, x), Finset.mem_univ _, rfl⟩)) with ht' + -- the lifted equation holds in the colimit … + have hM0 : Ring.DirectLimit.of G (f · · ·) M + ((∑ j, c' j * MvPolynomial.aeval (t' j) q) - 1) = 0 := by + rw [map_sub, map_one, MvPolynomial.map_sum_mul_aeval, hq, sub_eq_zero] + simp only [hc', ht', hlift] + exact hsum + -- … hence already in some component `G N` + obtain ⟨N, hMN, hN⟩ := Ring.DirectLimit.of.zero_exact (f' := f) hM0 + refine MvPolynomial.representsUnit_of_map_of_valueIdeal_eq_top + (Ring.DirectLimit.of G (f · · ·) N) (hLG N) (q := MvPolynomial.map (f M N hMN) q) ?_ + (MvPolynomial.valueIdeal_eq_top_of_sum_mul_aeval_eq_one (fun j ↦ f M N hMN (c' j)) + (fun j x ↦ f M N hMN (t' j x)) ?_) + · rw [MvPolynomial.map_map, ← hq] + exact congrArg (MvPolynomial.map · q) (RingHom.ext fun x ↦ Ring.DirectLimit.of_f _ _) + · rw [← MvPolynomial.map_sum_mul_aeval, ← sub_eq_zero, ← map_one (f M N hMN), ← map_sub] + exact hN diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Examples.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Examples.lean new file mode 100644 index 0000000000..59cd275600 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Examples.lean @@ -0,0 +1,67 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs + +/-! +# Examples of LG rings + +## Main results + +* `isLGRing_of_subsingleton` : the zero ring is an LG-ring (`GN 2.2(a)`). +* `isLGRing_of_field` : every field is an LG-ring (`GPR 11.20`, remarked immediately after the + definition). + +## Implementation notes + +`GPR 11.22` continues: semilocal rings are LG, via `GPR 11.21` (`R/Jac(R)` is a finite product of +fields for `R` semilocal, and both the Jacobson-quotient and finite-product cases of the LG +property transfer). Both halves of `GPR 11.21` are now proved — `LGRing/Jacobson.lean` and +`LGRing/Products.lean` — and `GPR 11.22` itself is `isLGRing_of_finite_maximalSpectrum` in +`LGRing/Semilocal.lean`, which is where this theorem is used. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.20, 11.21, + 11.22. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Example 2.2(a). +* [EG] Estes, Guralnick, *Module equivalences: local to global when primitive polynomials represent + units*, Journal of Algebra **77** (1982), 138–157. +-/ + +@[expose] public section + +universe u + +/-- **The zero ring is an LG-ring** (`GN 2.2(a)`). + +Both sides of the defining biconditional are trivially true: the zero ring has no maximal ideal at +all, so the right-hand side is vacuous, and every element of the zero ring — in particular every +value of `p` — is a unit, so the left-hand side holds outright. -/ +theorem isLGRing_of_subsingleton (R : Type u) [CommRing R] [Subsingleton R] : IsLGRing R := + fun _ _ ↦ ⟨fun _ _ _ ↦ ⟨fun _ ↦ 0, isUnit_of_subsingleton _⟩, + fun _ ↦ ⟨fun _ ↦ 0, isUnit_of_subsingleton _⟩⟩ + +/-- Every field is an LG-ring (`GPR 11.20`): the unique maximal ideal is `⊥`, with `K ⧸ ⊥ ≅ K`, so +the defining biconditional is trivial in each direction — the forward direction always holds +(units push forward along any algebra map), and the reverse direction follows by transporting the +witness back along `K ⧸ ⊥ ≅ K`. -/ +theorem isLGRing_of_field (K : Type u) [Field K] : IsLGRing K := by + intro n p + constructor + · rintro ⟨s, hs⟩ 𝔪 _ + refine ⟨fun i ↦ algebraMap K (K ⧸ 𝔪) (s i), ?_⟩ + have heq := MvPolynomial.comp_aeval_apply (f := s) (φ := Algebra.ofId K (K ⧸ 𝔪)) (p := p) + simp only [Algebra.ofId_apply] at heq + exact heq ▸ hs.map (algebraMap K (K ⧸ 𝔪)) + · intro hLG + obtain ⟨s, hs⟩ := @hLG ⊥ Ideal.bot_isMaximal + refine ⟨fun i ↦ (AlgEquiv.quotientBot K K) (s i), ?_⟩ + have heq := MvPolynomial.comp_aeval_apply + (f := s) (φ := (AlgEquiv.quotientBot K K).toAlgHom) (p := p) + exact heq ▸ hs.map (AlgEquiv.quotientBot K K).toRingEquiv.toRingHom diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Jacobson.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Jacobson.lean new file mode 100644 index 0000000000..b74ed5272f --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Jacobson.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import Mathlib.RingTheory.Jacobson.Ideal +public import Mathlib.RingTheory.Jacobson.Radical + +/-! +# `R` is LG iff `R ⧸ Jac(R)` is LG + +The Jacobson-quotient half of `GPR 11.21` (`GN 2.1(b)`): `R` is an LG-ring iff `R ⧸ Jac(R)` is. +The other half of `GPR 11.21` (finite products of LG-rings are LG) is not covered here — see +`LGRing/Products.lean`. + +## Main results + +* `isLGRing_iff_isLGRing_quotient_jacobson` : `IsLGRing R ↔ IsLGRing (R ⧸ Ring.jacobson R)`. + +## Proof idea + +Every maximal ideal `𝔪` of `R` **contains** `Jac(R)` (it is the intersection of all of them), so +maximal ideals of `R` correspond exactly to maximal ideals of `R ⧸ Jac(R)`, via `𝔪 ↦ 𝔪.map π` and +back via `comap π`, where `π : R → R ⧸ Jac(R)` is the quotient map — and the residue fields agree on +the nose: `R ⧸ 𝔪 ≅ (R ⧸ Jac(R)) ⧸ 𝔪.map π` (`residueFieldQuotientJacobsonEquiv`, which is mathlib's +third isomorphism theorem `DoubleQuot.quotQuotEquivQuotOfLE`, applicable because `Jac(R) ≤ 𝔪`). +Transporting a witness for `p.RepresentsUnit` back and forth along this isomorphism and along +`MvPolynomial.map π` (`aeval_comp_residueFieldQuotientJacobsonEquiv`, `aeval_map_quotient`) turns +"`p` represents a unit at every residue field of `R`" into "`p`'s image represents a unit at every +residue field of `R ⧸ Jac(R)`" and back (`represents_unit_quotient_jacobson_of_forall`, +`represents_unit_of_forall_quotient_jacobson`). + +The one place this needs more than bookkeeping: going from "`p`'s image represents a unit over +`R ⧸ Jac(R)`" back to "`p` represents a unit over `R`" needs that a witness whose *image* is a +unit modulo `Jac(R)` was *already* a unit in `R` (`isUnit_of_isUnit_image_jacobson`) — this is +specific to the Jacobson radical (it is false for a general quotient) and is where `1 - j` being a +unit for `j ∈ Jac(R)` actually gets used. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.21(i). +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §2.1(b). +-/ + +@[expose] public section + +universe u v + +/-- If the image of `x` under `R → R ⧸ Jac(R)` is a unit, so is `x` itself. This is specific to +the Jacobson radical: `xz ≡ 1 mod Jac(R)` gives `xz - 1 ∈ Jac(R)`, hence `xz` is a unit (elements +of `1 + Jac(R)` are always units), hence (commutativity) `x` is a unit. -/ +theorem isUnit_of_isUnit_image_jacobson {R : Type u} [CommRing R] (x : R) + (h : IsUnit (Ideal.Quotient.mk (Ring.jacobson R) x)) : IsUnit x := by + obtain ⟨z, hz⟩ := Ideal.Quotient.mk_surjective (↑h.unit⁻¹ : R ⧸ Ring.jacobson R) + have hxz : Ideal.Quotient.mk (Ring.jacobson R) (x * z) = + Ideal.Quotient.mk (Ring.jacobson R) 1 := by + rw [map_mul, hz, map_one]; exact h.mul_val_inv + have hmem : x * z - 1 ∈ Ring.jacobson R := Ideal.Quotient.eq.mp hxz + have hunit_xz : IsUnit (x * z) := by + apply Ideal.isUnit_of_sub_one_mem_jacobson_bot; rwa [Ideal.jacobson_bot] + exact isUnit_of_mul_isUnit_left hunit_xz + +/-- The residue field of `R` at a maximal ideal `𝔪` agrees with the residue field of +`R ⧸ Jac(R)` at the corresponding maximal ideal `𝔪.map π` (`π` the quotient-by-`Jac(R)` map). +This is mathlib's third isomorphism theorem `DoubleQuot.quotQuotEquivQuotOfLE`, which applies +because `Jac(R) ≤ 𝔪`. -/ +noncomputable def residueFieldQuotientJacobsonEquiv {R : Type u} [CommRing R] (𝔪 : Ideal R) + [h𝔪 : 𝔪.IsMaximal] : + R ⧸ 𝔪 ≃+* + (R ⧸ Ring.jacobson R) ⧸ Ideal.map (Ideal.Quotient.mk (Ring.jacobson R)) 𝔪 := + (DoubleQuot.quotQuotEquivQuotOfLE <| by + rw [Ring.jacobson_eq_sInf_isMaximal]; exact sInf_le h𝔪).symm + +@[simp] +theorem residueFieldQuotientJacobsonEquiv_apply {R : Type u} [CommRing R] (𝔪 : Ideal R) + [𝔪.IsMaximal] (r : R) : + residueFieldQuotientJacobsonEquiv 𝔪 (Ideal.Quotient.mk 𝔪 r) = + Ideal.Quotient.mk (Ideal.map (Ideal.Quotient.mk (Ring.jacobson R)) 𝔪) + (Ideal.Quotient.mk (Ring.jacobson R) r) := + rfl + +/-- `aeval` commutes with `residueFieldQuotientJacobsonEquiv`: evaluating `p` at a point of +`R ⧸ 𝔪` and transporting the result along the equivalence agrees with reducing `p`'s coefficients +mod `Jac(R)` first and evaluating at the transported point. -/ +theorem aeval_comp_residueFieldQuotientJacobsonEquiv {R : Type u} [CommRing R] {n : ℕ} + (p : MvPolynomial (Fin n) R) (𝔪 : Ideal R) [𝔪.IsMaximal] (s : Fin n → R ⧸ 𝔪) : + residueFieldQuotientJacobsonEquiv 𝔪 (MvPolynomial.aeval s p) = + MvPolynomial.aeval (fun i ↦ residueFieldQuotientJacobsonEquiv 𝔪 (s i)) + (MvPolynomial.map (Ideal.Quotient.mk (Ring.jacobson R)) p) := by + simp only [MvPolynomial.aeval_def] + have heq := MvPolynomial.hom_eval₂ p (algebraMap R (R ⧸ 𝔪)) + (residueFieldQuotientJacobsonEquiv 𝔪).toRingHom s + simp only [RingEquiv.toRingHom_eq_coe, RingHom.coe_coe] at heq + rw [heq, MvPolynomial.eval₂_map] + congr 1 + +/-- `aeval` commutes with reduction mod any ideal `J`: evaluating `p` at a point of `R` and then +reducing mod `J` agrees with reducing `p`'s coefficients mod `J` first and evaluating at the +reduced point. -/ +theorem aeval_map_quotient {R : Type u} [CommRing R] (J : Ideal R) {n : ℕ} + (p : MvPolynomial (Fin n) R) (t : Fin n → R) : + Ideal.Quotient.mk J (MvPolynomial.aeval t p) = + MvPolynomial.aeval (fun i ↦ Ideal.Quotient.mk J (t i)) + (MvPolynomial.map (Ideal.Quotient.mk J) p) := by + simp only [MvPolynomial.aeval_def] + rw [MvPolynomial.hom_eval₂, MvPolynomial.eval₂_map] + congr 1 + +/-- If `p` represents a unit at every residue field of `R`, its image under `R → R ⧸ Jac(R)` +represents a unit at every residue field of `R ⧸ Jac(R)`: every maximal ideal `𝔐` of +`R ⧸ Jac(R)` is `𝔪.map π` for `𝔪 := comap π 𝔐` maximal in `R`, and the residue fields agree via +`residueFieldQuotientJacobsonEquiv`. -/ +theorem represents_unit_quotient_jacobson_of_forall {R : Type u} [CommRing R] {n : ℕ} + (p : MvPolynomial (Fin n) R) + (hwit : ∀ (𝔪 : Ideal R) [𝔪.IsMaximal], p.RepresentsUnit (R ⧸ 𝔪)) : + ∀ (𝔐 : Ideal (R ⧸ Ring.jacobson R)) [𝔐.IsMaximal], + (MvPolynomial.map (Ideal.Quotient.mk (Ring.jacobson R)) p).RepresentsUnit + ((R ⧸ Ring.jacobson R) ⧸ 𝔐) := by + set J := Ring.jacobson R with hJdef + set π := Ideal.Quotient.mk J with hπdef + have hsurj : Function.Surjective π := Ideal.Quotient.mk_surjective + intro 𝔐 hmax𝔐 + have h𝔪max : (Ideal.comap π 𝔐).IsMaximal := Ideal.comap_isMaximal_of_surjective π hsurj + have hcm : Ideal.map π (Ideal.comap π 𝔐) = 𝔐 := + Ideal.map_comap_of_surjective π hsurj 𝔐 + rw [← hcm] + obtain ⟨s, hs⟩ := hwit (Ideal.comap π 𝔐) + refine ⟨fun i ↦ residueFieldQuotientJacobsonEquiv (Ideal.comap π 𝔐) (s i), ?_⟩ + rw [← aeval_comp_residueFieldQuotientJacobsonEquiv] + exact hs.map _ + +/-- Conversely, if the image of `p` under `R → R ⧸ Jac(R)` represents a unit at every residue +field of `R ⧸ Jac(R)`, then `p` itself represents a unit at every residue field of `R`: for `𝔪` +maximal in `R`, `𝔪.map π` is maximal in `R ⧸ Jac(R)` (`Jac(R) ≤ 𝔪` supplies the kernel +hypothesis), and the residue fields agree via `residueFieldQuotientJacobsonEquiv`. -/ +theorem represents_unit_of_forall_quotient_jacobson {R : Type u} [CommRing R] {n : ℕ} + (p : MvPolynomial (Fin n) R) + (hwit : ∀ (𝔐 : Ideal (R ⧸ Ring.jacobson R)) [𝔐.IsMaximal], + (MvPolynomial.map (Ideal.Quotient.mk (Ring.jacobson R)) p).RepresentsUnit + ((R ⧸ Ring.jacobson R) ⧸ 𝔐)) : + ∀ (𝔪 : Ideal R) [𝔪.IsMaximal], p.RepresentsUnit (R ⧸ 𝔪) := by + set J := Ring.jacobson R with hJdef + set π := Ideal.Quotient.mk J with hπdef + have hsurj : Function.Surjective π := Ideal.Quotient.mk_surjective + intro 𝔪 hmax𝔪 + have hJm : J ≤ 𝔪 := by + rw [hJdef, Ring.jacobson_eq_sInf_isMaximal]; exact sInf_le hmax𝔪 + have hker : RingHom.ker π = J := Ideal.mk_ker + have hkerle : RingHom.ker π ≤ 𝔪 := by rw [hker]; exact hJm + have hmax𝔐 : (𝔪.map π).IsMaximal := + Ideal.IsMaximal.map_of_surjective_of_ker_le hsurj hkerle + obtain ⟨s, hs⟩ := hwit (𝔪.map π) + set e := residueFieldQuotientJacobsonEquiv 𝔪 + refine ⟨fun i ↦ e.symm (s i), ?_⟩ + have heq := aeval_comp_residueFieldQuotientJacobsonEquiv p 𝔪 (fun i ↦ e.symm (s i)) + simp only [RingEquiv.apply_symm_apply, e] at heq + have hunit_e : IsUnit (e (MvPolynomial.aeval (fun i ↦ e.symm (s i)) p)) := heq ▸ hs + simpa using hunit_e.map e.symm.toMonoidHom + +/-- **`GPR 11.21(i)`**: `R` is an LG-ring iff `R ⧸ Jac(R)` is. -/ +theorem isLGRing_iff_isLGRing_quotient_jacobson {R : Type u} [CommRing R] : + IsLGRing R ↔ IsLGRing (R ⧸ Ring.jacobson R) := by + set J := Ring.jacobson R with hJdef + set π := Ideal.Quotient.mk J with hπdef + have hsurj : Function.Surjective π := Ideal.Quotient.mk_surjective + constructor + · intro hLG n q + constructor + · rintro ⟨s, hs⟩ 𝔐 _ + refine ⟨fun i ↦ Ideal.Quotient.mk 𝔐 (s i), ?_⟩ + have heq := MvPolynomial.comp_aeval_apply + (f := s) (φ := Algebra.ofId (R ⧸ J) ((R ⧸ J) ⧸ 𝔐)) (p := q) + simp only [Algebra.ofId_apply] at heq + exact heq ▸ hs.map (algebraMap (R ⧸ J) ((R ⧸ J) ⧸ 𝔐)) + · intro hRHS + obtain ⟨p, hp⟩ := MvPolynomial.map_surjective π hsurj q + subst hp + obtain ⟨t, ht⟩ := (hLG n p).mpr (represents_unit_of_forall_quotient_jacobson p hRHS) + refine ⟨fun i ↦ π (t i), ?_⟩ + rw [← aeval_map_quotient] + exact ht.map π + · intro hLG n p + constructor + · rintro ⟨s, hs⟩ 𝔪 _ + refine ⟨fun i ↦ Ideal.Quotient.mk 𝔪 (s i), ?_⟩ + have heq := MvPolynomial.comp_aeval_apply + (f := s) (φ := Algebra.ofId R (R ⧸ 𝔪)) (p := p) + simp only [Algebra.ofId_apply] at heq + exact heq ▸ hs.map (algebraMap R (R ⧸ 𝔪)) + · intro hRHS + obtain ⟨tbar, htbar⟩ := (hLG n (MvPolynomial.map π p)).mpr + (represents_unit_quotient_jacobson_of_forall p hRHS) + choose t ht using fun i ↦ hsurj (tbar i) + refine ⟨t, isUnit_of_isUnit_image_jacobson _ ?_⟩ + rw [aeval_map_quotient J p t, funext ht] + exact htbar diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/NonExamples.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/NonExamples.lean new file mode 100644 index 0000000000..5a73faf4b4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/NonExamples.lean @@ -0,0 +1,93 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import Mathlib.RingTheory.Polynomial.Content +public import Mathlib.Algebra.Polynomial.Div +public import Mathlib.Tactic.NormNum + +/-! +# Non-examples of LG rings + +`ℤ` and `R[t]` (`R` a nonzero commutative domain) are not LG-rings (`GPR Exercise 11.42`). These +are cheap, high-value negative results: they stop `IsLGRing` being silently assumed for the two +most familiar base rings, and mark exactly where the classification in this project stops +applying. + +## Main results + +* `not_isLGRing_int` : `ℤ` is not an LG-ring. +* `not_isLGRing_polynomial` : `R[t]` is not an LG-ring, for `R` a nonzero commutative domain. + +## Implementation notes + +Both proofs go through `exists_isUnit_of_isUnit_quotient` (`LGRing/Defs.lean`) instead of `GPR` +Exercise 11.42's `X² + c` argument: if `R` is LG, `Rˣ → (R ⧸ (b))ˣ` is surjective for *every* +`b : R`, so exhibiting one `b` and one unit of `R ⧸ (b)` with no lift in `Rˣ` refutes `IsLGRing R` +directly, with no case analysis on fields needed at the application site (all of that is bundled +once, inside `exists_isUnit_of_isUnit_quotient` itself). + +* `ℤ`, `b = 5`: `2` is a unit mod `5` (inverse `3`), but neither `1` nor `-1` — the only units of + `ℤ` (`Int.units_eq_one_or`) — is `≡ 2 mod 5`. +* `R[t]`, `b = t²`: `1 + t` is a unit mod `t²` (inverse `1 - t`, since `(1+t)(1-t) = 1 - t²`), but + the units of `R[t]` are exactly `C r` for `r ∈ Rˣ` (`Polynomial.isUnit_iff`, needs `R` a domain) + — degree `0` — while anything `≡ 1 + t mod t²` has `t`-coefficient `1 ≠ 0` + (`Polynomial.X_pow_dvd_iff`), hence is not of that form. + +`GPR`'s discrete-valuation extension of the `R[t]` argument (any ring with a discrete valuation +admitting an element of odd negative valuation is not LG) is not formalized here. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exercise Exc. 11.42. +-/ + +@[expose] public section + +open Polynomial + +/-- `ℤ` is not an LG-ring (`GPR Exercise 11.42`): `2` is a unit mod `5`, but no unit of `ℤ` is +`≡ 2 mod 5` (the units of `ℤ` are `±1`, and neither is `≡ 2 mod 5`). -/ +theorem not_isLGRing_int : ¬ IsLGRing ℤ := by + intro hLG + have hu2 : IsUnit (Ideal.Quotient.mk (Ideal.span {(5 : ℤ)}) 2) := by + apply IsUnit.of_mul_eq_one (Ideal.Quotient.mk (Ideal.span {(5 : ℤ)}) 3) + rw [← map_mul, ← map_one (Ideal.Quotient.mk (Ideal.span {(5 : ℤ)})), Ideal.Quotient.eq] + exact Ideal.mem_span_singleton.mpr (by norm_num) + obtain ⟨u', hu'⟩ := exists_isUnit_of_isUnit_quotient hLG 5 hu2.unit + simp only [IsUnit.unit_spec] at hu' + rcases Int.units_eq_one_or u' with rfl | rfl + · simp only [Units.val_one] at hu' + have hdvd : (5 : ℤ) ∣ (1 - 2) := Ideal.mem_span_singleton.mp (Ideal.Quotient.eq.mp hu') + norm_num at hdvd + · simp only [Units.val_neg, Units.val_one] at hu' + have hdvd : (5 : ℤ) ∣ (-1 - 2) := Ideal.mem_span_singleton.mp (Ideal.Quotient.eq.mp hu') + norm_num at hdvd + +/-- `R[t]` is not an LG-ring, for `R` a nonzero commutative domain (`GPR Exercise 11.42`(b)): +`1 + t` is a unit mod `t²`, but no unit of `R[t]` — all of which have +degree `0` — is `≡ 1 + t mod t²`, since that congruence class has `t`-coefficient `1 ≠ 0`. -/ +theorem not_isLGRing_polynomial (R : Type*) [CommRing R] [IsDomain R] : + ¬ IsLGRing (Polynomial R) := by + intro hLG + have hu2 : IsUnit (Ideal.Quotient.mk (Ideal.span {(X : R[X]) ^ 2}) (1 + X)) := by + apply IsUnit.of_mul_eq_one (Ideal.Quotient.mk (Ideal.span {(X : R[X]) ^ 2}) (1 - X)) + rw [← map_mul, ← map_one (Ideal.Quotient.mk (Ideal.span {(X : R[X]) ^ 2})), + Ideal.Quotient.eq] + have heq : (1 + X) * (1 - X) - 1 = -(X ^ 2 : R[X]) := by ring + rw [heq] + exact Submodule.neg_mem _ (Ideal.mem_span_singleton_self _) + obtain ⟨u', hu'⟩ := exists_isUnit_of_isUnit_quotient hLG (X ^ 2) hu2.unit + simp only [IsUnit.unit_spec] at hu' + obtain ⟨r, -, hr⟩ := Polynomial.isUnit_iff.mp u'.isUnit + rw [← hr] at hu' + have hdvd : (X : R[X]) ^ 2 ∣ (C r - (1 + X)) := + Ideal.mem_span_singleton.mp (Ideal.Quotient.eq.mp hu') + rw [Polynomial.X_pow_dvd_iff] at hdvd + have h1 := hdvd 1 (by norm_num) + simp only [coeff_sub, coeff_C, coeff_add, coeff_one, coeff_X_one] at h1 + norm_num at h1 diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Products.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Products.lean new file mode 100644 index 0000000000..5ac978ee0c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Products.lean @@ -0,0 +1,343 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ValueIdeal +public import Mathlib.Algebra.Group.Pi.Units +public import Mathlib.RingTheory.Ideal.Prod + +/-! +# Products of LG-rings + +The product half of `GPR 11.21` (`GN 2.1(a)`): `R₁ × R₂` is an LG-ring iff `R₁` and `R₂` both +are. The Jacobson-quotient half is in `LGRing/Jacobson.lean`; the two combine in +`LGRing/Semilocal.lean` to give `GPR 11.22`. + +A second, unrelated result closes the file: an **arbitrary** product of fields is an LG-ring. That +is not a corollary of the binary statement — induction on `isLGRing_prod_iff` reaches only finite +products — and its proof runs through the value-ideal criterion instead. + +## Main results + +* `MvPolynomial.RepresentsUnit.mapOfComm`, `MvPolynomial.RepresentsUnit.ofMapOfComm` : transport + of `RepresentsUnit` along a commuting square of ring homomorphisms (`aeval_map_comm`, in + `LGRing/Defs.lean`), forwards and (when the vertical map is an isomorphism) backwards. Every + transport below, and every one in `LGRing/Semilocal.lean`, is an instance of these. +* `Ideal.prodQuotientFstEquiv`, `Ideal.prodQuotientSndEquiv` : the residue fields of `R₁ × R₂` at + `Ideal.prod 𝔪 ⊤` and `Ideal.prod ⊤ 𝔪` are those of `R₁` at `𝔪` and of `R₂` at `𝔪`. +* `isLGRing_prod_iff` : **`GPR 11.21(ii)`**, `IsLGRing (R₁ × R₂) ↔ IsLGRing R₁ ∧ IsLGRing R₂`. +* `isLGRing_pi_of_forall_field`, `isLGRing_pi_field` : an arbitrary product `∏ᵢ Kᵢ` of fields — in + particular `F^I` for a field `F` and any index set `I` — is an LG-ring. + +## Proof idea + +The maximal ideals of `R₁ × R₂` are exactly `Ideal.prod 𝔪 ⊤` and `Ideal.prod ⊤ 𝔪` for `𝔪` maximal +in `R₁` resp. `R₂` — `Ideal.ideal_prod_prime` classifies the primes, and maximality transfers both +ways along `Ideal.comap_isMaximal_of_surjective` and `Ideal.map_fst_prod` — with the +corresponding residue fields those of the factors. + +For `⇐`, given `p` over `R₁ × R₂` representing a unit at every residue field, its images +`MvPolynomial.map (RingHom.fst _ _) p` and `map (RingHom.snd _ _) p` represent units at every +residue field of `R₁` resp. `R₂`; the LG hypotheses give witnesses `s₁, s₂`, and +`fun i ↦ (s₁ i, s₂ i)` is a witness over `R₁ × R₂`, because `IsUnit` in a product is +componentwise (`Prod.isUnit_iff`). + +For `⟹`, the point is that a polynomial over `R₁` must be *promoted* to one over `R₁ × R₂` that +carries no information about `R₂`. There is no ring homomorphism `R₁ → R₁ × R₂` to push it +through — `r ↦ (r, 1)` is not additive and `r ↦ (r, 0)` is not unital — but +`MvPolynomial.map (RingHom.fst _ _)` is surjective, so `p₁` has *some* preimage `q`, and the +orthogonal idempotents of `R₁ × R₂` assemble it into + + `p := C (1, 0) * q + C (0, 1)`, + +for which `map fst p = p₁` while `map snd p = 1`. Then `p` represents a unit at every residue +field of `R₁ × R₂`: on the `R₁` side because `p₁` does, and on the `R₂` side for free, the +constant `1` representing a unit anywhere. The LG hypothesis for `R₁ × R₂` yields a witness, whose +first components witness `p₁` over `R₁`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.21(ii). +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §2.1(a), + Example 2.2. +* [EG] Estes, Guralnick, *Module equivalences: local to global when primitive polynomials represent + units*, Journal of Algebra **77** (1982), 138–157. +-/ + +@[expose] public section + +universe u v + +/-! ### Transport of `RepresentsUnit` along a square of ring homomorphisms -/ + +/-- Pushing a `RepresentsUnit` witness forward along a commuting square. -/ +theorem MvPolynomial.RepresentsUnit.mapOfComm {R : Type*} [CommRing R] {R' : Type*} [CommRing R'] + (φ : R →+* R') {S : Type*} [CommRing S] [Algebra R S] {S' : Type*} [CommRing S'] + [Algebra R' S'] (ψ : S →+* S') + (hcomm : ψ.comp (algebraMap R S) = (algebraMap R' S').comp φ) + {n : ℕ} {p : MvPolynomial (Fin n) R} (h : p.RepresentsUnit S) : + (MvPolynomial.map φ p).RepresentsUnit S' := by + obtain ⟨s, hs⟩ := h + exact ⟨fun i ↦ ψ (s i), (MvPolynomial.aeval_map_comm φ ψ hcomm s p) ▸ hs.map ψ⟩ + +/-- Pulling a `RepresentsUnit` witness *back* along a commuting square whose vertical map is an +isomorphism. This is the direction that needs `ψ` invertible: the witness is transported by +`e.symm` and the resulting unit is recognised by applying `e`. -/ +theorem MvPolynomial.RepresentsUnit.ofMapOfComm {R : Type*} [CommRing R] {R' : Type*} [CommRing R'] + (φ : R →+* R') {S : Type*} [CommRing S] [Algebra R S] {S' : Type*} [CommRing S'] + [Algebra R' S'] (e : S ≃+* S') + (hcomm : e.toRingHom.comp (algebraMap R S) = (algebraMap R' S').comp φ) + {n : ℕ} {p : MvPolynomial (Fin n) R} (h : (MvPolynomial.map φ p).RepresentsUnit S') : + p.RepresentsUnit S := by + obtain ⟨t, ht⟩ := h + refine ⟨fun i ↦ e.symm (t i), ?_⟩ + have key := MvPolynomial.aeval_map_comm φ e.toRingHom hcomm (fun i ↦ e.symm (t i)) p + simp only [RingEquiv.toRingHom_eq_coe, RingHom.coe_coe, RingEquiv.apply_symm_apply] at key + rw [key] at ht + simpa using ht.map e.symm.toRingHom + +/-! ### Maximal ideals and residue fields of a product -/ + +namespace Ideal + +variable {R₁ : Type u} [CommRing R₁] {R₂ : Type u} [CommRing R₂] + +theorem comap_fst_eq_prod_top (𝔪 : Ideal R₁) : + Ideal.comap (RingHom.fst R₁ R₂) 𝔪 = Ideal.prod 𝔪 ⊤ := by + ext x; simp + +theorem comap_snd_eq_top_prod (𝔪 : Ideal R₂) : + Ideal.comap (RingHom.snd R₁ R₂) 𝔪 = Ideal.prod ⊤ 𝔪 := by + ext x; simp + +theorem prod_top_isMaximal (𝔪 : Ideal R₁) [𝔪.IsMaximal] : + (Ideal.prod 𝔪 (⊤ : Ideal R₂)).IsMaximal := by + rw [← comap_fst_eq_prod_top] + exact Ideal.comap_isMaximal_of_surjective _ Prod.fst_surjective + +theorem top_prod_isMaximal (𝔪 : Ideal R₂) [𝔪.IsMaximal] : + (Ideal.prod (⊤ : Ideal R₁) 𝔪).IsMaximal := by + rw [← comap_snd_eq_top_prod] + exact Ideal.comap_isMaximal_of_surjective _ Prod.snd_surjective + +theorem isMaximal_of_prod_top_isMaximal {𝔭 : Ideal R₁} + (h : (Ideal.prod 𝔭 (⊤ : Ideal R₂)).IsMaximal) : 𝔭.IsMaximal := by + have := h + have hle : RingHom.ker (RingHom.fst R₁ R₂) ≤ Ideal.prod 𝔭 (⊤ : Ideal R₂) := by + intro x hx + simp only [RingHom.mem_ker, RingHom.coe_fst] at hx + simp [Ideal.mem_prod, hx] + have hmax := Ideal.IsMaximal.map_of_surjective_of_ker_le + (f := RingHom.fst R₁ R₂) Prod.fst_surjective hle + rwa [Ideal.map_fst_prod] at hmax + +theorem isMaximal_of_top_prod_isMaximal {𝔭 : Ideal R₂} + (h : (Ideal.prod (⊤ : Ideal R₁) 𝔭).IsMaximal) : 𝔭.IsMaximal := by + have := h + have hle : RingHom.ker (RingHom.snd R₁ R₂) ≤ Ideal.prod (⊤ : Ideal R₁) 𝔭 := by + intro x hx + simp only [RingHom.mem_ker, RingHom.coe_snd] at hx + simp [Ideal.mem_prod, hx] + have hmax := Ideal.IsMaximal.map_of_surjective_of_ker_le + (f := RingHom.snd R₁ R₂) Prod.snd_surjective hle + rwa [Ideal.map_snd_prod] at hmax + +/-- The residue field of `R₁ × R₂` at `Ideal.prod 𝔪 ⊤` is the residue field of `R₁` at `𝔪`: +apply the first isomorphism theorem to `R₁ × R₂ → R₁ → R₁ ⧸ 𝔪`, whose kernel is `Ideal.prod 𝔪 ⊤` +by `Ideal.comap_fst_eq_prod_top`. -/ +noncomputable def prodQuotientFstEquiv (𝔪 : Ideal R₁) : + ((R₁ × R₂) ⧸ Ideal.prod 𝔪 (⊤ : Ideal R₂)) ≃+* R₁ ⧸ 𝔪 := + have hsurj : Function.Surjective ((Ideal.Quotient.mk 𝔪).comp (RingHom.fst R₁ R₂)) := + Ideal.Quotient.mk_surjective.comp Prod.fst_surjective + have hker : Ideal.prod 𝔪 (⊤ : Ideal R₂) = + RingHom.ker ((Ideal.Quotient.mk 𝔪).comp (RingHom.fst R₁ R₂)) := by + rw [← RingHom.comap_ker, Ideal.mk_ker, comap_fst_eq_prod_top] + (Ideal.quotEquivOfEq hker).trans (RingHom.quotientKerEquivOfSurjective hsurj) + +@[simp] +theorem prodQuotientFstEquiv_apply (𝔪 : Ideal R₁) (x : R₁ × R₂) : + prodQuotientFstEquiv (R₂ := R₂) 𝔪 + (Ideal.Quotient.mk (Ideal.prod 𝔪 (⊤ : Ideal R₂)) x) = + Ideal.Quotient.mk 𝔪 x.1 := by + simp only [prodQuotientFstEquiv, RingEquiv.trans_apply, Ideal.quotEquivOfEq_mk, + RingHom.quotientKerEquivOfSurjective_apply_mk, RingHom.comp_apply, RingHom.coe_fst] + +/-- The residue field of `R₁ × R₂` at `Ideal.prod ⊤ 𝔪` is the residue field of `R₂` at `𝔪`. -/ +noncomputable def prodQuotientSndEquiv (𝔪 : Ideal R₂) : + ((R₁ × R₂) ⧸ Ideal.prod (⊤ : Ideal R₁) 𝔪) ≃+* R₂ ⧸ 𝔪 := + have hsurj : Function.Surjective ((Ideal.Quotient.mk 𝔪).comp (RingHom.snd R₁ R₂)) := + Ideal.Quotient.mk_surjective.comp Prod.snd_surjective + have hker : Ideal.prod (⊤ : Ideal R₁) 𝔪 = + RingHom.ker ((Ideal.Quotient.mk 𝔪).comp (RingHom.snd R₁ R₂)) := by + rw [← RingHom.comap_ker, Ideal.mk_ker, comap_snd_eq_top_prod] + (Ideal.quotEquivOfEq hker).trans (RingHom.quotientKerEquivOfSurjective hsurj) + +@[simp] +theorem prodQuotientSndEquiv_apply (𝔪 : Ideal R₂) (x : R₁ × R₂) : + prodQuotientSndEquiv (R₁ := R₁) 𝔪 (Ideal.Quotient.mk (Ideal.prod (⊤ : Ideal R₁) 𝔪) x) = + Ideal.Quotient.mk 𝔪 x.2 := by + simp only [prodQuotientSndEquiv, RingEquiv.trans_apply, Ideal.quotEquivOfEq_mk, + RingHom.quotientKerEquivOfSurjective_apply_mk, RingHom.comp_apply, RingHom.coe_snd] + +theorem prodQuotientFstEquiv_comm (𝔪 : Ideal R₁) : + (prodQuotientFstEquiv (R₂ := R₂) 𝔪).toRingHom.comp + (algebraMap (R₁ × R₂) ((R₁ × R₂) ⧸ Ideal.prod 𝔪 (⊤ : Ideal R₂))) = + (algebraMap R₁ (R₁ ⧸ 𝔪)).comp (RingHom.fst R₁ R₂) := + RingHom.ext fun x ↦ by simp [Ideal.Quotient.algebraMap_eq] + +theorem prodQuotientSndEquiv_comm (𝔪 : Ideal R₂) : + (prodQuotientSndEquiv (R₁ := R₁) 𝔪).toRingHom.comp + (algebraMap (R₁ × R₂) ((R₁ × R₂) ⧸ Ideal.prod (⊤ : Ideal R₁) 𝔪)) = + (algebraMap R₂ (R₂ ⧸ 𝔪)).comp (RingHom.snd R₁ R₂) := + RingHom.ext fun x ↦ by simp [Ideal.Quotient.algebraMap_eq] + +end Ideal + +/-! ### `GPR 11.21(ii)` -/ + +section Main + +variable {R₁ : Type u} [CommRing R₁] {R₂ : Type u} [CommRing R₂] + +/-- **`GPR 11.21(ii)`**: a binary product of rings is an LG-ring iff both factors are. -/ +theorem isLGRing_prod_iff : IsLGRing (R₁ × R₂) ↔ IsLGRing R₁ ∧ IsLGRing R₂ := by + constructor + · intro hLG + refine ⟨fun n p₁ ↦ ⟨fun ⟨s, hs⟩ 𝔪 _ ↦ ?_, fun hRHS ↦ ?_⟩, + fun n p₂ ↦ ⟨fun ⟨s, hs⟩ 𝔪 _ ↦ ?_, fun hRHS ↦ ?_⟩⟩ + · exact ⟨fun i ↦ algebraMap R₁ (R₁ ⧸ 𝔪) (s i), + (MvPolynomial.comp_aeval_apply (f := s) (φ := Algebra.ofId R₁ (R₁ ⧸ 𝔪)) (p := p₁)) ▸ + hs.map (algebraMap R₁ (R₁ ⧸ 𝔪))⟩ + · -- Promote `p₁` to a polynomial over `R₁ × R₂` that is the constant `1` on the `R₂` side. + obtain ⟨q, hq⟩ := MvPolynomial.map_surjective (RingHom.fst R₁ R₂) Prod.fst_surjective p₁ + set p : MvPolynomial (Fin n) (R₁ × R₂) := + MvPolynomial.C ((1 : R₁), (0 : R₂)) * q + MvPolynomial.C ((0 : R₁), (1 : R₂)) with hp + have hfst : MvPolynomial.map (RingHom.fst R₁ R₂) p = p₁ := by simp [hp, hq] + have hsnd : MvPolynomial.map (RingHom.snd R₁ R₂) p = 1 := by simp [hp] + have hall : ∀ (M : Ideal (R₁ × R₂)) [M.IsMaximal], p.RepresentsUnit ((R₁ × R₂) ⧸ M) := by + intro M hM + rcases (Ideal.ideal_prod_prime M).mp hM.isPrime with ⟨𝔭, _, rfl⟩ | ⟨𝔭, _, rfl⟩ + · have : 𝔭.IsMaximal := Ideal.isMaximal_of_prod_top_isMaximal hM + exact MvPolynomial.RepresentsUnit.ofMapOfComm (RingHom.fst R₁ R₂) + (Ideal.prodQuotientFstEquiv (R₂ := R₂) 𝔭) (Ideal.prodQuotientFstEquiv_comm 𝔭) + (hfst ▸ hRHS 𝔭) + · have : 𝔭.IsMaximal := Ideal.isMaximal_of_top_prod_isMaximal hM + refine MvPolynomial.RepresentsUnit.ofMapOfComm (RingHom.snd R₁ R₂) + (Ideal.prodQuotientSndEquiv (R₁ := R₁) 𝔭) (Ideal.prodQuotientSndEquiv_comm 𝔭) ?_ + rw [hsnd] + exact ⟨fun _ ↦ 0, by simp⟩ + obtain ⟨s, hs⟩ := (hLG n p).mpr hall + exact hfst ▸ MvPolynomial.RepresentsUnit.mapOfComm (S := R₁ × R₂) (S' := R₁) + (RingHom.fst R₁ R₂) (RingHom.fst R₁ R₂) (by ext x; simp) ⟨s, hs⟩ + · exact ⟨fun i ↦ algebraMap R₂ (R₂ ⧸ 𝔪) (s i), + (MvPolynomial.comp_aeval_apply (f := s) (φ := Algebra.ofId R₂ (R₂ ⧸ 𝔪)) (p := p₂)) ▸ + hs.map (algebraMap R₂ (R₂ ⧸ 𝔪))⟩ + · obtain ⟨q, hq⟩ := MvPolynomial.map_surjective (RingHom.snd R₁ R₂) Prod.snd_surjective p₂ + set p : MvPolynomial (Fin n) (R₁ × R₂) := + MvPolynomial.C ((0 : R₁), (1 : R₂)) * q + MvPolynomial.C ((1 : R₁), (0 : R₂)) with hp + have hsnd : MvPolynomial.map (RingHom.snd R₁ R₂) p = p₂ := by simp [hp, hq] + have hfst : MvPolynomial.map (RingHom.fst R₁ R₂) p = 1 := by simp [hp] + have hall : ∀ (M : Ideal (R₁ × R₂)) [M.IsMaximal], p.RepresentsUnit ((R₁ × R₂) ⧸ M) := by + intro M hM + rcases (Ideal.ideal_prod_prime M).mp hM.isPrime with ⟨𝔭, _, rfl⟩ | ⟨𝔭, _, rfl⟩ + · have : 𝔭.IsMaximal := Ideal.isMaximal_of_prod_top_isMaximal hM + refine MvPolynomial.RepresentsUnit.ofMapOfComm (RingHom.fst R₁ R₂) + (Ideal.prodQuotientFstEquiv (R₂ := R₂) 𝔭) (Ideal.prodQuotientFstEquiv_comm 𝔭) ?_ + rw [hfst] + exact ⟨fun _ ↦ 0, by simp⟩ + · have : 𝔭.IsMaximal := Ideal.isMaximal_of_top_prod_isMaximal hM + exact MvPolynomial.RepresentsUnit.ofMapOfComm (RingHom.snd R₁ R₂) + (Ideal.prodQuotientSndEquiv (R₁ := R₁) 𝔭) (Ideal.prodQuotientSndEquiv_comm 𝔭) + (hsnd ▸ hRHS 𝔭) + obtain ⟨s, hs⟩ := (hLG n p).mpr hall + exact hsnd ▸ MvPolynomial.RepresentsUnit.mapOfComm (S := R₁ × R₂) (S' := R₂) + (RingHom.snd R₁ R₂) (RingHom.snd R₁ R₂) (by ext x; simp) ⟨s, hs⟩ + · rintro ⟨h₁, h₂⟩ n p + refine ⟨fun ⟨s, hs⟩ M _ ↦ ?_, fun hRHS ↦ ?_⟩ + · exact ⟨fun i ↦ algebraMap (R₁ × R₂) ((R₁ × R₂) ⧸ M) (s i), + (MvPolynomial.comp_aeval_apply (f := s) + (φ := Algebra.ofId (R₁ × R₂) ((R₁ × R₂) ⧸ M)) (p := p)) ▸ + hs.map (algebraMap (R₁ × R₂) ((R₁ × R₂) ⧸ M))⟩ + · obtain ⟨s₁, hs₁⟩ : (MvPolynomial.map (RingHom.fst R₁ R₂) p).RepresentsUnit R₁ := by + refine (h₁ n _).mpr fun 𝔪 _ ↦ ?_ + have := Ideal.prod_top_isMaximal (R₂ := R₂) 𝔪 + exact MvPolynomial.RepresentsUnit.mapOfComm (RingHom.fst R₁ R₂) + (Ideal.prodQuotientFstEquiv (R₂ := R₂) 𝔪).toRingHom + (Ideal.prodQuotientFstEquiv_comm 𝔪) (hRHS _) + obtain ⟨s₂, hs₂⟩ : (MvPolynomial.map (RingHom.snd R₁ R₂) p).RepresentsUnit R₂ := by + refine (h₂ n _).mpr fun 𝔪 _ ↦ ?_ + have := Ideal.top_prod_isMaximal (R₁ := R₁) 𝔪 + exact MvPolynomial.RepresentsUnit.mapOfComm (RingHom.snd R₁ R₂) + (Ideal.prodQuotientSndEquiv (R₁ := R₁) 𝔪).toRingHom + (Ideal.prodQuotientSndEquiv_comm 𝔪) (hRHS _) + refine ⟨fun i ↦ (s₁ i, s₂ i), Prod.isUnit_iff.mpr ⟨?_, ?_⟩⟩ + · have hcomm : (RingHom.fst R₁ R₂).comp (algebraMap (R₁ × R₂) (R₁ × R₂)) + = (algebraMap R₁ R₁).comp (RingHom.fst R₁ R₂) := by ext x; simp + have key := MvPolynomial.aeval_map_comm (RingHom.fst R₁ R₂) (RingHom.fst R₁ R₂) hcomm + (fun i ↦ ((s₁ i, s₂ i) : R₁ × R₂)) p + exact cast (congrArg IsUnit key) hs₁ + · have hcomm : (RingHom.snd R₁ R₂).comp (algebraMap (R₁ × R₂) (R₁ × R₂)) + = (algebraMap R₂ R₂).comp (RingHom.snd R₁ R₂) := by ext x; simp + have key := MvPolynomial.aeval_map_comm (RingHom.snd R₁ R₂) (RingHom.snd R₁ R₂) hcomm + (fun i ↦ ((s₁ i, s₂ i) : R₁ × R₂)) p + exact cast (congrArg IsUnit key) hs₂ + +end Main + +/-! ### Arbitrary products of fields -/ + +section PiFields + +variable {ι : Type v} (K : ι → Type u) [∀ i, Field (K i)] + +/-- **An arbitrary product of fields is an LG-ring** (`GN 2.2`, from `EG`). + +By the value-ideal criterion it suffices to turn an equation `1 = Σⱼ cⱼ · p(tⱼ)` — finitely many +points `tⱼ` of `(∏ᵢ Kᵢ)ⁿ` whose values at `p` generate the unit ideal — into a single point where +`p` is a unit. Read that equation off at one index `i`: the `i`-th components sum to `1 ≠ 0` in the +field `Kᵢ`, so *some* `j` has `p(tⱼ)ᵢ ≠ 0`. Choosing such a `j = j(i)` for every `i` and splicing, +`s x i := t (j i) x i`, gives a point whose value has `p(s)ᵢ = p(t (j i))ᵢ ≠ 0` in every +coordinate — and a unit in a product is exactly a coordinatewise unit. + +A product of fields is von Neumann regular, so this also follows from +`IsVonNeumannRegular.isLGRing` in `LGRing/ZeroDimensional.lean`; the direct argument is kept +because it is elementary — no idempotents, no value ideal beyond its unwinding — and because it is +what makes the shape of the general statement visible. + +The splicing step is legitimate because evaluation commutes with each projection +`∏ᵢ Kᵢ → Kᵢ` (`MvPolynomial.aeval_map_comm`): the `i`-th coordinate of a value depends on the +`i`-th coordinates of the point and on nothing else. This is the whole reason the argument needs +the factors to be *fields* only coordinatewise, with no compatibility between them. -/ +theorem isLGRing_pi_of_forall_field : IsLGRing (∀ i, K i) := by + rw [isLGRing_iff_forall_valueIdeal_eq_top] + intro n p htop + -- Evaluation in the `i`-th coordinate only sees the `i`-th coordinate of the point. + have key : ∀ (u : Fin n → ∀ i, K i) (i : ι), + MvPolynomial.aeval (fun x ↦ u x i) (MvPolynomial.map (Pi.evalRingHom K i) p) + = MvPolynomial.aeval u p i := + fun u i ↦ MvPolynomial.aeval_map_comm (Pi.evalRingHom K i) (Pi.evalRingHom K i) + (by ext x; simp) u p + obtain ⟨k, c, t, hsum⟩ := MvPolynomial.exists_sum_mul_aeval_eq_one htop + have hne : ∀ i : ι, ∃ j : Fin k, MvPolynomial.aeval (t j) p i ≠ 0 := by + intro i + have h1 : ∑ j : Fin k, c j i * MvPolynomial.aeval (t j) p i = (1 : K i) := by + simpa using congrFun hsum i + have h2 : ∑ j : Fin k, c j i * MvPolynomial.aeval (t j) p i ≠ 0 := by + rw [h1]; exact one_ne_zero + obtain ⟨j, -, hj⟩ := Finset.exists_ne_zero_of_sum_ne_zero h2 + exact ⟨j, fun h ↦ hj (by rw [h, mul_zero])⟩ + choose j hj using hne + refine ⟨fun x i ↦ t (j i) x i, Pi.isUnit_iff.mpr fun i ↦ isUnit_iff_ne_zero.mpr ?_⟩ + rw [← key _ i, key (t (j i)) i] + exact hj i + +/-- **`F^I` is an LG-ring** for a field `F` and an arbitrary index set `I` (`GN 2.2`, from `EG`); +the constant-family case of `isLGRing_pi_of_forall_field`. -/ +theorem isLGRing_pi_field (F : Type u) [Field F] (I : Type v) : IsLGRing (I → F) := + isLGRing_pi_of_forall_field fun _ ↦ F + +end PiFields diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Semilocal.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Semilocal.lean new file mode 100644 index 0000000000..955b5d099b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Semilocal.lean @@ -0,0 +1,154 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Examples +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Jacobson +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Products +public import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic + +/-! +# Semilocal rings are LG-rings + +`GPR 11.22`: a commutative ring with only finitely many maximal ideals is an LG-ring. This is the +workhorse instance for the rest of the development — local rings, Artinian rings and fields are +all semilocal. + +Semilocality is expressed in mathlib's way, as `[Finite (MaximalSpectrum R)]`. + +## Main results + +* `IsLGRing.of_ringEquiv` : the LG property transfers along a ring isomorphism. +* `IsLGRing.quotient_span_one_sub_of_isIdempotentElem` : an idempotent factor of an LG ring is + LG. +* `isLGRing_of_finite_maximalSpectrum` : **`GPR 11.22`**, semilocal implies LG. +* `isLGRing_of_isLocalRing` : every commutative local ring is LG. + +## Proof idea + +Assemble the two halves of `GPR 11.21`. Writing `𝔪₁, …, 𝔪ₖ` for the maximal ideals, +`Jac(R) = 𝔪₁ ⊓ ⋯ ⊓ 𝔪ₖ` is a *finite* intersection, so the Chinese Remainder Theorem +(`Ideal.quotientInfEquivQuotientProd`, applied `k` times) identifies `R ⧸ Jac(R)` with a finite +product of the residue fields `R ⧸ 𝔪ᵢ`. Fields are LG (`isLGRing_of_field`), binary products of +LG-rings are LG (`isLGRing_prod_iff`), so `R ⧸ Jac(R)` is LG, and `R` itself is LG by +`isLGRing_iff_isLGRing_quotient_jacobson`. + +The induction is on a `Finset` of maximal ideals rather than on a cardinality, which keeps +everything inside `R`: `isLGRing_quotient_biInf` proves `R ⧸ (⨅ 𝔪 ∈ s, 𝔪)` is LG for every finite +set `s` of maximal ideals, with the empty set giving the zero ring +(`isLGRing_of_subsingleton`, in `LGRing/Examples.lean`). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.22. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §2.1. +-/ + +@[expose] public section + +universe u + +/-- The LG property transfers along a ring isomorphism: maximal ideals correspond +(`Ideal.map_isMaximal_of_equiv`), the residue fields correspond (`Ideal.quotientEquiv`), and +`MvPolynomial.map` transports polynomials both ways. -/ +theorem IsLGRing.of_ringEquiv {R : Type u} [CommRing R] {S : Type u} [CommRing S] (e : R ≃+* S) + (hR : IsLGRing R) : IsLGRing S := by + intro n q + obtain ⟨p, rfl⟩ := MvPolynomial.map_surjective e.toRingHom e.surjective q + refine ⟨fun ⟨t, ht⟩ 𝔐 _ ↦ ?_, fun hRHS ↦ ?_⟩ + · exact ⟨fun i ↦ algebraMap S (S ⧸ 𝔐) (t i), + (MvPolynomial.comp_aeval_apply (f := t) (φ := Algebra.ofId S (S ⧸ 𝔐)) + (p := MvPolynomial.map e.toRingHom p)) ▸ ht.map (algebraMap S (S ⧸ 𝔐))⟩ + · have hp : p.RepresentsUnit R := by + refine (hR n p).mpr fun 𝔪 _ ↦ ?_ + have : (Ideal.map (e : R →+* S) 𝔪).IsMaximal := Ideal.map_isMaximal_of_equiv e + refine MvPolynomial.RepresentsUnit.ofMapOfComm e.toRingHom + (Ideal.quotientEquiv 𝔪 (Ideal.map (e : R →+* S) 𝔪) e rfl) ?_ (hRHS _) + exact RingHom.ext fun x ↦ by simp [Ideal.Quotient.algebraMap_eq] + obtain ⟨s, hs⟩ := hp + exact MvPolynomial.RepresentsUnit.mapOfComm e.toRingHom e.toRingHom + (by ext x; simp) ⟨s, hs⟩ + +/-- An idempotent factor of an LG ring is LG. + +The complementary ideals `(1 - e)` and `(e)` have zero intersection, so the Chinese remainder +theorem identifies the original ring with the product of the two quotient rings. The assertion +then follows from `GPR 11.21(ii)`. -/ +theorem IsLGRing.quotient_span_one_sub_of_isIdempotentElem {R : Type u} [CommRing R] + (hLG : IsLGRing R) {e : R} (he : IsIdempotentElem e) : + IsLGRing (R ⧸ Ideal.span {1 - e}) := by + let I : Ideal R := Ideal.span {1 - e} + let J : Ideal R := Ideal.span {e} + have hcop : IsCoprime I J := by + change IsCoprime (Ideal.span {1 - e}) (Ideal.span {e}) + rw [Ideal.isCoprime_span_singleton_iff] + exact ⟨1, 1, by ring⟩ + have hinf : I ⊓ J = ⊥ := by + calc + I ⊓ J = I * J := (Ideal.mul_eq_inf_of_isCoprime hcop).symm + _ = Ideal.span {(1 - e) * e} := by + simp only [I, J, Ideal.span_singleton_mul_span_singleton] + _ = ⊥ := by simp only [sub_mul, one_mul, he.eq, sub_self, Set.singleton_zero, + Ideal.span_zero] + let eprod : R ≃+* (R ⧸ I) × (R ⧸ J) := + (RingEquiv.quotientBot R).symm |>.trans + ((Ideal.quotEquivOfEq hinf.symm).trans + (Ideal.quotientInfEquivQuotientProd I J hcop)) + have hprod : IsLGRing ((R ⧸ I) × (R ⧸ J)) := + IsLGRing.of_ringEquiv eprod hLG + exact (isLGRing_prod_iff.mp hprod).1 + +/-- For any finite set `s` of maximal ideals of `R`, the quotient `R ⧸ (⨅ 𝔪 ∈ s, 𝔪)` is an +LG-ring. Induction on `s`: the empty set gives the zero ring, and the induction step splits off +one maximal ideal by the Chinese Remainder Theorem and applies `isLGRing_prod_iff`. -/ +theorem isLGRing_quotient_biInf {R : Type u} [CommRing R] (s : Finset (Ideal R)) + (hs : ∀ 𝔪 ∈ s, 𝔪.IsMaximal) : IsLGRing (R ⧸ (⨅ 𝔪 ∈ s, 𝔪)) := by + classical + induction s using Finset.induction with + | empty => + have htop : (⨅ 𝔪 ∈ (∅ : Finset (Ideal R)), 𝔪) = ⊤ := by simp + rw [htop] + have : Subsingleton (R ⧸ (⊤ : Ideal R)) := Ideal.Quotient.subsingleton_iff.mpr rfl + exact isLGRing_of_subsingleton _ + | insert 𝔪 t h𝔪t ih => + have h𝔪 : 𝔪.IsMaximal := hs 𝔪 (Finset.mem_insert_self _ _) + have ht : ∀ 𝔫 ∈ t, 𝔫.IsMaximal := + fun 𝔫 h𝔫 ↦ hs 𝔫 (Finset.mem_insert_of_mem h𝔫) + have hcop : IsCoprime 𝔪 (⨅ 𝔫 ∈ t, 𝔫) := + Ideal.isCoprime_biInf fun 𝔫 h𝔫 ↦ + have := ht 𝔫 h𝔫 + Ideal.isCoprime_of_isMaximal (by rintro rfl; exact h𝔪t h𝔫) + have hinsert : (⨅ 𝔫 ∈ insert 𝔪 t, 𝔫) = 𝔪 ⊓ (⨅ 𝔫 ∈ t, 𝔫) := by + rw [Finset.iInf_insert] + rw [hinsert] + refine + IsLGRing.of_ringEquiv + (Ideal.quotientInfEquivQuotientProd 𝔪 (⨅ 𝔫 ∈ t, 𝔫) hcop).symm ?_ + refine isLGRing_prod_iff.mpr ⟨?_, ih ht⟩ + let : Field (R ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + exact isLGRing_of_field _ + +/-- **`GPR 11.22`**: every semilocal ring is an LG-ring. Semilocality is mathlib's +`[Finite (MaximalSpectrum R)]`: `R` has only finitely many maximal ideals. -/ +theorem isLGRing_of_finite_maximalSpectrum (R : Type u) [CommRing R] + [Finite (MaximalSpectrum R)] : IsLGRing R := by + classical + have h : {𝔪 : Ideal R | 𝔪.IsMaximal}.Finite := + (Set.finite_range (MaximalSpectrum.asIdeal : MaximalSpectrum R → Ideal R)).subset + fun 𝔪 h𝔪 ↦ ⟨⟨𝔪, h𝔪⟩, rfl⟩ + rw [isLGRing_iff_isLGRing_quotient_jacobson] + have hjac : Ring.jacobson R = ⨅ 𝔪 ∈ h.toFinset, 𝔪 := by + rw [Ring.jacobson_eq_sInf_isMaximal] + refine le_antisymm (le_iInf fun 𝔪 ↦ le_iInf fun h𝔪 ↦ sInf_le (h.mem_toFinset.mp h𝔪)) + (le_sInf fun 𝔪 h𝔪 ↦ iInf_le_of_le 𝔪 (iInf_le_of_le (h.mem_toFinset.mpr h𝔪) le_rfl)) + rw [hjac] + exact isLGRing_quotient_biInf _ fun 𝔪 h𝔪 ↦ (h.mem_toFinset.mp h𝔪) + +/-- Every commutative local ring is an LG ring, since it has a unique maximal ideal and hence is +semilocal. -/ +theorem isLGRing_of_isLocalRing (R : Type u) [CommRing R] [IsLocalRing R] : IsLGRing R := + isLGRing_of_finite_maximalSpectrum R diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/Unimodular.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/Unimodular.lean new file mode 100644 index 0000000000..a88821a67b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/Unimodular.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import Mathlib.LinearAlgebra.StdBasis +public import Mathlib.LinearAlgebra.TensorProduct.Tower +public import Mathlib.RingTheory.Finiteness.Projective +public import Mathlib.RingTheory.Ideal.Quotient.Defs + +/-! +# Faithfully projective modules over an LG-ring contain a unimodular element (`GN 2.6(a)`) + +Over an LG-ring `R`, a finitely generated projective module `M` that is nonzero at every residue +field contains a unimodular element. + +## Main definitions + +* `MvPolynomial.bilinearPairing E` : for a square array `E : Fin n → Fin n → R`, the polynomial + `∑ᵢ ∑ⱼ C (E i j) * X (castAdd n j) * X (natAdd n i)` in `n + n` variables. The first block of + variables is a column vector `t`, the second a row vector `c`, and the polynomial is the + pairing `cᵀ E t`. + +## Main results + +* `IsLGRing.exists_isUnimodular` : **`GN 2.6(a)`**. If `R` is an LG-ring and `M` is finitely + generated projective with `(R ⧸ 𝔪) ⊗[R] M ≠ 0` for every maximal `𝔪`, then `M` contains a + unimodular element. + +## Proof idea + +Write `M` as a retract of a finite free module: `π : Rⁿ ↠ M` and `σ : M ↪ Rⁿ` with `π ∘ σ = id` +(`Module.Finite.exists_comp_eq_id_of_projective`). Put `e := σ ∘ π`, an idempotent endomorphism of +`Rⁿ`, and let `E i j := e (Pi.single j 1) i` be its matrix in the standard basis. + +For `t c : Fin n → R` set `m := π t` and `l := ∑ᵢ cᵢ · (proj i ∘ σ) : M →ₗ[R] R`. Then + + `l m = ∑ᵢ cᵢ · (e t)ᵢ = ∑ᵢ ∑ⱼ Eᵢⱼ tⱼ cᵢ`, + +which is exactly `bilinearPairing E` evaluated at the point `(t, c)` — and by `GPR 9.13` +(`Module.isUnimodular_of_apply_eq_one`), a value of `1` produces a unimodular element. +So it suffices to know that `bilinearPairing E` represents a unit over `R`, and by the LG axiom +that reduces to representing a unit over every residue field `k = R ⧸ 𝔪`. + +Over `k` the polynomial represents a unit as soon as some entry of `E` survives in `k`: take `t` +and `c` to be the corresponding standard basis vectors, and the double sum collapses to that +entry. And if *every* entry died in `k`, then `e ⊗ k = 0`; since `π ⊗ k` and `σ ⊗ k` still +compose to the identity of `k ⊗[R] M`, every `x` there satisfies +`σₖ x = σₖ (πₖ (σₖ x)) = eₖ (σₖ x) = 0`, hence `x = πₖ (σₖ x) = 0`, contradicting the hypothesis +that `k ⊗[R] M` is nonzero. + +## Implementation notes + +The hypothesis is stated as `Nontrivial ((R ⧸ 𝔪) ⊗[R] M)` for every maximal `𝔪` rather than as +`Module.HasFullSupport` (`QuadraticForm/Representation.lean`), for two reasons: it is exactly what +the proof consumes — the LG axiom quantifies over residue fields — and it keeps this file below +`QuadraticForm/` in the import order. `Module.HasFullSupport.nontrivial_quotient_tensor` supplies +it, and `Module.exists_isUnimodular_of_hasFullSupport` in `QuadraticForm/Representation.lean` +packages the combination. + +Following the implementation notes of `LGRing/Defs.lean`, the residue field is handled through the +`Prop`-valued `IsField (R ⧸ 𝔪)` rather than the bundled `Field` instance from +`Ideal.Quotient.field`, which avoids the instance diamond entirely. + +`GN` proves 2.6(a) by scheme theory, applying its Proposition 2.4 to the punctured affine space +`W(M) ∖ Spec(R)`, a quasi-compact open subscheme; that is a stronger form of the LG axiom than the +one taken as the definition here. The argument above is elementary and uses only the single- +polynomial axiom, at the cost of choosing a presentation of `M`. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Lemma 2.6(a). +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.13, 11.24. +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +variable {R : Type u} [CommRing R] {n : ℕ} + +/-- The **pairing polynomial** of a square array `E`, in `n + n` variables: reading the first +block of variables as a column vector `t` and the second as a row vector `c`, this is `cᵀ E t`. -/ +noncomputable def MvPolynomial.bilinearPairing (E : Fin n → Fin n → R) : + MvPolynomial (Fin (n + n)) R := + ∑ i, ∑ j, MvPolynomial.C (E i j) * MvPolynomial.X (Fin.castAdd n j) * + MvPolynomial.X (Fin.natAdd n i) + +/-- Evaluating `bilinearPairing E` over an `R`-algebra `S` gives the double sum `∑ᵢ ∑ⱼ Eᵢⱼ tⱼ cᵢ`, +where `t` and `c` are the two blocks of the evaluation point. -/ +theorem MvPolynomial.aeval_bilinearPairing {S : Type v} [CommRing S] [Algebra R S] + (E : Fin n → Fin n → R) (s : Fin (n + n) → S) : + MvPolynomial.aeval s (MvPolynomial.bilinearPairing E) = + ∑ i, ∑ j, algebraMap R S (E i j) * s (Fin.castAdd n j) * s (Fin.natAdd n i) := by + simp only [bilinearPairing, map_sum, map_mul, aeval_C, aeval_X] + +/-- At the pair of standard basis vectors indexed by `j₀` and `i₀`, the double sum of +`aeval_bilinearPairing` collapses to the single entry `Eᵢ₀ⱼ₀`. -/ +private theorem sum_sum_mul_single_mul_single {S : Type v} [CommRing S] (a : Fin n → Fin n → S) + (i₀ j₀ : Fin n) : + ∑ i, ∑ j, a i j * (Pi.single j₀ 1 : Fin n → S) j * (Pi.single i₀ 1 : Fin n → S) i = + a i₀ j₀ := by + classical + rw [Finset.sum_eq_single i₀ (fun i _ hi ↦ Finset.sum_eq_zero fun j _ ↦ by + simp [Pi.single_eq_of_ne hi]) (fun h ↦ absurd (Finset.mem_univ i₀) h)] + rw [Finset.sum_eq_single j₀ (fun j _ hj ↦ by simp [Pi.single_eq_of_ne hj]) + (fun h ↦ absurd (Finset.mem_univ j₀) h)] + simp + +/-- Every vector of `Fin n → R` is the sum of its coordinates against the standard basis. -/ +private theorem sum_smul_single_eq_self (t : Fin n → R) : + ∑ j, t j • (Pi.single j 1 : Fin n → R) = t := by + classical + simpa using (Pi.basisFun R (Fin n)).sum_repr t + +variable {M : Type v} [AddCommGroup M] [Module R M] + +/-- **`GN 2.6(a)`.** Over an LG-ring, a finitely generated projective module that is nonzero at +every residue field contains a unimodular element. + +See the module docstring for the construction; `Module.HasFullSupport.nontrivial_quotient_tensor` +supplies the hypothesis from the more geometric formulation. -/ +theorem IsLGRing.exists_isUnimodular [Module.Finite R M] [Module.Projective R M] + (hLG : IsLGRing R) + (hM : ∀ (𝔪 : Ideal R), 𝔪.IsMaximal → Nontrivial ((R ⧸ 𝔪) ⊗[R] M)) : + ∃ m : M, Module.IsUnimodular R m := by + classical + obtain ⟨n, π, σ, -, -, hσ⟩ := Module.Finite.exists_comp_eq_id_of_projective R M + set e : (Fin n → R) →ₗ[R] (Fin n → R) := σ ∘ₗ π with he + set E : Fin n → Fin n → R := fun i j ↦ e (Pi.single j 1) i with hE + -- The matrix `E` computes `e` on every vector. + have hcoord : ∀ (t : Fin n → R) (i : Fin n), e t i = ∑ j, E i j * t j := by + intro t i + conv_lhs => rw [← sum_smul_single_eq_self t] + rw [map_sum] + simp only [Finset.sum_apply, map_smul, Pi.smul_apply, smul_eq_mul, hE] + exact Finset.sum_congr rfl fun j _ ↦ mul_comm _ _ + -- The pairing polynomial of `E` represents a unit over every residue field, hence over `R`. + have hrep : (MvPolynomial.bilinearPairing E).RepresentsUnit R := by + refine (hLG (n + n) _).mpr fun 𝔪 hmax ↦ ?_ + have hfield : IsField (R ⧸ 𝔪) := + (Ideal.Quotient.maximal_ideal_iff_isField_quotient 𝔪).mp hmax + -- Some entry of `E` survives in the residue field: otherwise `e` dies there, and with it + -- the retract `(R ⧸ 𝔪) ⊗[R] M`. + have hne : ∃ i j, algebraMap R (R ⧸ 𝔪) (E i j) ≠ 0 := by + by_contra hcon + simp only [not_exists, not_not] at hcon + have hek : + ∀ y : (R ⧸ 𝔪) ⊗[R] (Fin n → R), LinearMap.baseChange (R ⧸ 𝔪) e y = 0 := by + intro y + induction y using TensorProduct.inductionOn with + | tmul a t => + rw [LinearMap.baseChange_tmul] + conv_lhs => rw [← sum_smul_single_eq_self (e t)] + rw [TensorProduct.tmul_sum] + refine Finset.sum_eq_zero fun i _ ↦ ?_ + rw [TensorProduct.tmul_smul, TensorProduct.smul_tmul'] + have hzero : (e t i) • a = 0 := by + rw [Algebra.smul_def, hcoord t i, map_sum] + simp only [map_mul, hcon, zero_mul, Finset.sum_const_zero, zero_mul] + rw [hzero, TensorProduct.zero_tmul] + | add x y hx hy => rw [map_add, hx, hy, add_zero] + have hid : ∀ x : (R ⧸ 𝔪) ⊗[R] M, + LinearMap.baseChange (R ⧸ 𝔪) π (LinearMap.baseChange (R ⧸ 𝔪) σ x) = x := by + have h : LinearMap.baseChange (R ⧸ 𝔪) π ∘ₗ LinearMap.baseChange (R ⧸ 𝔪) σ = + LinearMap.id := by + rw [← LinearMap.baseChange_comp, hσ, LinearMap.baseChange_id] + exact fun x ↦ DFunLike.congr_fun h x + have hzero : ∀ x : (R ⧸ 𝔪) ⊗[R] M, x = 0 := by + intro x + have hσx : LinearMap.baseChange (R ⧸ 𝔪) σ x = 0 := by + conv_lhs => rw [← hid x] + have := hek (LinearMap.baseChange (R ⧸ 𝔪) σ x) + rwa [he, LinearMap.baseChange_comp] at this + rw [← hid x, hσx, map_zero] + obtain ⟨x, y, hxy⟩ := (hM 𝔪 hmax).exists_pair_ne + exact hxy (by rw [hzero x, hzero y]) + obtain ⟨i₀, j₀, hij⟩ := hne + refine + ⟨Fin.addCases (motive := fun _ ↦ R ⧸ 𝔪) (Pi.single j₀ 1) (Pi.single i₀ 1), ?_⟩ + rw [MvPolynomial.aeval_bilinearPairing] + simp only [Fin.addCases_left, Fin.addCases_right] + rw [sum_sum_mul_single_mul_single] + obtain ⟨b, hb⟩ := hfield.mul_inv_cancel hij + exact IsUnit.of_mul_eq_one b hb + -- Descend the witness: it is a functional taking the value `1` on a point of `M`. + obtain ⟨s, hs⟩ := hrep + set t : Fin n → R := fun j ↦ s (Fin.castAdd n j) with ht + set c : Fin n → R := fun i ↦ s (Fin.natAdd n i) with hc + have htj : ∀ j, t j = s (Fin.castAdd n j) := fun _ ↦ rfl + have hci : ∀ i, c i = s (Fin.natAdd n i) := fun _ ↦ rfl + set l : M →ₗ[R] R := + ∑ i, c i • ((LinearMap.proj i : (Fin n → R) →ₗ[R] R) ∘ₗ σ) with hl + have hlm : l (π t) = MvPolynomial.aeval s (MvPolynomial.bilinearPairing E) := by + rw [MvPolynomial.aeval_bilinearPairing, hl] + simp only [LinearMap.sum_apply, LinearMap.smul_apply, LinearMap.comp_apply, + smul_eq_mul, Algebra.algebraMap_self_apply] + refine Finset.sum_congr rfl fun i _ ↦ ?_ + have hei : σ (π t) i = ∑ j, E i j * t j := hcoord t i + rw [LinearMap.proj_apply, hei, Finset.mul_sum] + exact Finset.sum_congr rfl fun j _ ↦ by rw [htj, hci]; ring + rw [← hlm] at hs + refine ⟨π t, Module.isUnimodular_of_apply_eq_one (f := (hs.unit⁻¹ : Rˣ) • l) ?_⟩ + rw [LinearMap.smul_apply, Units.smul_def, smul_eq_mul] + exact hs.val_inv_mul diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/ValueIdeal.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/ValueIdeal.lean new file mode 100644 index 0000000000..562114ee1c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/ValueIdeal.lean @@ -0,0 +1,168 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Defs + +/-! +# The value ideal, and a finitary criterion for `IsLGRing` + +The defining biconditional of `IsLGRing` quantifies over all residue fields. This file replaces +that quantifier by a single ideal-theoretic condition on `R` itself: `p` represents a unit over +every residue field iff the ideal generated by *all* the values `p(s)`, `s : Fin n → R`, is the +unit ideal. + +The point is that the resulting criterion is **finitary**: `1 ∈ Ideal.span {p(s) : s}` unwinds to a +single equation `1 = Σᵢ cᵢ · p(sᵢ)` involving finitely many elements of `R`. Every example in +`LGRing/DirectLimit.lean` and `LGRing/ZeroDimensional.lean` is proved by starting from that +equation, and the direct-limit example is *exactly* the observation that a finitary condition +passes to filtered colimits. + +## Main definitions + +* `MvPolynomial.valueIdeal p` : the ideal of `R` generated by the set of values of `p`. + +## Main results + +* `MvPolynomial.representsUnit_quotient_iff` : `p` represents a unit over the residue field + `R ⧸ 𝔪` iff some value `p(s)`, with `s` taken in `R` itself, escapes `𝔪`. +* `MvPolynomial.valueIdeal_eq_top_iff` : `p.valueIdeal = ⊤` iff `p` represents a unit over every + residue field. +* `isLGRing_iff_forall_valueIdeal_eq_top` : `R` is LG iff every `p` with `p.valueIdeal = ⊤` + represents a unit over `R`. + +## Implementation notes + +`MvPolynomial.representsUnit_quotient_iff` is what makes the whole file work, and it is where the +maximality of `𝔪` is used: over a *field* a nonzero element is a unit, so the existence of a +witness in `(R ⧸ 𝔪)ⁿ` can be traded for the existence of a witness in `Rⁿ` — the reduction map +`Rⁿ → (R ⧸ 𝔪)ⁿ` is surjective, so nothing is lost by lifting. As in `LGRing/Defs.lean` we use the +`Prop`-valued `IsField (R ⧸ 𝔪)` rather than `Ideal.Quotient.field`, to avoid introducing a second +`Field` structure on the quotient. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.20. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §2.1. +-/ + +@[expose] public section + +universe u + +namespace MvPolynomial + +variable {R : Type u} [CommRing R] {n : ℕ} + +/-- The **value ideal** of `p : R[X₁,…,Xₙ]`: the ideal of `R` generated by the values `p(s)` as `s` +ranges over `Rⁿ`. It is the unit ideal exactly when `p` represents a unit over every residue field +(`MvPolynomial.valueIdeal_eq_top_iff`), which is the hypothesis side of the LG axiom. -/ +def valueIdeal (p : MvPolynomial (Fin n) R) : Ideal R := + Ideal.span (Set.range fun s : Fin n → R ↦ aeval s p) + +theorem aeval_mem_valueIdeal (p : MvPolynomial (Fin n) R) (s : Fin n → R) : + aeval s p ∈ p.valueIdeal := + Ideal.subset_span ⟨s, rfl⟩ + +theorem valueIdeal_le_iff {p : MvPolynomial (Fin n) R} {I : Ideal R} : + p.valueIdeal ≤ I ↔ ∀ s : Fin n → R, aeval s p ∈ I := by + simp [valueIdeal, Ideal.span_le, Set.range_subset_iff, SetLike.mem_coe] + +/-- Evaluating over `R` and reducing mod `𝔪` is evaluating over `R ⧸ 𝔪` at the reduced point. -/ +theorem quotient_mk_aeval (I : Ideal R) (p : MvPolynomial (Fin n) R) (s : Fin n → R) : + Ideal.Quotient.mk I (aeval s p) = aeval (fun i ↦ Ideal.Quotient.mk I (s i)) p := by + have := MvPolynomial.comp_aeval_apply (f := s) (φ := Algebra.ofId R (R ⧸ I)) (p := p) + simpa [Algebra.ofId_apply, Ideal.Quotient.algebraMap_eq] using this + +/-- `p` represents a unit over the residue field `R ⧸ 𝔪` exactly when some value of `p` *at a point +of `R`* escapes `𝔪`. + +Both directions use that `R ⧸ 𝔪` is a field: forwards, a unit is nonzero; backwards, a nonzero +element is a unit. The passage between witnesses over `R ⧸ 𝔪` and witnesses over `R` is the +surjectivity of `Ideal.Quotient.mk`. -/ +theorem representsUnit_quotient_iff (𝔪 : Ideal R) [h𝔪 : 𝔪.IsMaximal] + (p : MvPolynomial (Fin n) R) : + p.RepresentsUnit (R ⧸ 𝔪) ↔ ∃ s : Fin n → R, aeval s p ∉ 𝔪 := by + have hfield : IsField (R ⧸ 𝔪) := + (Ideal.Quotient.maximal_ideal_iff_isField_quotient 𝔪).mp h𝔪 + have : Nontrivial (R ⧸ 𝔪) := Ideal.Quotient.nontrivial_iff.mpr h𝔪.ne_top + constructor + · rintro ⟨t, ht⟩ + choose s hs using fun i ↦ Ideal.Quotient.mk_surjective (t i) + have hts : t = fun i ↦ Ideal.Quotient.mk 𝔪 (s i) := funext fun i ↦ (hs i).symm + subst hts + refine ⟨s, fun hmem ↦ ?_⟩ + rw [← quotient_mk_aeval, Ideal.Quotient.eq_zero_iff_mem.mpr hmem] at ht + exact zero_ne_one (isUnit_zero_iff.mp ht) + · rintro ⟨s, hs⟩ + refine ⟨fun i ↦ Ideal.Quotient.mk 𝔪 (s i), ?_⟩ + rw [← quotient_mk_aeval] + obtain ⟨c, hc⟩ := hfield.mul_inv_cancel (fun h ↦ hs (Ideal.Quotient.eq_zero_iff_mem.mp h)) + exact IsUnit.of_mul_eq_one c hc + +/-- The value ideal is the unit ideal exactly when `p` represents a unit over every residue field: +"`p.valueIdeal ≠ ⊤`" and "`p` misses a residue field" are both the statement that some maximal +ideal swallows every value of `p`. -/ +theorem valueIdeal_eq_top_iff (p : MvPolynomial (Fin n) R) : + p.valueIdeal = ⊤ ↔ + ∀ (𝔪 : Ideal R) [𝔪.IsMaximal], p.RepresentsUnit (R ⧸ 𝔪) := by + constructor + · intro htop 𝔪 h𝔪 + rw [representsUnit_quotient_iff] + by_contra hcon + exact h𝔪.ne_top (top_le_iff.mp (htop ▸ valueIdeal_le_iff.mpr + fun s ↦ not_not.mp fun hns ↦ hcon ⟨s, hns⟩)) + · intro hall + by_contra hne + obtain ⟨𝔪, h𝔪, hle⟩ := Ideal.exists_le_maximal _ hne + obtain ⟨s, hs⟩ := (representsUnit_quotient_iff 𝔪 p).mp (hall 𝔪) + exact hs (hle (aeval_mem_valueIdeal p s)) + +/-! ### The finitary unwinding + +`p.valueIdeal = ⊤` says `1` lies in the span of the values of `p`, which is a statement about a +single equation in finitely many elements of `R`. These two lemmas are that translation, and they +are the only interface the examples use. -/ + +/-- Unwinding `p.valueIdeal = ⊤`: finitely many points `t j` of `Rⁿ` whose values at `p` combine +to `1`. -/ +theorem exists_sum_mul_aeval_eq_one {p : MvPolynomial (Fin n) R} (h : p.valueIdeal = ⊤) : + ∃ (k : ℕ) (c : Fin k → R) (t : Fin k → Fin n → R), + ∑ j, c j * aeval (t j) p = 1 := by + obtain ⟨k, c, g, hg⟩ := + Submodule.mem_span_set'.mp (h ▸ Submodule.mem_top (R := R) (x := (1 : R))) + choose t ht using fun j ↦ (g j).2 + exact ⟨k, c, t, by simpa only [ht, smul_eq_mul] using hg⟩ + +/-- Conversely, one such equation forces `p.valueIdeal = ⊤`. -/ +theorem valueIdeal_eq_top_of_sum_mul_aeval_eq_one {p : MvPolynomial (Fin n) R} {k : ℕ} + (c : Fin k → R) (t : Fin k → Fin n → R) (h : ∑ j, c j * aeval (t j) p = 1) : + p.valueIdeal = ⊤ := + Ideal.eq_top_of_isUnit_mem _ + (h ▸ Submodule.sum_mem _ fun j _ ↦ Ideal.mul_mem_left _ _ (aeval_mem_valueIdeal p (t j))) + isUnit_one + +end MvPolynomial + +/-- **A finitary criterion for `IsLGRing`.** `R` is an LG-ring iff, whenever the values of a +polynomial `p` generate the unit ideal, `p` already takes a unit value. + +This is the form of the LG axiom used throughout `LGRing/DirectLimit.lean` and +`LGRing/ZeroDimensional.lean`: unlike the definition, its hypothesis unwinds to a *single equation* +`1 = Σᵢ cᵢ · p(sᵢ)` in finitely many elements of `R`. -/ +theorem isLGRing_iff_forall_valueIdeal_eq_top (R : Type u) [CommRing R] : + IsLGRing R ↔ ∀ (n : ℕ) (p : MvPolynomial (Fin n) R), + p.valueIdeal = ⊤ → p.RepresentsUnit R := by + constructor + · exact fun hLG n p htop ↦ (hLG n p).mpr ((MvPolynomial.valueIdeal_eq_top_iff p).mp htop) + · intro h n p + refine + ⟨fun ⟨s, hs⟩ 𝔪 _ ↦ ?_, + fun hall ↦ h n p ((MvPolynomial.valueIdeal_eq_top_iff p).mpr fun 𝔪 _ ↦ hall 𝔪)⟩ + refine ⟨fun i ↦ Ideal.Quotient.mk 𝔪 (s i), ?_⟩ + rw [← MvPolynomial.quotient_mk_aeval] + simpa using hs.map (Ideal.Quotient.mk 𝔪) diff --git a/LeanPool/CompositionAlgebrasOverRings/LGRing/ZeroDimensional.lean b/LeanPool/CompositionAlgebrasOverRings/LGRing/ZeroDimensional.lean new file mode 100644 index 0000000000..edaabd0da4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/LGRing/ZeroDimensional.lean @@ -0,0 +1,394 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Jacobson +public import LeanPool.CompositionAlgebrasOverRings.LGRing.ValueIdeal +public import Mathlib.RingTheory.Ideal.Maps +public import Mathlib.RingTheory.KrullDimension.Basic + +/-! +# Von Neumann regular and zero-dimensional rings are LG + +`GN 2.2` (from `EG`): von Neumann regular rings are LG-rings, and more generally so are +zero-dimensional rings. + +## Main definitions + +* `IsVonNeumannRegular R` : every `a : R` satisfies `a * x * a = a` for some `x`. mathlib has no + such predicate, so we introduce one; see the implementation notes. +* `MvPolynomial.RepresentsUnitOn p e` : local scaffolding — `p` takes a value that is invertible + "on the idempotent `e`", i.e. invertible in the ring `eR`, without leaving `R`. + +## Main results + +* `isLGRing_of_forall_exists_idempotent` : the shared criterion. If every `a : R` admits an + idempotent `f` such that `a` is invertible on `f` and some power of `a` lies in `(f)`, then `R` + is an LG-ring. +* `IsVonNeumannRegular.isLGRing` : **`GN 2.2`**, von Neumann regular implies LG. +* `isLGRing_of_isVonNeumannRegular_quotient_jacobson` : the same with `R ⧸ Jac(R)` von Neumann + regular, which is how `GN` states it. +* `Ring.exists_pow_eq_pow_succ_mul` : in a zero-dimensional ring every `a` satisfies + `aᵐ = aᵐ⁺¹ x` for some `m` and `x`. +* `isLGRing_of_krullDimLE_zero` : **`GN 2.2`**, `Ring.KrullDimLE 0` implies LG. + +## Proof idea + +By the value-ideal criterion (`LGRing/ValueIdeal.lean`), being LG amounts to: from +`1 = Σⱼ cⱼ · p(tⱼ)` produce a *single* point where `p` is a unit. The `tⱼ` each work somewhere but +nowhere in particular; the idempotents are what let their witnesses be spliced together. + +Write `aⱼ := p(tⱼ)` and let `fⱼ` be the idempotent supplied by the hypothesis, so that `aⱼ` is +invertible on `fⱼ`. Since a power of `aⱼ` lies in `(fⱼ)`, a maximal ideal containing every `fⱼ` +would contain every `aⱼ` and hence `1`; so the `fⱼ` generate the unit ideal and `∏ⱼ (1 - fⱼ) = 0`. +Orthogonalising, `1 = Σⱼ eⱼ` with `eⱼ ≤ fⱼ`, and the point `s := Σⱼ eⱼ tⱼ` restricts to `tⱼ` on the +`j`-th block: `eⱼ · s = eⱼ · tⱼ`, hence `eⱼ · p(s) = eⱼ · p(tⱼ)` — the key step +`MvPolynomial.mul_aeval_eq_of_mul_eq`, proved by induction on `p`, using only that multiplication +by an idempotent is "the projection onto `eR`". So `p(s)` is invertible on every block, and the +blocks exhaust `R`. + +The two examples differ only in producing the idempotent. Von Neumann regularity gives it at once +(`f = ax`, with `a` invertible on `f` and `a ∈ (f)`). For a zero-dimensional ring one first shows +`aᵐ = aᵐ⁺¹ x`, which produces `f = aᵐ xᵐ` with `aᵐ ∈ (f)` — the power is genuinely needed here, +which is why the criterion is stated with `a ^ m ∈ (f)` rather than `a ∈ (f)`. + +## Implementation notes + +`IsVonNeumannRegular` is a new definition, which overview §0 asks us to justify: mathlib (as +pinned in `lake-manifest.json`) has no von Neumann regular *ring* predicate — its only +`VonNeumann` namespace is `Analysis.VonNeumannAlgebra`, an unrelated notion. The definition is +stated for `CommRing` because that is all this file needs and all the LG theory ever uses; the +usual definition makes sense for any ring. + +`MvPolynomial.RepresentsUnitOn` is deliberately phrased inside `R`, as `∃ s c, e * p(s) * c = e`, +rather than as `MvPolynomial.RepresentsUnit` over the ring `eR` or `R ⧸ (1 - e)`. Every proof here +is an identity between elements of `R`, and routing through a quotient or a subtype would force +transporting polynomials back and forth for no gain. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Example 2.2. +* [EG] Estes, Guralnick, *Module equivalences: local to global when primitive polynomials represent + units*, Journal of Algebra **77** (1982), 138–157. +-/ + +@[expose] public section + +universe u + +variable {R : Type u} [CommRing R] {n : ℕ} + +/-! ### Evaluation only sees a point through an idempotent -/ + +namespace MvPolynomial + +/-- **Multiplication by an idempotent is a ring map onto `eR`,** so it cannot tell two points +apart that agree after multiplication by `e`. This is the splicing lemma: it is what allows a +witness assembled block by block to be evaluated block by block. + +The proof is a direct induction on `p`; the multiplicative step is +`e·(AB) = (e·e)·(AB) = (e·A)(e·B)`. -/ +theorem mul_aeval_eq_of_mul_eq {e : R} (he : IsIdempotentElem e) {s t : Fin n → R} + (h : ∀ i, e * s i = e * t i) (p : MvPolynomial (Fin n) R) : + e * aeval s p = e * aeval t p := by + have hsplit : ∀ (u : Fin n → R) (q : MvPolynomial (Fin n) R) (i : Fin n), + e * aeval u (q * X i) = (e * aeval u q) * (e * u i) := by + intro u q i + rw [map_mul, aeval_X] + calc e * (aeval u q * u i) = e * e * (aeval u q * u i) := by rw [he] + _ = e * aeval u q * (e * u i) := by ring + induction p using MvPolynomial.induction_on with + | C a => simp + | add q r hq hr => rw [map_add, map_add, mul_add, mul_add, hq, hr] + | mul_X q i hq => rw [hsplit s q i, hsplit t q i, hq, h i] + +/-- `p` **represents a unit on the idempotent `e`**: some value `p(s)` is invertible in the ring +`eR`, expressed without leaving `R`. For `e = 1` this is `MvPolynomial.RepresentsUnit` +(`MvPolynomial.RepresentsUnitOn.representsUnit`), and for `e = 0` it is vacuous. -/ +def RepresentsUnitOn (p : MvPolynomial (Fin n) R) (e : R) : Prop := + ∃ (s : Fin n → R) (c : R), e * aeval s p * c = e + +theorem representsUnitOn_zero (p : MvPolynomial (Fin n) R) : p.RepresentsUnitOn 0 := + ⟨0, 0, by simp⟩ + +/-- Representing a unit on `e` is inherited by any `e'` below `e` (`e' * e = e'`): the same witness +works, since `e'` factors through `e`. -/ +theorem RepresentsUnitOn.mono {p : MvPolynomial (Fin n) R} {e e' : R} (h : p.RepresentsUnitOn e) + (hle : e' * e = e') : p.RepresentsUnitOn e' := by + obtain ⟨s, c, hsc⟩ := h + refine ⟨s, c, ?_⟩ + calc e' * aeval s p * c = e' * e * aeval s p * c := by rw [hle] + _ = e' * (e * aeval s p * c) := by ring + _ = e' * e := by rw [hsc] + _ = e' := hle + +/-- **Gluing over orthogonal idempotents.** Witnesses on `e₁` and on `e₂` splice into a witness on +`e₁ + e₂`: take `s := e₁ s₁ + e₂ s₂`, which agrees with `sₖ` after multiplication by `eₖ`, so that +`eₖ · p(s) = eₖ · p(sₖ)` by `MvPolynomial.mul_aeval_eq_of_mul_eq`; the inverses glue as +`e₁ c₁ + e₂ c₂`, all cross terms being killed by orthogonality. -/ +theorem RepresentsUnitOn.add {p : MvPolynomial (Fin n) R} {e₁ e₂ : R} + (h₁ : IsIdempotentElem e₁) + (h₂ : IsIdempotentElem e₂) (horth : e₁ * e₂ = 0) (hr₁ : p.RepresentsUnitOn e₁) + (hr₂ : p.RepresentsUnitOn e₂) : p.RepresentsUnitOn (e₁ + e₂) := by + obtain ⟨s₁, c₁, hs₁⟩ := hr₁ + obtain ⟨s₂, c₂, hs₂⟩ := hr₂ + have horth' : e₂ * e₁ = 0 := by rw [mul_comm]; exact horth + refine ⟨fun x ↦ e₁ * s₁ x + e₂ * s₂ x, e₁ * c₁ + e₂ * c₂, ?_⟩ + have k₁ : e₁ * aeval (fun x ↦ e₁ * s₁ x + e₂ * s₂ x) p = e₁ * aeval s₁ p := + mul_aeval_eq_of_mul_eq h₁ (fun i ↦ by + calc + e₁ * (e₁ * s₁ i + e₂ * s₂ i) = + e₁ * e₁ * s₁ i + e₁ * e₂ * s₂ i := by ring + _ = e₁ * s₁ i := by rw [h₁, horth]; ring) p + have k₂ : e₂ * aeval (fun x ↦ e₁ * s₁ x + e₂ * s₂ x) p = e₂ * aeval s₂ p := + mul_aeval_eq_of_mul_eq h₂ (fun i ↦ by + calc + e₂ * (e₁ * s₁ i + e₂ * s₂ i) = + e₂ * e₁ * s₁ i + e₂ * e₂ * s₂ i := by ring + _ = e₂ * s₂ i := by rw [h₂, horth']; ring) p + set v := aeval (fun x ↦ e₁ * s₁ x + e₂ * s₂ x) p with hv + calc (e₁ + e₂) * v * (e₁ * c₁ + e₂ * c₂) + = e₁ * e₁ * (v * c₁) + e₁ * e₂ * (v * c₂) + + (e₂ * e₁ * (v * c₁) + e₂ * e₂ * (v * c₂)) := by + ring + _ = e₁ * v * c₁ + e₂ * v * c₂ := by rw [h₁, h₂, horth, horth']; ring + _ = e₁ * aeval s₁ p * c₁ + e₂ * aeval s₂ p * c₂ := by rw [k₁, k₂] + _ = e₁ + e₂ := by rw [hs₁, hs₂] + +theorem RepresentsUnitOn.representsUnit {p : MvPolynomial (Fin n) R} (h : p.RepresentsUnitOn 1) : + p.RepresentsUnit R := by + obtain ⟨s, c, hsc⟩ := h + exact ⟨s, IsUnit.of_mul_eq_one c (by simpa using hsc)⟩ + +/-- Orthogonalisation, in the form the induction needs: for a family of idempotents `f` each of +which supports a witness for `p`, the idempotent `1 - ∏_{i ∈ T} (1 - fᵢ)` — the "union" of the +blocks indexed by `T` — again supports one. + +The step from `T` to `insert j T` writes `1 - ∏_{insert j T}(1 - fᵢ) = e + fⱼ(1 - e)` with +`e := 1 - ∏_T (1 - fᵢ)`, a sum of *orthogonal* idempotents to which +`MvPolynomial.RepresentsUnitOn.add` applies; the second summand lies below `fⱼ`, so it inherits a +witness by `MvPolynomial.RepresentsUnitOn.mono`. -/ +theorem representsUnitOn_one_sub_prod {ι : Type*} {p : MvPolynomial (Fin n) R} + (f : ι → R) (hf : ∀ i, IsIdempotentElem (f i)) (hrep : ∀ i, p.RepresentsUnitOn (f i)) + (T : Finset ι) : + IsIdempotentElem (1 - ∏ i ∈ T, (1 - f i)) ∧ + p.RepresentsUnitOn (1 - ∏ i ∈ T, (1 - f i)) := by + classical + induction T using Finset.induction with + | empty => simpa using ⟨IsIdempotentElem.zero, representsUnitOn_zero p⟩ + | insert j T hj ih => + obtain ⟨hidem, hrepT⟩ := ih + set e : R := 1 - ∏ i ∈ T, (1 - f i) with he + have hnew : 1 - ∏ i ∈ insert j T, (1 - f i) = e + f j * (1 - e) := by + rw [Finset.prod_insert hj, he]; ring + have h2 : IsIdempotentElem (f j * (1 - e)) := by + change f j * (1 - e) * (f j * (1 - e)) = f j * (1 - e) + calc f j * (1 - e) * (f j * (1 - e)) + = f j * f j * (1 - e - (e - e * e)) := by ring + _ = f j * (1 - e) := by rw [hf j, hidem]; ring + have horth : e * (f j * (1 - e)) = 0 := by + calc e * (f j * (1 - e)) = f j * (e - e * e) := by ring + _ = 0 := by rw [hidem]; ring + have hsum : IsIdempotentElem (e + f j * (1 - e)) := by + change (e + f j * (1 - e)) * (e + f j * (1 - e)) = e + f j * (1 - e) + calc (e + f j * (1 - e)) * (e + f j * (1 - e)) + = e * e + (e * (f j * (1 - e)) + e * (f j * (1 - e))) + + f j * (1 - e) * (f j * (1 - e)) := by ring + _ = e + f j * (1 - e) := by rw [hidem, horth, h2]; ring + refine ⟨hnew ▸ hsum, hnew ▸ hrepT.add hidem h2 horth ((hrep j).mono ?_)⟩ + calc f j * (1 - e) * f j = f j * f j * (1 - e) := by ring + _ = f j * (1 - e) := by rw [hf j] + +end MvPolynomial + +/-! ### The shared criterion -/ + +/-- **The idempotent criterion for `IsLGRing`.** Suppose every `a : R` admits an idempotent `f` +together with a `c` making `a` invertible on `f` (`a·c·f = f`), and some power `aᵐ` lying in the +ideal `(f)`. Then `R` is an LG-ring. + +The two hypotheses on `f` play complementary roles: `a·c·f = f` supplies the witness *on the block +`f`*, and `aᵐ ∈ (f)` forces the blocks to cover `Spec R`, since a maximal ideal containing all the +`fⱼ` would contain all the `aⱼ` and hence `1 = Σⱼ cⱼ aⱼ`. -/ +theorem isLGRing_of_forall_exists_idempotent + (h : ∀ a : R, ∃ f c : R, IsIdempotentElem f ∧ a * c * f = f ∧ ∃ m : ℕ, + a ^ m ∈ Ideal.span {f}) : IsLGRing R := by + classical + rw [isLGRing_iff_forall_valueIdeal_eq_top] + intro n p htop + obtain ⟨k, c, t, hsum⟩ := MvPolynomial.exists_sum_mul_aeval_eq_one htop + choose F C hFidem hFinv m hFpow using fun j : Fin k ↦ h (MvPolynomial.aeval (t j) p) + -- Each block carries a witness, namely `t j` itself. + have hrep : ∀ j, p.RepresentsUnitOn (F j) := fun j ↦ + ⟨t j, C j, by + calc F j * MvPolynomial.aeval (t j) p * C j + = MvPolynomial.aeval (t j) p * C j * F j := by ring + _ = F j := hFinv j⟩ + -- The blocks cover: no maximal ideal contains every `F j`. + have hspan : Ideal.span (Set.range F) = ⊤ := by + by_contra hne + obtain ⟨𝔪, h𝔪, hle⟩ := Ideal.exists_le_maximal _ hne + have : 𝔪.IsPrime := h𝔪.isPrime + refine h𝔪.ne_top ((Ideal.eq_top_iff_one 𝔪).mpr ?_) + rw [← hsum] + refine Submodule.sum_mem _ fun j _ ↦ Ideal.mul_mem_left _ _ ?_ + refine Ideal.IsPrime.mem_of_pow_mem (n := m j) inferInstance ?_ + exact Ideal.span_le.mpr (Set.singleton_subset_iff.mpr + (hle (Ideal.subset_span ⟨j, rfl⟩))) (hFpow j) + -- Hence the complementary idempotents multiply to zero, so the blocks exhaust `R`. + have hprod : ∏ j : Fin k, (1 - F j) = 0 := by + obtain ⟨d, hd⟩ := Ideal.mem_span_range_iff_exists_fun.mp (hspan ▸ Submodule.mem_top) + calc + ∏ j : Fin k, (1 - F j) = + (∏ j : Fin k, (1 - F j)) * ∑ j, d j * F j := by + rw [hd, mul_one] + _ = ∑ j, d j * ((∏ i ∈ Finset.univ.erase j, (1 - F i)) * ((1 - F j) * F j)) := by + rw [Finset.mul_sum] + refine Finset.sum_congr rfl fun j _ ↦ ?_ + rw [← Finset.mul_prod_erase Finset.univ (fun i ↦ 1 - F i) (Finset.mem_univ j)] + ring + _ = 0 := by + refine Finset.sum_eq_zero fun j _ ↦ ?_ + have : (1 - F j) * F j = 0 := by rw [sub_mul, one_mul, hFidem j, sub_self] + rw [this, mul_zero, mul_zero] + have := (MvPolynomial.representsUnitOn_one_sub_prod F hFidem hrep Finset.univ).2 + rw [hprod, sub_zero] at this + exact this.representsUnit + +/-! ### Von Neumann regular rings -/ + +/-- A commutative ring is **von Neumann regular** if every element `a` satisfies `a * x * a = a` +for some `x` — equivalently, if every principal ideal is generated by an idempotent. + +⚠ mathlib has no von Neumann regular ring predicate at the pinned revision (its only `VonNeumann` +namespace is the unrelated `Analysis.VonNeumannAlgebra`), which is why this is defined here rather +than imported. If one is added upstream, this definition should be replaced by it. -/ +def IsVonNeumannRegular (R : Type u) [CommRing R] : Prop := + ∀ a : R, ∃ x : R, a * x * a = a + +/-- **`GN 2.2`: a von Neumann regular ring is an LG-ring.** + +The support idempotent of `a` is `f = a·x`: it is idempotent because `axax = (axa)x = ax`, the +element `a` is invertible on it with `c = x` for the same reason, and `a = a·(ax)` lies in `(f)` +outright — no power is needed. -/ +theorem IsVonNeumannRegular.isLGRing (h : IsVonNeumannRegular R) : IsLGRing R := by + refine isLGRing_of_forall_exists_idempotent fun a ↦ ?_ + obtain ⟨x, hx⟩ := h a + refine ⟨a * x, x, ?_, ?_, 1, ?_⟩ + · change a * x * (a * x) = a * x + calc a * x * (a * x) = a * x * a * x := by ring + _ = a * x := by rw [hx] + · calc a * x * (a * x) = a * x * a * x := by ring + _ = a * x := by rw [hx] + · rw [pow_one, Ideal.mem_span_singleton'] + refine ⟨a, ?_⟩ + calc a * (a * x) = a * x * a := by ring + _ = a := hx + +/-- **`GN 2.2`, in the form the source states it:** it is enough that `R ⧸ Jac(R)` be von Neumann +regular. Combine `IsVonNeumannRegular.isLGRing` with `GPR 11.21(i)` +(`isLGRing_iff_isLGRing_quotient_jacobson`). -/ +theorem isLGRing_of_isVonNeumannRegular_quotient_jacobson + (h : IsVonNeumannRegular (R ⧸ Ring.jacobson R)) : IsLGRing R := + isLGRing_iff_isLGRing_quotient_jacobson.mpr h.isLGRing + +/-! ### Zero-dimensional rings -/ + +/-- In a zero-dimensional ring every element satisfies `aᵐ = aᵐ⁺¹ x` for some `m` and `x`. + +The ideal `J = ⋃ₘ Ann(aᵐ)` together with `(a)` generates everything: were both inside a maximal +ideal `𝔪`, then — `𝔪` being *minimal* prime, `R` having dimension zero — the multiplicative set +`{aⁱ s : s ∉ 𝔪}` would miss `0`, and a prime disjoint from it would be a prime strictly inside +`𝔪` (it omits `a ∈ 𝔪`) yet still maximal, which is absurd. So `0 = aⁱ s` for some `s ∉ 𝔪`, putting +`s` in `J ⊆ 𝔪`. Writing `1 = c·a + z` with `z·aᵐ = 0` and multiplying by `aᵐ` gives the claim. -/ +theorem Ring.exists_pow_eq_pow_succ_mul [Ring.KrullDimLE 0 R] (a : R) : + ∃ (m : ℕ) (x : R), a ^ m = a ^ (m + 1) * x := by + classical + set A : ℕ → Ideal R := fun i ↦ (Ideal.span {a ^ i}).annihilator with hA + have hmemA : ∀ (i : ℕ) (r : R), r ∈ A i ↔ r * a ^ i = 0 := fun i r ↦ by + rw [hA]; simpa using Submodule.mem_annihilator_span_singleton (a ^ i) r + have hmono : Monotone A := by + intro i i' hii r hr + rw [hmemA] at hr ⊢ + rw [← Nat.add_sub_cancel' hii, pow_add, ← mul_assoc, hr, zero_mul] + have hdir : Directed (· ≤ ·) A := hmono.directed_le + have hmemJ : ∀ r : R, r ∈ ⨆ i, A i ↔ ∃ i, r * a ^ i = 0 := fun r ↦ by + rw [Submodule.mem_iSup_of_directed A hdir] + exact exists_congr fun i ↦ hmemA i r + have hkey : Ideal.span {a} ⊔ (⨆ i, A i) = ⊤ := by + by_contra hne + obtain ⟨𝔪, h𝔪, hle⟩ := Ideal.exists_le_maximal _ hne + have hprime : 𝔪.IsPrime := h𝔪.isPrime + have ha𝔪 : a ∈ 𝔪 := hle (Submodule.mem_sup_left (Ideal.mem_span_singleton_self a)) + have hone : (1 : R) ∉ 𝔪 := fun hcon ↦ h𝔪.ne_top ((Ideal.eq_top_iff_one 𝔪).mpr hcon) + set S : Submonoid R := + { carrier := {y | ∃ (i : ℕ) (s : R), s ∉ 𝔪 ∧ y = a ^ i * s} + one_mem' := ⟨0, 1, hone, by simp⟩ + mul_mem' := by + rintro _ _ ⟨i, s, hs, rfl⟩ ⟨i', s', hs', rfl⟩ + exact ⟨i + i', s * s', fun hcon ↦ (hprime.mem_or_mem hcon).elim hs hs', + by rw [pow_add]; ring⟩ } with hS + have hzero : (0 : R) ∈ S := by + by_contra h0 + obtain ⟨q, hq, -, hdisj⟩ := Ideal.exists_le_prime_disjoint (⊥ : Ideal R) S (by + rw [Set.disjoint_left] + intro x hx + rw [SetLike.mem_coe, Ideal.mem_bot] at hx + exact hx ▸ h0) + have haq : a ∉ q := fun hcon ↦ + Set.disjoint_left.mp hdisj hcon ⟨1, 1, hone, by simp⟩ + refine haq ?_ + have : q.IsMaximal := hq.isMaximal' + have hqle : q ≤ 𝔪 := fun x hx ↦ by + by_contra hxm + exact Set.disjoint_left.mp hdisj hx ⟨0, x, hxm, by simp⟩ + rw [Ideal.IsMaximal.eq_of_le ‹q.IsMaximal› h𝔪.ne_top hqle] + exact ha𝔪 + obtain ⟨i, s, hs, hsi⟩ := hzero + exact hs (hle (Submodule.mem_sup_right ((hmemJ s).mpr ⟨i, by rw [mul_comm, ← hsi]⟩))) + have h1 : (1 : R) ∈ Ideal.span {a} ⊔ (⨆ i, A i) := by rw [hkey]; trivial + obtain ⟨y, hy, z, hz, hyz⟩ := Submodule.mem_sup.mp h1 + obtain ⟨cc, hcc⟩ := Ideal.mem_span_singleton'.mp hy + obtain ⟨i, hzi⟩ := (hmemJ z).mp hz + refine ⟨i, cc, ?_⟩ + have haz : a ^ i * z = 0 := by rw [mul_comm]; exact hzi + calc a ^ i = a ^ i * (y + z) := by rw [hyz, mul_one] + _ = a ^ i * y + a ^ i * z := by ring + _ = a ^ i * (cc * a) := by rw [haz, ← hcc]; ring + _ = a ^ (i + 1) * cc := by rw [pow_succ]; ring + +/-- **`GN 2.2`: a zero-dimensional ring is an LG-ring.** + +From `aᵐ = aᵐ⁺¹ x` (`Ring.exists_pow_eq_pow_succ_mul`) one gets, by iterating, `aᵐ = aᵐ⁺ᵏ xᵏ` for +every `k`; taking `k = m` shows `f := aᵐ xᵐ` is idempotent, that `a·x·f = f`, and that +`aᵐ = aᵐ · f ∈ (f)`. This is the case the criterion's `a ^ m ∈ (f)` clause was written for: unlike +the von Neumann regular case, `a` itself need not lie in `(f)`. -/ +theorem isLGRing_of_krullDimLE_zero (R : Type u) [CommRing R] [Ring.KrullDimLE 0 R] : + IsLGRing R := by + refine isLGRing_of_forall_exists_idempotent fun a ↦ ?_ + obtain ⟨m, x, hmx⟩ := Ring.exists_pow_eq_pow_succ_mul a + have hstep : ∀ j : ℕ, a ^ (m + j) = a ^ (m + j + 1) * x := fun j ↦ + calc a ^ (m + j) = a ^ j * a ^ m := by rw [pow_add]; ring + _ = a ^ j * (a ^ (m + 1) * x) := by rw [← hmx] + _ = a ^ (m + j + 1) * x := by rw [pow_add, pow_add, pow_add]; ring + have hiter : ∀ k : ℕ, a ^ m = a ^ (m + k) * x ^ k := by + intro k + induction k with + | zero => simp + | succ k ih => + rw [ih, hstep k, show m + (k + 1) = m + k + 1 from rfl, pow_succ] + ring + refine ⟨a ^ m * x ^ m, x, ?_, ?_, m, ?_⟩ + · change a ^ m * x ^ m * (a ^ m * x ^ m) = a ^ m * x ^ m + calc a ^ m * x ^ m * (a ^ m * x ^ m) = (a ^ (m + m) * x ^ m) * x ^ m := by rw [pow_add]; ring + _ = a ^ m * x ^ m := by rw [← hiter m] + · calc a * x * (a ^ m * x ^ m) = a ^ (m + 1) * x * x ^ m := by rw [pow_succ]; ring + _ = a ^ m * x ^ m := by rw [← hmx] + · rw [Ideal.mem_span_singleton'] + refine ⟨a ^ m, ?_⟩ + calc a ^ m * (a ^ m * x ^ m) = a ^ (m + m) * x ^ m := by rw [pow_add]; ring + _ = a ^ m := (hiter m).symm diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/AlternatingBaseChange.lean b/LeanPool/CompositionAlgebrasOverRings/Module/AlternatingBaseChange.lean new file mode 100644 index 0000000000..a5900ee055 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/AlternatingBaseChange.lean @@ -0,0 +1,305 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.Alternating.Curry +public import Mathlib.LinearAlgebra.Dual.BaseChange +public import Mathlib.LinearAlgebra.Matrix.Determinant.Basic +public import Mathlib.RingTheory.TensorProduct.Basic + +/-! +# Base change of alternating trilinear forms + +This file constructs the scalar extension of an alternating trilinear form. The construction is +written for three variables, which is the case used by vector products on oriented rank-three +modules. It first extends the curried trilinear map one variable at a time and then verifies that +the resulting form remains alternating, without any assumption that two is invertible. + +## Main definitions + +* `AlternatingMap.baseChangeAlternatingFinThree` : scalar extension of an alternating trilinear + form. + +## Main results + +* `AlternatingMap.baseChangeAlternatingFinThree_tmul` : evaluation on pure tensors. +* `AlternatingMap.baseChangeFinThree_mul_eq_det` : scalar extension preserves the determinant + identity coupling a form on a module to one on its dual. +-/ + +@[expose] public section + +universe u v w + +open Matrix TensorProduct + +namespace AlternatingMap + +variable {R : Type u} [CommRing R] + {M : Type v} [AddCommGroup M] [Module R M] + {S : Type w} [CommRing S] [Algebra R S] + +/-- An alternating trilinear form, curried as two linear maps followed by a dual vector. -/ +noncomputable def curryFinThree (a : M [⋀^Fin 3]→ₗ[R] R) : + M →ₗ[R] M →ₗ[R] Module.Dual R M := + let z : M [⋀^Fin 0]→ₗ[R] R ≃ₗ[R] R := constLinearEquivOfIsEmpty.symm + let y₁ : M [⋀^Fin 1]→ₗ[R] R →ₗ[R] Module.Dual R M := + LinearMap.llcomp R M (M [⋀^Fin 0]→ₗ[R] R) R z ∘ₗ curryLeftLinearMap + let y₂ : M [⋀^Fin 2]→ₗ[R] R →ₗ[R] M →ₗ[R] Module.Dual R M := + LinearMap.llcomp R M (M [⋀^Fin 1]→ₗ[R] R) (Module.Dual R M) y₁ ∘ₗ + curryLeftLinearMap + LinearMap.llcomp R M (M [⋀^Fin 2]→ₗ[R] R) (M →ₗ[R] Module.Dual R M) y₂ + a.curryLeft + +@[simp] theorem curryFinThree_apply (a : M [⋀^Fin 3]→ₗ[R] R) (x y z : M) : + curryFinThree a x y z = a ![x, y, z] := by + simp [curryFinThree, Matrix.vecCons, Matrix.vecEmpty] + +/-- The scalar extension of the curried trilinear map underlying an alternating trilinear +form. -/ +noncomputable def baseChangeFinThree (a : M [⋀^Fin 3]→ₗ[R] R) : + (S ⊗[R] M) →ₗ[S] (S ⊗[R] M) →ₗ[S] Module.Dual S (S ⊗[R] M) := + let middleR : M →ₗ[R] M →ₗ[R] Module.Dual S (S ⊗[R] M) := + (curryFinThree a).compr₂ (Module.Dual.baseChange (R := R) (V := M) S) + let outerR : M →ₗ[R] (S ⊗[R] M) →ₗ[S] Module.Dual S (S ⊗[R] M) := + { toFun := fun x ↦ (middleR x).liftBaseChange S + map_add' := by intro x y; ext z; simp [middleR] + map_smul' := by intro r x; ext z; simp [middleR] } + outerR.liftBaseChange S + +@[simp] theorem baseChangeFinThree_tmul (a : M [⋀^Fin 3]→ₗ[R] R) + (r s t : S) (x y z : M) : + baseChangeFinThree (S := S) a (r ⊗ₜ[R] x) (s ⊗ₜ[R] y) (t ⊗ₜ[R] z) = + r * s * t * algebraMap R S (a ![x, y, z]) := by + simp [baseChangeFinThree, Module.Dual.baseChange_apply_tmul, Algebra.smul_def] + ring + +private theorem fin_three_swap_zero_one (a : M [⋀^Fin 3]→ₗ[R] R) (x y z : M) : + a ![x, y, z] = -a ![y, x, z] := by + have h := a.map_swap ![x, y, z] (show (0 : Fin 3) ≠ 1 by decide) + have heq : ![x, y, z] ∘ Equiv.swap (0 : Fin 3) 1 = ![y, x, z] := by + ext i + fin_cases i <;> rfl + rw [heq] at h + rw [h, neg_neg] + +private theorem fin_three_swap_one_two (a : M [⋀^Fin 3]→ₗ[R] R) (x y z : M) : + a ![x, y, z] = -a ![x, z, y] := by + have h := a.map_swap ![x, y, z] (show (1 : Fin 3) ≠ 2 by decide) + have heq : ![x, y, z] ∘ Equiv.swap (1 : Fin 3) 2 = ![x, z, y] := by + ext i + fin_cases i <;> rfl + rw [heq] at h + rw [h, neg_neg] + +theorem baseChangeFinThree_swap_zero_one (a : M [⋀^Fin 3]→ₗ[R] R) + (x y z : S ⊗[R] M) : + baseChangeFinThree (S := S) a x y z = -baseChangeFinThree (S := S) a y x z := by + induction x using TensorProduct.inductionOn with + | add x x' hx hx' => simp [hx, hx']; abel + | tmul r x => + induction y using TensorProduct.inductionOn with + | add y y' hy hy' => simp [hy, hy']; abel + | tmul s y => + induction z using TensorProduct.inductionOn with + | add z z' hz hz' => simp [hz, hz']; abel + | tmul t z => + rw [baseChangeFinThree_tmul, baseChangeFinThree_tmul, fin_three_swap_zero_one] + simp only [map_neg] + ring + +theorem baseChangeFinThree_swap_one_two (a : M [⋀^Fin 3]→ₗ[R] R) + (x y z : S ⊗[R] M) : + baseChangeFinThree (S := S) a x y z = -baseChangeFinThree (S := S) a x z y := by + induction x using TensorProduct.inductionOn with + | add x x' hx hx' => simp [hx, hx']; abel + | tmul r x => + induction y using TensorProduct.inductionOn with + | add y y' hy hy' => simp [hy, hy']; abel + | tmul s y => + induction z using TensorProduct.inductionOn with + | add z z' hz hz' => simp [hz, hz']; abel + | tmul t z => + rw [baseChangeFinThree_tmul, baseChangeFinThree_tmul, fin_three_swap_one_two] + simp only [map_neg] + ring + +theorem baseChangeFinThree_self_zero_one (a : M [⋀^Fin 3]→ₗ[R] R) + (x z : S ⊗[R] M) : baseChangeFinThree (S := S) a x x z = 0 := by + induction x using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, LinearMap.add_apply] + rw [hx, hy, baseChangeFinThree_swap_zero_one a y x z] + abel + | tmul r x => + induction z using TensorProduct.inductionOn with + | add z z' hz hz' => simp [hz, hz'] + | tmul t z => + rw [baseChangeFinThree_tmul] + rw [a.map_eq_zero_of_eq ![x, x, z] (by rfl) (show (0 : Fin 3) ≠ 1 by decide)] + simp + +theorem baseChangeFinThree_self_one_two (a : M [⋀^Fin 3]→ₗ[R] R) + (x y : S ⊗[R] M) : baseChangeFinThree (S := S) a x y y = 0 := by + rw [baseChangeFinThree_swap_zero_one a x y y, + baseChangeFinThree_swap_one_two a y x y, + baseChangeFinThree_self_zero_one, neg_neg] + +theorem baseChangeFinThree_self_zero_two (a : M [⋀^Fin 3]→ₗ[R] R) + (x y : S ⊗[R] M) : baseChangeFinThree (S := S) a x y x = 0 := by + rw [baseChangeFinThree_swap_zero_one a x y x, + baseChangeFinThree_self_one_two, neg_zero] + +/-- Scalar extension of an alternating trilinear form. The diagonal-vanishing proof is valid in +all characteristics; in particular it does not infer alternation from skew-symmetry. -/ +noncomputable def baseChangeAlternatingFinThree (a : M [⋀^Fin 3]→ₗ[R] R) : + (S ⊗[R] M) [⋀^Fin 3]→ₗ[S] S where + toMultilinearMap := MultilinearMap.mk' (fun x ↦ + baseChangeFinThree (S := S) a (x 0) (x 1) (x 2)) + (by intro x i y z; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + (by intro x i r y; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + map_eq_zero_of_eq' x i j hij hne := by + change baseChangeFinThree (S := S) a (x 0) (x 1) (x 2) = 0 + fin_cases i <;> fin_cases j + · exact (hne rfl).elim + · have h : x 0 = x 1 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_zero_one] + · have h : x 0 = x 2 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_zero_two] + · have h : x 1 = x 0 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_zero_one] + · exact (hne rfl).elim + · have h : x 1 = x 2 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_one_two] + · have h : x 2 = x 0 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_zero_two] + · have h : x 2 = x 1 := by + convert hij using 1 <;> apply congr_arg x <;> apply Fin.ext <;> rfl + rw [h, baseChangeFinThree_self_one_two] + · exact (hne rfl).elim + +@[simp] theorem baseChangeAlternatingFinThree_tmul + (a : M [⋀^Fin 3]→ₗ[R] R) (r s t : S) (x y z : M) : + baseChangeAlternatingFinThree (S := S) a ![r ⊗ₜ[R] x, s ⊗ₜ[R] y, t ⊗ₜ[R] z] = + r * s * t * algebraMap R S (a ![x, y, z]) := + baseChangeFinThree_tmul a r s t x y z + +/-- A determinant identity between two alternating trilinear forms is preserved by scalar +extension. The equivalence `e` identifies the scalar extension of `M⁺` with the dual of the +scalar extension of `M`; its pure-tensor evaluation is stated explicitly so that this theorem +does not require freeness or projectivity. -/ +theorem baseChangeFinThree_mul_eq_det + (a : M [⋀^Fin 3]→ₗ[R] R) (d : Module.Dual R M [⋀^Fin 3]→ₗ[R] R) + (e : S ⊗[R] Module.Dual R M ≃ₗ[S] Module.Dual S (S ⊗[R] M)) + (he : ∀ (r s : S) (f : Module.Dual R M) (x : M), + e (r ⊗ₜ[R] f) (s ⊗ₜ[R] x) = r * s * algebraMap R S (f x)) + (had : ∀ (x : Fin 3 → M) (f : Fin 3 → Module.Dual R M), + a x * d f = Matrix.det (fun i j ↦ f i (x j))) + (x₀ x₁ x₂ : S ⊗[R] M) (q₀ q₁ q₂ : S ⊗[R] Module.Dual R M) : + baseChangeFinThree (S := S) a x₀ x₁ x₂ * + baseChangeFinThree (S := S) d q₀ q₁ q₂ = + Matrix.det !![e q₀ x₀, e q₀ x₁, e q₀ x₂; + e q₁ x₀, e q₁ x₁, e q₁ x₂; + e q₂ x₀, e q₂ x₁, e q₂ x₂] := by + induction x₀ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, LinearMap.add_apply, add_mul] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', Matrix.cons_val_fin_one, + Matrix.cons_val_one, Matrix.cons_val_zero, Matrix.cons_val] + ring + | tmul s₀ v₀ => + induction x₁ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, LinearMap.add_apply, add_mul] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', Matrix.cons_val_fin_one, + Matrix.cons_val_one, Matrix.cons_val_zero, Matrix.cons_val] + ring + | tmul s₁ v₁ => + induction x₂ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, add_mul] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', Matrix.cons_val_fin_one, + Matrix.cons_val_one, Matrix.cons_val_zero, Matrix.cons_val] + ring + | tmul s₂ v₂ => + induction q₀ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, LinearMap.add_apply, mul_add] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', + Matrix.cons_val_fin_one, Matrix.cons_val_one, Matrix.cons_val_zero, + Matrix.cons_val] + ring + | tmul r₀ f₀ => + induction q₁ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, LinearMap.add_apply, mul_add] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', + Matrix.cons_val_fin_one, Matrix.cons_val_one, Matrix.cons_val_zero, + Matrix.cons_val] + ring + | tmul r₁ f₁ => + induction q₂ using TensorProduct.inductionOn with + | add x y hx hy => + simp only [map_add, mul_add] + rw [hx, hy] + simp_rw [Matrix.det_fin_three] + simp [Matrix.of_apply, Matrix.cons_val', Matrix.empty_val', + Matrix.cons_val_fin_one, Matrix.cons_val_one, Matrix.cons_val_zero, + Matrix.cons_val] + ring + | tmul r₂ f₂ => + simp only [baseChangeFinThree_tmul] + have had' := had ![v₀, v₁, v₂] ![f₀, f₁, f₂] + change a ![v₀, v₁, v₂] * d ![f₀, f₁, f₂] = + Matrix.det (Matrix.of fun i j ↦ + (![f₀, f₁, f₂] i) (![v₀, v₁, v₂] j)) at had' + rw [Matrix.det_fin_three] at had' + simp only [Fin.isValue, Matrix.of_apply, Matrix.cons_val_zero, + Matrix.cons_val_one, Matrix.cons_val] at had' + have had'' := congrArg (algebraMap R S) had' + simp only [map_mul, map_sub, map_add] at had'' + rw [Matrix.det_fin_three] + simp only [Fin.isValue, Matrix.of_apply, Matrix.cons_val', + Matrix.cons_val_zero, Matrix.cons_val_fin_one, Matrix.cons_val_one, + Matrix.cons_val] + simp only [he] + calc + s₀ * s₁ * s₂ * algebraMap R S (a ![v₀, v₁, v₂]) * + (r₀ * r₁ * r₂ * algebraMap R S (d ![f₀, f₁, f₂])) = + (s₀ * s₁ * s₂ * r₀ * r₁ * r₂) * + (algebraMap R S (a ![v₀, v₁, v₂]) * + algebraMap R S (d ![f₀, f₁, f₂])) := by ring + _ = (s₀ * s₁ * s₂ * r₀ * r₁ * r₂) * + (algebraMap R S (f₀ v₀) * algebraMap R S (f₁ v₁) * + algebraMap R S (f₂ v₂) - + algebraMap R S (f₀ v₀) * algebraMap R S (f₁ v₂) * + algebraMap R S (f₂ v₁) - + algebraMap R S (f₀ v₁) * algebraMap R S (f₁ v₀) * + algebraMap R S (f₂ v₂) + + algebraMap R S (f₀ v₁) * algebraMap R S (f₁ v₂) * + algebraMap R S (f₂ v₀) + + algebraMap R S (f₀ v₂) * algebraMap R S (f₁ v₀) * + algebraMap R S (f₂ v₁) - + algebraMap R S (f₀ v₂) * algebraMap R S (f₁ v₁) * + algebraMap R S (f₂ v₀)) := by rw [had''] + _ = _ := by ring + +end AlternatingMap diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/ExteriorPower.lean b/LeanPool/CompositionAlgebrasOverRings/Module/ExteriorPower.lean new file mode 100644 index 0000000000..f2ea504a6b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/ExteriorPower.lean @@ -0,0 +1,129 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.Dual.Basis +public import Mathlib.LinearAlgebra.Dual.BaseChange +public import Mathlib.LinearAlgebra.ExteriorPower.Basis +public import Mathlib.RingTheory.TensorProduct.Basic + +/-! +# Exterior powers of finite projective modules + +This file proves the perfect-duality statement for exterior powers of projective modules, which +is missing from mathlib: for a finitely generated projective module `M`, the determinant pairing +identifies `⋀ⁿ(M*)` with `( ⋀ⁿ M )*`. This is `GPR 21.7`. + +mathlib has the finite free case (`exteriorPower.bijective_pairingDual`). For a finite projective +module, write `M` as a retract of a finite free module. Naturality of the +pairing transports the inverse across that retraction, avoiding any choice of local bases. + +## Main results + +* `exteriorPower.baseChangeLinear` : the canonical base-change map for exterior powers. +* `exteriorPower.pairingDual_naturality` : naturality of the determinant pairing. +* `exteriorPower.pairingDualEquiv` : perfect duality for every finite projective module. +* `exteriorPower.instProjective` : the exterior powers of a projective module are projective. + +## References + +* [GPR] Skip Garibaldi, Holger Petersson, and Michel Racine, *Albert Algebras over Commutative + Rings*, 21.7. +-/ + +@[expose] public section + +universe u v w + +open Function + +namespace exteriorPower + +variable {R : Type u} [CommRing R] + {M : Type v} [AddCommGroup M] [Module R M] + {N : Type w} [AddCommGroup N] [Module R N] + +/-- The canonical map from the base change of an exterior power to the exterior power of the +base-changed module. -/ +noncomputable def baseChangeLinear (S : Type w) [CommRing S] [Algebra R S] (n : ℕ) : + TensorProduct R S (⋀[R]^n M) →ₗ[S] + (⋀[S]^n (TensorProduct R S M)) := by + let altR : (TensorProduct R S M) [⋀^Fin n]→ₗ[R] + (⋀[S]^n (TensorProduct R S M)) := + { toMultilinearMap := (exteriorPower.ιMulti S n).toMultilinearMap.restrictScalars R + map_eq_zero_of_eq' := (exteriorPower.ιMulti S n).map_eq_zero_of_eq } + exact (exteriorPower.alternatingMapLinearEquiv + (altR.compLinearMap (TensorProduct.mk R S M 1))).liftBaseChange S + +@[simp] theorem baseChangeLinear_tmul_ιMulti (S : Type w) [CommRing S] [Algebra R S] + (n : ℕ) (s : S) (x : Fin n → M) : + baseChangeLinear (M := M) S n (s ⊗ₜ[R] exteriorPower.ιMulti R n x) = + s • exteriorPower.ιMulti S n (fun i ↦ 1 ⊗ₜ[R] x i) := by + simp [baseChangeLinear] + rfl + +/-- The determinant pairing on exterior powers is natural in the module. -/ +theorem pairingDual_naturality (n : ℕ) (f : M →ₗ[R] N) : + pairingDual R M n ∘ₗ map n f.dualMap = + (map n f).dualMap ∘ₗ pairingDual R N n := by + ext g v + simp + +/-- **`GPR 21.7`.** For a finitely generated projective module, the canonical determinant +pairing `⋀ⁿ(M*) → (⋀ⁿ M)*` is bijective. -/ +theorem pairingDual_bijective_of_projective [Module.Finite R M] [Module.Projective R M] + (n : ℕ) : Function.Bijective (pairingDual R M n) := by + obtain ⟨d, r, hr⟩ := Module.Finite.exists_fin' R M + obtain ⟨i, hri⟩ := r.exists_rightInverse_of_surjective (LinearMap.range_eq_top.2 hr) + let P := Fin d → R + let eP : (⋀[R]^n (Module.Dual R P)) ≃ₗ[R] Module.Dual R (⋀[R]^n P) := + LinearEquiv.ofBijective (pairingDual R P n) + (bijective_pairingDual R P n) + let inverse : Module.Dual R (⋀[R]^n M) →ₗ[R] ⋀[R]^n (Module.Dual R M) := + map n i.dualMap ∘ₗ eP.symm.toLinearMap ∘ₗ (map n r).dualMap + have hinvRight : Function.RightInverse inverse (pairingDual R M n) := by + intro F + dsimp only [inverse, LinearMap.comp_apply] + have hi := LinearMap.congr_fun (pairingDual_naturality n i) + (eP.symm ((map n r).dualMap F)) + simp only [LinearMap.comp_apply] at hi + change pairingDual R M n (map n i.dualMap + (eP.symm ((map n r).dualMap F))) = F + rw [hi] + change (map n i).dualMap (eP (eP.symm ((map n r).dualMap F))) = F + rw [eP.apply_symm_apply, ← LinearMap.comp_apply, LinearMap.dualMap_comp_dualMap, + ← map_comp, hri, map_id, LinearMap.dualMap_id, LinearMap.id_apply] + have hinvLeft : Function.LeftInverse inverse (pairingDual R M n) := by + intro x + dsimp only [inverse, LinearMap.comp_apply] + have hr' := LinearMap.congr_fun (pairingDual_naturality n r) x + simp only [LinearMap.comp_apply] at hr' + rw [← hr'] + change map n i.dualMap (eP.symm (eP (map n r.dualMap x))) = x + rw [eP.symm_apply_apply, ← LinearMap.comp_apply, ← map_comp, + LinearMap.dualMap_comp_dualMap, hri, LinearMap.dualMap_id, map_id, + LinearMap.id_apply] + exact ⟨hinvLeft.injective, hinvRight.surjective⟩ + +/-- **`GPR 21.7`.** The canonical perfect pairing between the `n`th exterior powers of a finite +projective module and its dual. -/ +noncomputable def pairingDualEquiv [Module.Finite R M] [Module.Projective R M] (n : ℕ) : + (⋀[R]^n (Module.Dual R M)) ≃ₗ[R] Module.Dual R (⋀[R]^n M) := + LinearEquiv.ofBijective (pairingDual R M n) (pairingDual_bijective_of_projective n) + +@[simp] theorem pairingDualEquiv_apply [Module.Finite R M] [Module.Projective R M] + (n : ℕ) (x : ⋀[R]^n (Module.Dual R M)) : + pairingDualEquiv (M := M) n x = pairingDual R M n x := rfl + +end exteriorPower + +/-- The exterior powers of a projective module are projective. -/ +instance exteriorPower.instProjective {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] + [Module R M] [Module.Projective R M] (n : ℕ) : Module.Projective R (⋀[R]^n M) := by + obtain ⟨s, hs⟩ := Module.projective_def'.mp ‹Module.Projective R M› + exact Module.Projective.of_split (exteriorPower.map n s) + (exteriorPower.map n (Finsupp.linearCombination R id)) + (by rw [← exteriorPower.map_comp, hs, exteriorPower.map_id]) diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentDecomposition.lean b/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentDecomposition.lean new file mode 100644 index 0000000000..7852f435ba --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentDecomposition.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.RingTheory.Idempotents +public import Mathlib.RingTheory.QuotSMulTop + +/-! +# Decomposing a module along a complete orthogonal system of idempotents + +A complete orthogonal system of idempotents `(eᵢ)` in a commutative ring `R` decomposes `R` as a +finite product of rings `R ⧸ (1 - eᵢ)` — that is mathlib's +`CompleteOrthogonalIdempotents.bijective_pi`. This file supplies the **module** analogue: the same +system decomposes every `R`-module `M` as `∏ᵢ M ⧸ (1 - eᵢ)M`, compatibly with the ring +decomposition. + +Applying this with mathlib's `QuotSMulTop.equivQuotTensor` rewrites the factors as +`(R ⧸ (1 - eᵢ)) ⊗[R] M`, which is the form in which the pieces are modules over the factor rings. + +## Main results + +* `CompleteOrthogonalIdempotents.bijective_piQuotSMulTop` : the comparison map + `M → ∏ᵢ M ⧸ (1 - eᵢ)M` is bijective. +* `CompleteOrthogonalIdempotents.linearEquivPiQuotSMulTop` : that map packaged as a linear + equivalence. +* `CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor` : the same, with the factors + written as `(R ⧸ (1 - eᵢ)) ⊗[R] M`. + +## Implementation notes + +This is a statement mathlib is missing, not a competing formulation of one it has: mathlib's +`CompleteOrthogonalIdempotents.bijective_pi` is exactly the case `M = R`, and the proof here is +the same two-line computation carried out with scalars acting on `M`. Both directions are +elementary — injectivity because `x = (∑ᵢ eᵢ) • x` and each `eᵢ • x` vanishes, surjectivity by +assembling `∑ᵢ eᵢ • xᵢ` from lifts of the components. + +The factors are `QuotSMulTop (1 - eᵢ) M`, mathlib's abbreviation for `M ⧸ (1 - eᵢ) • ⊤`, rather +than the tensor products `(R ⧸ (1 - eᵢ)) ⊗[R] M`, because the quotient form is what the proof +manipulates. `linearEquivPiQuotientTensor` converts. +-/ + +@[expose] public section + +universe u v w + +open scoped Pointwise TensorProduct + +variable {R : Type u} [CommRing R] (M : Type v) [AddCommGroup M] [Module R M] +variable {I : Type w} [Fintype I] {e : I → R} + +/-- Membership in `r • ⊤` is just divisibility by `r` in `M`. -/ +private theorem mem_smul_top_iff (r : R) (x : M) : + x ∈ r • (⊤ : Submodule R M) ↔ ∃ y : M, r • y = x := by + rw [Submodule.mem_smul_pointwise_iff_exists] + exact ⟨fun ⟨y, _, hy⟩ ↦ ⟨y, hy⟩, fun ⟨y, hy⟩ ↦ ⟨y, Submodule.mem_top, hy⟩⟩ + +variable (e) in +/-- The comparison map `M → ∏ᵢ M ⧸ (1 - eᵢ)M` attached to a family of elements of `R`. -/ +def piQuotSMulTop : M →ₗ[R] ∀ i, QuotSMulTop (1 - e i) M := + LinearMap.pi fun i ↦ Submodule.mkQ ((1 - e i) • (⊤ : Submodule R M)) + +omit [Fintype I] in +@[simp] +theorem piQuotSMulTop_apply (x : M) (i : I) : + piQuotSMulTop M e x i = Submodule.Quotient.mk x := + rfl + +/-- **A complete orthogonal system of idempotents decomposes every module.** The module analogue +of `CompleteOrthogonalIdempotents.bijective_pi`, which is the case `M = R`. -/ +theorem CompleteOrthogonalIdempotents.bijective_piQuotSMulTop + (he : CompleteOrthogonalIdempotents e) : Function.Bijective (piQuotSMulTop M e) := by + classical + constructor + · rw [injective_iff_map_eq_zero] + intro x hx + -- Each `eᵢ • x` vanishes, and the `eᵢ` sum to `1`. + have hcomp : ∀ i, e i • x = 0 := by + intro i + obtain ⟨y, hy⟩ := (mem_smul_top_iff M _ x).mp + ((Submodule.Quotient.mk_eq_zero _).mp (congrFun hx i)) + rw [← hy, smul_smul, mul_sub, mul_one, (he.idem i).eq, sub_self, zero_smul] + calc x = (∑ i, e i) • x := by rw [he.complete, one_smul] + _ = ∑ i, e i • x := Finset.sum_smul + _ = 0 := by simp [hcomp] + · intro m + choose x hx using fun i ↦ Submodule.Quotient.mk_surjective _ (m i) + refine ⟨∑ i, e i • x i, funext fun j ↦ ?_⟩ + rw [piQuotSMulTop_apply, ← hx j, Submodule.Quotient.eq] + -- `∑ᵢ eᵢ • xᵢ - xⱼ` is divisible by `1 - eⱼ`: the `i ≠ j` terms because + -- `eⱼ eᵢ = 0`, and the + -- `j`th because `eⱼ - 1 = -(1 - eⱼ)`. + have hsplit : ∑ i, e i • x i - x j = + ∑ i ∈ Finset.univ.erase j, e i • x i + (1 - e j) • (-x j) := by + rw [← Finset.sum_erase_add _ _ (Finset.mem_univ j)] + module + rw [hsplit] + refine Submodule.add_mem _ (Submodule.sum_mem _ fun i hi ↦ ?_) + (Submodule.smul_mem_pointwise_smul _ _ _ Submodule.mem_top) + refine (mem_smul_top_iff M _ _).mpr ⟨e i • x i, ?_⟩ + rw [smul_smul, sub_mul, one_mul, he.ortho (Finset.ne_of_mem_erase hi).symm, sub_zero] + +variable (e) in +/-- The decomposition of `M` along a complete orthogonal system of idempotents, +`M ≃ ∏ᵢ M ⧸ (1 - eᵢ)M`. -/ +noncomputable def CompleteOrthogonalIdempotents.linearEquivPiQuotSMulTop + (he : CompleteOrthogonalIdempotents e) : M ≃ₗ[R] ∀ i, QuotSMulTop (1 - e i) M := + LinearEquiv.ofBijective _ (he.bijective_piQuotSMulTop M) + +@[simp] +theorem CompleteOrthogonalIdempotents.linearEquivPiQuotSMulTop_apply + (he : CompleteOrthogonalIdempotents e) (x : M) (i : I) : + he.linearEquivPiQuotSMulTop M e x i = Submodule.Quotient.mk x := + rfl + +variable (e) in +/-- The decomposition of `M` with the factors written as base changes, +`M ≃ ∏ᵢ (R ⧸ (1 - eᵢ)) ⊗[R] M`. This is the form in which each factor is a module over the +corresponding factor ring of `R`. -/ +noncomputable def CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor + (he : CompleteOrthogonalIdempotents e) : + M ≃ₗ[R] ∀ i, (R ⧸ Ideal.span {1 - e i}) ⊗[R] M := + (he.linearEquivPiQuotSMulTop M e).trans + (LinearEquiv.piCongrRight fun i ↦ QuotSMulTop.equivQuotTensor (1 - e i) M) + +/-- The tensor-product module decomposition sends an element to its pure-tensor image in each +idempotent factor. -/ +@[simp] +theorem CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor_apply + (he : CompleteOrthogonalIdempotents e) (x : M) (i : I) : + he.linearEquivPiQuotientTensor M e x i = 1 ⊗ₜ[R] x := by + simp [CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor, + QuotSMulTop.equivQuotTensor] diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentFactor.lean b/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentFactor.lean new file mode 100644 index 0000000000..891fe37e18 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/IdempotentFactor.lean @@ -0,0 +1,246 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.TensorProduct.Prod +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +public import Mathlib.RingTheory.Spectrum.Prime.RingHom +public import Mathlib.RingTheory.Finiteness.Prod +public import Mathlib.RingTheory.Support +public import Mathlib.RingTheory.TensorProduct.Free + +/-! +# Modules over an idempotent factor of a ring + +For an idempotent `e` of a commutative ring `k`, the quotient `S = k ⧸ (1 - e)` is the factor of +`k` cut out by `e`, and `Spec S` is the clopen set of primes containing `1 - e`. This file +compares modules over `S` with modules over `k`. + +An `S`-module `P` is a `k`-module by restriction of scalars, and as such it is the base change of +itself (`Module.isBaseChange_self_of_surjective`): `S ⊗[k] P ≅ P`. If `P` is finitely generated +projective over `S`, it is finitely generated projective over `k`, and its rank at a prime `p` of +`k` is its rank over `S` at the corresponding prime when `1 - e ∈ p`, and `0` otherwise. + +The point is `Module.free_of_forall_free_of_isIdempotentElem`: if every finitely generated +projective `k`-module of constant rank is free, then so is every finitely generated projective +`S`-module of constant rank. A constant-rank-`r` module `P` over `S` becomes one over `k` after +adding the free module of rank `r` over the complementary factor `k ⧸ (e)`; that sum is free over +`k`, and `P` is its base change to `S`. This is the reduction used tacitly in `GPR 22.16` when the +freeness hypothesis on `k` is applied to the rank components of a composition algebra. + +## Main results + +* `Module.isBaseChange_self_of_surjective` : over a surjection `k → S`, an `S`-module is its own + base change. +* `Module.projective_of_isIdempotentElem`, `Module.finite_of_isIdempotentElem` : a finitely + generated projective module over `k ⧸ (1 - e)` is finitely generated projective over `k`. +* `Module.rankAtStalk_comap_of_isIdempotentElem`, + `Module.rankAtStalk_eq_zero_of_isIdempotentElem` : its rank over `k`. +* `Module.free_of_forall_free_of_isIdempotentElem` : freeness of constant-rank projectives passes + from `k` to its idempotent factors. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 9.31, 22.16. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace Module + +section Surjective + +variable {k : Type u} {S : Type v} [CommRing k] [CommRing S] [Algebra k S] + (hS : Function.Surjective (algebraMap k S)) + (P : Type w) [AddCommGroup P] [Module k P] [Module S P] [IsScalarTower k S P] + +include hS in +/-- Over a surjection `k → S`, an `S`-module is its own base change: `S ⊗[k] P ≅ P`, by +`a ⊗ x ↦ a • x`. Every `a ∈ S` lifts to `k`, so every tensor is of the form `1 ⊗ x`. -/ +theorem isBaseChange_self_of_surjective : + IsBaseChange S ((LinearMap.id : P →ₗ[S] P).restrictScalars k) := by + refine IsBaseChange.of_lift_unique _ fun Q _ _ _ _ g ↦ ?_ + -- A `k`-linear map out of an `S`-module is `S`-linear, since every scalar of `S` lifts to `k`. + let g' : P →ₗ[S] Q := + { toFun := g + map_add' := g.map_add + map_smul' := fun a x ↦ by + obtain ⟨b, rfl⟩ := hS a + rw [algebraMap_smul, g.map_smul, RingHom.id_apply, algebraMap_smul] } + refine ⟨g', LinearMap.ext fun _ ↦ rfl, fun g'' hg'' ↦ LinearMap.ext fun x ↦ ?_⟩ + exact LinearMap.congr_fun hg'' x + +end Surjective + +section Idempotent + +variable {k : Type u} [CommRing k] {e : k} (he : IsIdempotentElem e) + +/-- In `k ⧸ (1 - e)` the element `e` becomes `1`. -/ +theorem algebraMap_quotient_one_sub_self : + algebraMap k (k ⧸ Ideal.span {1 - e}) e = 1 := by + rw [Ideal.Quotient.algebraMap_eq, ← map_one (Ideal.Quotient.mk _), Ideal.Quotient.eq, + show e - 1 = -(1 - e) by ring] + exact Submodule.neg_mem _ (Ideal.mem_span_singleton_self _) + +include he in +/-- The factor `k ⧸ (1 - e)` is a direct summand of `k`: the class of `x` ↦ `e x` splits the +quotient map. -/ +theorem projective_quotient_one_sub : + Module.Projective k (k ⧸ Ideal.span {1 - e}) := by + let I : Ideal k := Ideal.span {1 - e} + have hle : I ≤ LinearMap.ker (LinearMap.mulLeft k e) := by + rw [Ideal.span_le, Set.singleton_subset_iff, SetLike.mem_coe, LinearMap.mem_ker, + LinearMap.mulLeft_apply, mul_sub, mul_one, he.eq, sub_self] + refine Module.Projective.of_split (M := k) (I.liftQ (LinearMap.mulLeft k e) hle) I.mkQ ?_ + refine Submodule.linearMap_qext _ (LinearMap.ext fun x ↦ ?_) + simp only [LinearMap.coe_comp, Function.comp_apply, Submodule.mkQ_apply, Submodule.liftQ_apply, + LinearMap.mulLeft_apply, LinearMap.id_comp] + rw [Submodule.Quotient.eq, ← sub_one_mul, ← neg_sub, neg_mul] + exact I.neg_mem (I.mul_mem_right x (Ideal.mem_span_singleton_self _)) + +variable (P : Type w) [AddCommGroup P] [Module (k ⧸ Ideal.span {1 - e}) P] [Module k P] + [IsScalarTower k (k ⧸ Ideal.span {1 - e}) P] + +include he in +/-- A projective module over the factor `k ⧸ (1 - e)` is projective over `k`. -/ +theorem projective_of_isIdempotentElem [Module.Projective (k ⧸ Ideal.span {1 - e}) P] : + Module.Projective k P := by + classical + have := projective_quotient_one_sub he + have : Module.Projective k (P →₀ (k ⧸ Ideal.span {1 - e})) := + Module.Projective.of_equiv' (finsuppLequivDFinsupp k).symm + obtain ⟨s, hs⟩ := ‹Module.Projective (k ⧸ Ideal.span {1 - e}) P›.out + exact Module.Projective.of_split (s.restrictScalars k) + ((Finsupp.linearCombination _ id).restrictScalars k) (LinearMap.ext hs) + +/-- A finitely generated module over the factor `k ⧸ (1 - e)` is finitely generated over `k`. -/ +theorem finite_of_isIdempotentElem [Module.Finite (k ⧸ Ideal.span {1 - e}) P] : + Module.Finite k P := + Module.Finite.trans (k ⧸ Ideal.span {1 - e}) P + +variable [Module.Finite (k ⧸ Ideal.span {1 - e}) P] [Module.Projective (k ⧸ Ideal.span {1 - e}) P] + +include he in +/-- At a prime of `k` containing `1 - e`, the rank of a finitely generated projective module over +`k ⧸ (1 - e)` is its rank over the factor. -/ +theorem rankAtStalk_comap_of_isIdempotentElem (q : PrimeSpectrum (k ⧸ Ideal.span {1 - e})) : + rankAtStalk (R := k) P (q.comap (algebraMap k (k ⧸ Ideal.span {1 - e}))) = + rankAtStalk (R := k ⧸ Ideal.span {1 - e}) P q := by + have := projective_of_isIdempotentElem he P + have := finite_of_isIdempotentElem (e := e) P + exact (rankAtStalk_isBaseChange + (isBaseChange_self_of_surjective Ideal.Quotient.mk_surjective P) q).symm + +include he in +/-- At a prime of `k` not containing `1 - e`, a finitely generated projective module over +`k ⧸ (1 - e)` has rank zero: `1 - e` kills it and is a unit there. -/ +theorem rankAtStalk_eq_zero_of_isIdempotentElem (p : PrimeSpectrum k) + (hp : 1 - e ∉ p.asIdeal) : rankAtStalk (R := k) P p = 0 := by + have := projective_of_isIdempotentElem he P + have := finite_of_isIdempotentElem (e := e) P + rw [rankAtStalk_eq_zero_iff_notMem_support, Module.mem_support_iff_of_finite] + refine fun h ↦ hp (h (Module.mem_annihilator.mpr fun x ↦ ?_)) + rw [← algebraMap_smul (k ⧸ Ideal.span {1 - e}), Ideal.Quotient.algebraMap_eq, + Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.mem_span_singleton_self _), zero_smul] + +omit [Module.Finite (k ⧸ Ideal.span {1 - e}) P] [Module.Projective (k ⧸ Ideal.span {1 - e}) P] + [Module k P] [IsScalarTower k (k ⧸ Ideal.span {1 - e}) P] in +include he in +/-- **Freeness passes to idempotent factors.** If every finitely generated projective `k`-module of +constant rank is free, so is every finitely generated projective module of constant rank over the +factor `k ⧸ (1 - e)`. + +A module `P` of constant rank `r` over `k ⧸ (1 - e)` is, as a `k`-module, of rank `r` on the primes +containing `1 - e` and of rank `0` on the others; adding the free module of rank `r` over the +complementary factor `k ⧸ (e)` gives a `k`-module `N` of constant rank `r`. `N` is free by +hypothesis, hence so is its base change to `k ⧸ (1 - e)`, which is `P`. -/ +theorem free_of_forall_free_of_isIdempotentElem + (hfree : ∀ (N : Type (max u w)) [AddCommGroup N] [Module k N] [Module.Finite k N] + [Module.Projective k N] (r : ℕ), rankAtStalk (R := k) N = (fun _ ↦ r) → Module.Free k N) + (P : Type (max u w)) [AddCommGroup P] [Module (k ⧸ Ideal.span {1 - e}) P] + [Module.Finite (k ⧸ Ideal.span {1 - e}) P] [Module.Projective (k ⧸ Ideal.span {1 - e}) P] + (r : ℕ) (hP : rankAtStalk (R := k ⧸ Ideal.span {1 - e}) P = fun _ ↦ r) : + Module.Free (k ⧸ Ideal.span {1 - e}) P := by + set S := k ⧸ Ideal.span {1 - e} + set S' := k ⧸ Ideal.span {1 - (1 - e)} + have he' : IsIdempotentElem (1 - e) := he.one_sub + let : Module k P := Module.compHom P (algebraMap k S) + have : IsScalarTower k S P := + ⟨fun a b x ↦ by + change (a • b) • x = algebraMap k S a • (b • x) + rw [Algebra.smul_def, mul_smul]⟩ + have := projective_of_isIdempotentElem he P + have := finite_of_isIdempotentElem (e := e) P + have := projective_of_isIdempotentElem he' (Fin r → S') + have := finite_of_isIdempotentElem (e := 1 - e) (Fin r → S') + -- The padded module has constant rank `r` over `k`. + have hN : rankAtStalk (R := k) (P × (Fin r → S')) = fun _ ↦ r := by + funext p + rw [rankAtStalk_prod, Pi.add_apply] + by_cases h : 1 - e ∈ p.asIdeal + · obtain ⟨q, rfl⟩ : p ∈ Set.range (PrimeSpectrum.comap (algebraMap k S)) := by + change p ∈ Set.range (PrimeSpectrum.comap (Ideal.Quotient.mk (Ideal.span {1 - e}))) + rw [range_comap_of_surjective _ _ Ideal.Quotient.mk_surjective, + PrimeSpectrum.mem_zeroLocus, Ideal.mk_ker, + SetLike.coe_subset_coe, Ideal.span_le, Set.singleton_subset_iff] + exact h + rw [rankAtStalk_comap_of_isIdempotentElem he P q, hP, + rankAtStalk_eq_zero_of_isIdempotentElem he' (Fin r → S') _ ?_, add_zero] + rw [sub_sub_cancel] + intro he₀ + have : (1 : k) ∈ (q.comap (algebraMap k S)).asIdeal := by + simpa using Ideal.add_mem _ h he₀ + exact (q.comap (algebraMap k S)).isPrime.ne_top ((Ideal.eq_top_iff_one _).mpr this) + · have he₀ : 1 - (1 - e) ∈ p.asIdeal := by + rw [sub_sub_cancel] + refine (p.isPrime.mem_or_mem ?_).resolve_right h + rw [he.mul_one_sub_self] + exact p.asIdeal.zero_mem + obtain ⟨q, rfl⟩ : p ∈ Set.range (PrimeSpectrum.comap (algebraMap k S')) := by + change p ∈ Set.range + (PrimeSpectrum.comap (Ideal.Quotient.mk (Ideal.span {1 - (1 - e)}))) + rw [range_comap_of_surjective _ _ Ideal.Quotient.mk_surjective, + PrimeSpectrum.mem_zeroLocus, Ideal.mk_ker, + SetLike.coe_subset_coe, Ideal.span_le, Set.singleton_subset_iff] + exact he₀ + have : Nontrivial S' := Ideal.Quotient.nontrivial_iff.mpr fun htop ↦ + (q.comap (algebraMap k S')).isPrime.ne_top + (top_le_iff.mp (htop ▸ Ideal.span_le.mpr (Set.singleton_subset_iff.mpr he₀))) + rw [rankAtStalk_eq_zero_of_isIdempotentElem he P _ h, + rankAtStalk_comap_of_isIdempotentElem he' (Fin r → S') q, + rankAtStalk_eq_finrank_of_free, Module.finrank_fin_fun, zero_add] + rfl + have := hfree (P × (Fin r → S')) r hN + -- The base change of the padding to `k ⧸ (1 - e)` vanishes: `e` acts as `1` there, as `0` on it. + have hzero : Subsingleton (S ⊗[k] (Fin r → S')) := by + refine subsingleton_of_forall_eq 0 fun t ↦ ?_ + induction t using TensorProduct.inductionOn with + | tmul a f => + have hf : e • f = 0 := by + funext i + rw [Pi.smul_apply, Pi.zero_apply, Algebra.smul_def, + show algebraMap k S' e = 0 by + rw [Ideal.Quotient.algebraMap_eq, Ideal.Quotient.eq_zero_iff_mem] + rw [show (1 : k) - (1 - e) = e from sub_sub_cancel 1 e] + exact Ideal.mem_span_singleton_self _, + zero_mul] + rw [← one_smul S a, ← algebraMap_quotient_one_sub_self (e := e), algebraMap_smul, + TensorProduct.smul_tmul, hf, TensorProduct.tmul_zero] + | add x y hx hy => rw [hx, hy, add_zero] + let : Unique (S ⊗[k] (Fin r → S')) := uniqueOfSubsingleton 0 + let φ : S ⊗[k] (P × (Fin r → S')) ≃ₗ[S] P := + TensorProduct.prodRight k S S P (Fin r → S') ≪≫ₗ LinearEquiv.prodUnique ≪≫ₗ + (isBaseChange_self_of_surjective Ideal.Quotient.mk_surjective P).equiv + exact Module.Free.of_equiv φ + +end Idempotent + +end Module diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean b/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean new file mode 100644 index 0000000000..cca419791c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean @@ -0,0 +1,309 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.RingTheory.LocalProperties.Submodule +public import Mathlib.RingTheory.PicardGroup +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +public import Mathlib.LinearAlgebra.BilinearForm.TensorProduct + +/-! +# Invertible modules and line bundles + +This file proves the standard characterization of invertible modules as finite locally free +modules of rank one. This fills the corresponding TODO in mathlib's +`Mathlib/RingTheory/PicardGroup.lean`. + +## Main definitions + +* `Module.IsLocallyFreeRankOne R M`: `M` is finite projective and has rank one at every stalk. +* `Module.IsRankOnePairing R M`: the rank-one identity for the evaluation pairing. + +## Main results + +* `Module.invertible_iff_isLocallyFreeRankOne`: invertible modules are exactly the finite locally + free modules of rank one. +* `Module.IsLocallyFreeRankOne.isRankOnePairing`: a line bundle satisfies the rank-one pairing + identity. +* `Module.IsLocallyFreeRankOne.bilinMap_eq_zero_of_map_self_eq_zero`: an alternating bilinear + map out of a line bundle vanishes. +* `Module.isRankOnePairing_of_invertible`: the pairing identity for mathlib's invertible modules. + +## Proof idea + +For the converse, choose a finite dual frame `mᵢ, φᵢ` for the projective module. Rank one at +every stalk gives the identity `φ(x)ψ(y) = φ(y)ψ(x)`. The trace of the frame is one, and +consequently every elementary tensor satisfies + +`φ ⊗ x = φ(x) • ∑ᵢ φᵢ ⊗ mᵢ`. + +Thus contraction with the evaluation pairing is bijective, which is precisely mathlib's +definition of `Module.Invertible`. + +## References + +* [Stacks, Tag 00NX] The Stacks Project, *Finite projective modules*. +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +namespace Module + +variable (R : Type u) [CommRing R] (M : Type v) [AddCommGroup M] [Module R M] + +/-- An `R`-module is **locally free of rank one** if it is finite projective and its localization +at every prime has rank one. + +The finite-projective clauses are the algebraic form of finite local freeness; the stalk rank is +mathlib's `Module.rankAtStalk`. -/ +def IsLocallyFreeRankOne : Prop := + Module.Finite R M ∧ Module.Projective R M ∧ Module.rankAtStalk (R := R) M = 1 + +/-- The evaluation pairing of `M` has the **rank-one pairing identity** if +`φ(x) ψ(y) = φ(y) ψ(x)` for all functionals and vectors. -/ +def IsRankOnePairing : Prop := + ∀ (φ ψ : Module.Dual R M) (x y : M), φ x * ψ y = φ y * ψ x + +variable {R M} + +/-- A module isomorphic to the base ring has the rank-one pairing identity. -/ +theorem isRankOnePairing_of_linearEquiv (e : M ≃ₗ[R] R) : IsRankOnePairing R M := by + intro φ ψ x y + have hx : ∀ z : M, z = e z • e.symm 1 := fun z ↦ by + rw [← map_smul, smul_eq_mul, mul_one, e.symm_apply_apply] + rw [hx x, hx y, map_smul, map_smul, map_smul, map_smul] + ring + +/-- The base ring itself has the rank-one pairing identity. -/ +theorem isRankOnePairing_self : IsRankOnePairing R R := + isRankOnePairing_of_linearEquiv (LinearEquiv.refl R R) + +private theorem isRankOnePairing_of_finite_projective_of_rankAtStalk_eq_one + [Module.Finite R M] [Module.Projective R M] + (hrank : Module.rankAtStalk (R := R) M = 1) : + IsRankOnePairing R M := by + intro φ ψ x y + let A (P : Ideal R) [P.IsMaximal] := Localization.AtPrime P + let MP (P : Ideal R) [P.IsMaximal] := LocalizedModule P.primeCompl M + let j (P : Ideal R) [P.IsMaximal] : M →ₗ[R] MP P := + LocalizedModule.mkLinearMap P.primeCompl M + apply Module.eq_of_localization_maximal (fun P _ ↦ A P) (fun P _ ↦ Algebra.linearMap R (A P)) + intro P hP + let φP : Module.Dual (A P) (MP P) := + (IsLocalizedModule.map P.primeCompl (j P) + (Algebra.linearMap R (A P)) φ).extendScalarsOfIsLocalization P.primeCompl (A P) + let ψP : Module.Dual (A P) (MP P) := + (IsLocalizedModule.map P.primeCompl (j P) + (Algebra.linearMap R (A P)) ψ).extendScalarsOfIsLocalization P.primeCompl (A P) + have hfinrank : Module.finrank (A P) (MP P) = 1 := by + simpa [Module.rankAtStalk] using congrFun hrank ⟨P, hP.isPrime⟩ + let : Module.Free (A P) (MP P) := Module.free_of_flat_of_isLocalRing + let e : A P ≃ₗ[A P] MP P := (Module.nonempty_linearEquiv_of_finrank_eq_one hfinrank).some + have hpair := isRankOnePairing_of_linearEquiv e.symm φP ψP (j P x) (j P y) + simpa [φP, ψP, j, map_mul] using hpair + +/-- A finite locally free module of rank one has the rank-one pairing identity. -/ +theorem IsLocallyFreeRankOne.isRankOnePairing (h : IsLocallyFreeRankOne R M) : + IsRankOnePairing R M := by + let : Module.Finite R M := h.1 + let : Module.Projective R M := h.2.1 + exact isRankOnePairing_of_finite_projective_of_rankAtStalk_eq_one h.2.2 + +-- Extension of scalars preserves the condition that a bilinear map vanishes on the diagonal. +private theorem bilinMap_baseChange_apply_self_eq_zero + {S : Type*} [CommRing S] [Algebra R S] + {N : Type*} [AddCommGroup N] [Module R N] + (B : LinearMap.BilinMap R M N) (hB : ∀ x, B x x = 0) + (z : S ⊗[R] M) : B.baseChange S z z = 0 := by + -- The skew-symmetry of the base-changed map is an equality of bilinear maps, so it is enough + -- to check it on elementary tensors on both sides. + have hkey : ((B.baseChange S) + (B.baseChange S).flip).restrictScalars R = 0 := + TensorProduct.ext' fun a m ↦ by + apply LinearMap.restrictScalars_injective R + refine TensorProduct.ext' fun b n ↦ ?_ + change (a * b) ⊗ₜ[R] B m n + (b * a) ⊗ₜ[R] B n m = 0 + rw [mul_comm b a, ← TensorProduct.tmul_add, ← LinearMap.IsAlt.neg hB m n, + add_neg_cancel, TensorProduct.tmul_zero] + have hskewS (x y : S ⊗[R] M) : B.baseChange S x y + B.baseChange S y x = 0 := + DFunLike.congr_fun (DFunLike.congr_fun hkey x) y + induction z using TensorProduct.inductionOn with + | add x y hx hy => + rw [((B.baseChange S) (x + y)).map_add, (B.baseChange S).map_add, + LinearMap.add_apply, LinearMap.add_apply, hx, hy] + simpa only [zero_add, add_zero, add_comm] using hskewS x y + | tmul a m => + change (a * a) ⊗ₜ[R] B m m = 0 + rw [hB, TensorProduct.tmul_zero] + +/-- Every alternating bilinear map out of a line bundle vanishes. Equivalently, the second +exterior power of a line bundle is zero. -/ +theorem IsLocallyFreeRankOne.bilinMap_eq_zero_of_map_self_eq_zero + {N : Type*} [AddCommGroup N] [Module R N] (h : IsLocallyFreeRankOne R M) + (B : LinearMap.BilinMap R M N) (hB : ∀ x, B x x = 0) : B = 0 := by + let : Module.Finite R M := h.1 + let : Module.Projective R M := h.2.1 + ext x y + let A (P : Ideal R) [P.IsMaximal] := Localization.AtPrime P + let T (P : Ideal R) [P.IsMaximal] := A P ⊗[R] M + let U (P : Ideal R) [P.IsMaximal] := A P ⊗[R] N + let jN (P : Ideal R) [P.IsMaximal] : N →ₗ[R] U P := TensorProduct.mk R (A P) N 1 + apply Module.eq_zero_of_localization_maximal (fun P _ ↦ U P) (fun P _ ↦ jN P) (B x y) + intro P hP + let BA : LinearMap.BilinMap (A P) (T P) (U P) := B.baseChange (A P) + have hdiagA (z : T P) : BA z z = 0 := + bilinMap_baseChange_apply_self_eq_zero B hB z + have hfinrank : Module.finrank (A P) (T P) = 1 := by + calc + Module.finrank (A P) (T P) = + Module.rankAtStalk (R := R) M ⟨P, hP.isPrime⟩ := + (Module.rankAtStalk_eq_finrank_tensorProduct + (R := R) (M := M) ⟨P, hP.isPrime⟩).symm + _ = 1 := congrFun h.2.2 ⟨P, hP.isPrime⟩ + let : Module.Free (A P) (T P) := Module.free_of_flat_of_isLocalRing + let e : A P ≃ₗ[A P] T P := (Module.nonempty_linearEquiv_of_finrank_eq_one hfinrank).some + have he (z : T P) : z = e.symm z • e 1 := by + rw [← map_smul, smul_eq_mul, mul_one, e.apply_symm_apply] + change (1 : A P) ⊗ₜ[R] B x y = 0 + calc + (1 : A P) ⊗ₜ[R] B x y = + (1 * 1 : A P) ⊗ₜ[R] B x y := by rw [one_mul] + _ = BA ((1 : A P) ⊗ₜ[R] x) ((1 : A P) ⊗ₜ[R] y) := + (LinearMap.BilinMap.baseChange_tmul B 1 x 1 y).symm + _ = 0 := by + rw [he ((1 : A P) ⊗ₜ[R] x), he ((1 : A P) ⊗ₜ[R] y), + LinearMap.map_smul₂, map_smul, hdiagA] + simp + +-- The trace of a finite dual frame on a rank-one projective module is one. This isolates the +-- localization argument used to construct the inverse of the contraction pairing below. +private theorem sum_dual_frame_apply_eq_one_of_rankAtStalk_eq_one + [Module.Finite R M] [Module.Projective R M] + (hrank : Module.rankAtStalk (R := R) M = 1) {n : ℕ} + (φ : Fin n → Module.Dual R M) (m : Fin n → M) + (hframe : ∀ x, ∑ i, φ i x • m i = x) : ∑ i, φ i (m i) = 1 := by + let A (P : Ideal R) [P.IsMaximal] := Localization.AtPrime P + let MP (P : Ideal R) [P.IsMaximal] := LocalizedModule P.primeCompl M + let j (P : Ideal R) [P.IsMaximal] : M →ₗ[R] MP P := + LocalizedModule.mkLinearMap P.primeCompl M + apply Module.eq_of_localization_maximal (fun P _ ↦ A P) + (fun P _ ↦ Algebra.linearMap R (A P)) + intro P hP + let φP (i : Fin n) : Module.Dual (A P) (MP P) := + (IsLocalizedModule.map P.primeCompl (j P) (Algebra.linearMap R (A P)) + (φ i)).extendScalarsOfIsLocalization P.primeCompl (A P) + have hfinrank : Module.finrank (A P) (MP P) = 1 := by + simpa [Module.rankAtStalk] using congrFun hrank ⟨P, hP.isPrime⟩ + let : Module.Free (A P) (MP P) := Module.free_of_flat_of_isLocalRing + let e : A P ≃ₗ[A P] MP P := + (Module.nonempty_linearEquiv_of_finrank_eq_one hfinrank).some + have hframeP : + (∑ i, (φP i).smulRight (j P (m i))) = LinearMap.id := by + apply LinearMap.restrictScalars_injective R + apply IsLocalizedModule.linearMap_ext P.primeCompl (j P) (j P) + ext x + simp only [LinearMap.coe_comp, Function.comp_apply, LinearMap.coe_restrictScalars, + LinearMap.sum_apply, LinearMap.smulRight_apply, LinearMap.id_apply, φP, + LinearMap.extendScalarsOfIsLocalization_apply', IsLocalizedModule.map_apply] + simpa only [map_sum, map_smul, Algebra.linearMap_apply, + IsScalarTower.algebraMap_smul] using congrArg (j P) (hframe x) + have hsum : ∑ i, φP i (e 1) * e.symm (j P (m i)) = 1 := by + calc + ∑ i, φP i (e 1) * e.symm (j P (m i)) = + e.symm (∑ i, φP i (e 1) • j P (m i)) := by + simp only [map_sum, map_smul, smul_eq_mul] + _ = e.symm (e 1) := by + have hx := DFunLike.congr_fun hframeP (e 1) + simp only [LinearMap.sum_apply, LinearMap.smulRight_apply, LinearMap.id_apply] at hx + rw [hx] + _ = 1 := e.symm_apply_apply 1 + have hpairP := isRankOnePairing_of_linearEquiv e.symm + have hsum' : ∑ i, φP i (j P (m i)) = 1 := by + calc + ∑ i, φP i (j P (m i)) = + ∑ i, φP i (e 1) * e.symm (j P (m i)) := + Finset.sum_congr rfl fun i _ ↦ by + simpa using (hpairP (φP i) e.symm (e 1) (j P (m i))).symm + _ = 1 := hsum + rw [map_sum] + convert hsum' using 1 <;> + simp only [φP, Algebra.linearMap_apply, map_one, + LinearMap.extendScalarsOfIsLocalization_apply', IsLocalizedModule.map_apply] + +private theorem invertible_of_finite_projective_of_rankAtStalk_eq_one + [Module.Finite R M] [Module.Projective R M] + (hrank : Module.rankAtStalk (R := R) M = 1) : Module.Invertible R M := by + classical + let hpair := isRankOnePairing_of_finite_projective_of_rankAtStalk_eq_one hrank + obtain ⟨n, f, g, -, -, hfg⟩ := Module.Finite.exists_comp_eq_id_of_projective R M + let b := Pi.basisFun R (Fin n) + let φ (i : Fin n) : Module.Dual R M := b.coord i ∘ₗ g + let m (i : Fin n) : M := f (b i) + have hframe (x : M) : ∑ i, φ i x • m i = x := by + calc + ∑ i, φ i x • m i = f (∑ i, (b.repr (g x) i) • b i) := by + simp only [map_sum, map_smul, φ, m, LinearMap.coe_comp, Function.comp_apply, + Basis.coord_apply] + _ = f (g x) := by rw [b.sum_repr] + _ = x := by + simpa only [LinearMap.coe_comp, Function.comp_apply, LinearMap.id_apply] using + DFunLike.congr_fun hfg x + have htrace : ∑ i, φ i (m i) = 1 := + sum_dual_frame_apply_eq_one_of_rankAtStalk_eq_one hrank φ m hframe + let z : Module.Dual R M ⊗[R] M := ∑ i, φ i ⊗ₜ[R] m i + have hcontract : contractLeft R M z = 1 := by + simpa only [z, map_sum, contractLeft_apply] using htrace + have htensor (ψ : Module.Dual R M) (x : M) : ψ ⊗ₜ[R] x = ψ x • z := by + calc + ψ ⊗ₜ[R] x = ψ ⊗ₜ[R] (∑ i, φ i x • m i) := by rw [hframe] + _ = ∑ i, (φ i x • ψ) ⊗ₜ[R] m i := by + rw [TensorProduct.tmul_sum] + exact Finset.sum_congr rfl fun i _ ↦ (TensorProduct.smul_tmul _ _ _).symm + _ = ∑ i, (ψ x • φ i) ⊗ₜ[R] m i := + Finset.sum_congr rfl fun i _ ↦ by + congr 1 + ext y + simp only [LinearMap.smul_apply, smul_eq_mul] + exact (hpair (φ i) ψ x y).trans (mul_comm _ _) + _ = ψ x • z := by + simp only [z, Finset.smul_sum] + exact Finset.sum_congr rfl fun i _ ↦ (TensorProduct.smul_tmul' _ _ _).symm + have hreconstruct (w : Module.Dual R M ⊗[R] M) : w = contractLeft R M w • z := by + induction w using TensorProduct.inductionOn with + | add x y hx hy => rw [map_add, add_smul, ← hx, ← hy] + | tmul ψ x => exact htensor ψ x + refine ⟨?_, ?_⟩ + · intro x y hxy + rw [hreconstruct x, hreconstruct y, hxy] + · intro r + refine ⟨r • z, ?_⟩ + simp only [map_smul, hcontract, smul_eq_mul, mul_one] + +/-- An `R`-module is invertible if and only if it is finite locally free of rank one. + +This is the module-theoretic characterization of line bundles; see +[Stacks, Tag 00NX](https://stacks.math.columbia.edu/tag/00NX). -/ +theorem invertible_iff_isLocallyFreeRankOne : + Module.Invertible R M ↔ IsLocallyFreeRankOne R M := by + constructor + · intro h + let : Module.Invertible R M := h + refine ⟨inferInstance, inferInstance, funext fun P ↦ ?_⟩ + simpa only [Module.rankAtStalk, Pi.one_apply] using Module.Invertible.finrank_eq_one + (Localization.AtPrime P.asIdeal) (LocalizedModule P.asIdeal.primeCompl M) + · rintro ⟨hfinite, hprojective, hrank⟩ + let : Module.Finite R M := hfinite + let : Module.Projective R M := hprojective + exact invertible_of_finite_projective_of_rankAtStalk_eq_one hrank + +/-- An invertible module satisfies the rank-one identity for its evaluation pairing. -/ +theorem isRankOnePairing_of_invertible [Module.Invertible R M] : IsRankOnePairing R M := + (invertible_iff_isLocallyFreeRankOne.mp inferInstance).isRankOnePairing + +end Module diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/RankDecomposition.lean b/LeanPool/CompositionAlgebrasOverRings/Module/RankDecomposition.lean new file mode 100644 index 0000000000..c7e5aec1cd --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/RankDecomposition.lean @@ -0,0 +1,438 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Module.IdempotentDecomposition +public import Mathlib.LinearAlgebra.TensorProduct.Quotient +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +public import Mathlib.RingTheory.Spectrum.Prime.RingHom + +/-! +# The rank decomposition of a finitely generated projective module (`GPR Exc. 9.31`) + +A finitely generated projective module `M` over a commutative ring `R` takes only finitely many +ranks, and `R` splits — uniquely — into a finite product of rings on each factor of which `M` +becomes of constant rank. + +This is the tool that lets constant-rank hypotheses be assumed without loss of generality: `GPR` +uses it repeatedly, in the form "by the rank decomposition we may assume `M` (or the composition +algebra `C`) has constant rank `r`". + +## Main definitions + +* `Module.rankIdempotent R M i` : the unique idempotent of `R` cutting out + `{p ∈ Spec R | rankAtStalk M p = i}`. + +## Main results + +* `Module.finite_range_rankAtStalk` : **`GPR Exc. 9.31(a)`** — the set of ranks of `M` is finite. +* `Module.completeOrthogonalIdempotents_rankIdempotent` : the `rankIdempotent R M i`, for `i` + ranging over any finite set containing all the ranks, form a complete orthogonal system of + idempotents. With `CompleteOrthogonalIdempotents.bijective_pi` this is the ring decomposition + `R ≃ ∏ᵢ R ⧸ (1 - εᵢ)` of **`GPR Exc. 9.31(b)`**(1), and with + `CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor` + (`Module/IdempotentDecomposition.lean`) the module decomposition (2). +* `Module.rankAtStalk_quotientTensor_rankIdempotent` : on the `i`th factor, `M` has constant + rank `i`. This is the point of the whole construction. +* `Module.rankAtStalk_baseChange_of_eq` : constant rank survives base change. +* `Module.nonempty_basis_atPrime_of_rankAtStalk_eq` : a module of constant rank `n` is free of + rank `n` at every prime. +* `Module.eq_rankIdempotent_of_completeOrthogonalIdempotents` : **uniqueness** — any complete + orthogonal system with pairwise distinct constant ranks on its factors is the one above. + +## Proof idea + +`Module.rankAtStalk` is locally constant on `Spec R` for a finitely presented flat module +(mathlib's `Module.isLocallyConstant_rankAtStalk`), and `Spec R` is quasi-compact, so the range is +finite — that is (a). Each fibre `Uᵢ := {p | rankAtStalk M p = i}` is then clopen, so by +`GPR Exc. 9.29` — mathlib's `PrimeSpectrum.existsUnique_idempotent_basicOpen_eq_of_isClopen` — +there is a unique idempotent `εᵢ` with `D(εᵢ) = Uᵢ`. Orthogonality and completeness are read off +from the fact that the `Uᵢ` partition `Spec R`, via the observation that an idempotent whose +basic open set is empty is nilpotent, hence zero. + +That the `i`th factor has constant rank `i` is `Module.rankAtStalk_baseChange`: a prime of +`R ⧸ (1 - εᵢ)` pulls back to a prime of `R` at which `εᵢ` is a unit — indeed `εᵢ ↦ 1` — hence to +a point of `D(εᵢ) = Uᵢ`. + +Uniqueness follows because a competing system's basic opens are contained in the corresponding +`Uᵢ` (same base-change computation, in the other direction, using that `Spec (R ⧸ (1 - ηⱼ))` +surjects onto `D(ηⱼ)`) and both families cover `Spec R`. + +## Implementation notes + +`GPR` indexes the decomposition by all of `ℕ`, with `εᵢ = 0` for `i` outside the (finite) set of +ranks. `Module.rankIdempotent` is likewise defined for every `i : ℕ` and is `0` off the range +(`Module.rankIdempotent_eq_zero_of_notMem_range`), but the complete-orthogonal-system statement is +indexed by a `Finset ℕ` containing the ranks, since mathlib's `CompleteOrthogonalIdempotents` +requires a `Fintype`. + +The rank is mathlib's `Module.rankAtStalk`, not a bespoke rank function; `GPR` writes `rk_p(M)` +for the same thing. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 9.29, + Exc. 9.31. +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +open PrimeSpectrum + +variable (R : Type u) [CommRing R] (M : Type v) [AddCommGroup M] [Module R M] + [Module.Finite R M] [Module.Projective R M] + +/-- An idempotent whose basic open set is empty is zero: it is nilpotent, and a nilpotent +idempotent vanishes. This is how orthogonality and completeness of the rank idempotents get +proved — both reduce to a basic open set being empty. -/ +private theorem eq_zero_of_isIdempotentElem_of_basicOpen_eq_bot {S : Type u} [CommRing S] {e : S} + (he : IsIdempotentElem e) (h : basicOpen e = ⊥) : e = 0 := + he.eq_zero_of_isNilpotent ((basicOpen_eq_bot_iff e).mp h) + +/-- **`GPR Exc. 9.31(a)`.** A finitely generated projective module takes only finitely many ranks. + +`Module.rankAtStalk` is locally constant and `Spec R` is quasi-compact. -/ +theorem Module.finite_range_rankAtStalk : + (Set.range (Module.rankAtStalk (R := R) M)).Finite := by + have : Module.FinitePresentation R M := Module.finitePresentation_of_projective R M + exact (Module.isLocallyConstant_rankAtStalk (R := R) (M := M)).range_finite + +/-- The locus where `M` has rank `i` is clopen. -/ +theorem Module.isClopen_setOf_rankAtStalk_eq (i : ℕ) : + IsClopen {p : PrimeSpectrum R | Module.rankAtStalk (R := R) M p = i} := by + have : Module.FinitePresentation R M := Module.finitePresentation_of_projective R M + exact (Module.isLocallyConstant_rankAtStalk (R := R) (M := M)).isClopen_fiber i + +/-- The idempotent of `R` cutting out the locus where `M` has rank `i` (`GPR Exc. 9.31(b)`, +`GPR Exc. 9.29`). It is `0` exactly when `M` has rank `i` nowhere. -/ +noncomputable def Module.rankIdempotent (i : ℕ) : R := + (PrimeSpectrum.exists_idempotent_basicOpen_eq_of_isClopen + (Module.isClopen_setOf_rankAtStalk_eq R M i)).choose + +theorem Module.isIdempotentElem_rankIdempotent (i : ℕ) : + IsIdempotentElem (Module.rankIdempotent R M i) := + (PrimeSpectrum.exists_idempotent_basicOpen_eq_of_isClopen + (Module.isClopen_setOf_rankAtStalk_eq R M i)).choose_spec.1 + +theorem Module.coe_basicOpen_rankIdempotent (i : ℕ) : + (basicOpen (Module.rankIdempotent R M i) : Set (PrimeSpectrum R)) = + {p | Module.rankAtStalk (R := R) M p = i} := + ((PrimeSpectrum.exists_idempotent_basicOpen_eq_of_isClopen + (Module.isClopen_setOf_rankAtStalk_eq R M i)).choose_spec.2).symm + +theorem Module.rankAtStalk_eq_of_mem_basicOpen_rankIdempotent {i : ℕ} {p : PrimeSpectrum R} + (hp : p ∈ basicOpen (Module.rankIdempotent R M i)) : + Module.rankAtStalk (R := R) M p = i := by + rw [← Set.mem_ofPred_eq (p := fun p ↦ Module.rankAtStalk (R := R) M p = i), + ← Module.coe_basicOpen_rankIdempotent R M i] + exact hp + +/-- The rank idempotents are characterized by their basic open sets: an idempotent cutting out the +rank-`i` locus *is* `Module.rankIdempotent R M i` (`GPR Exc. 9.29(b)`). -/ +theorem Module.eq_rankIdempotent_of_coe_basicOpen_eq {e : R} (he : IsIdempotentElem e) (i : ℕ) + (h : (basicOpen e : Set (PrimeSpectrum R)) = + {p | Module.rankAtStalk (R := R) M p = i}) : + e = Module.rankIdempotent R M i := + PrimeSpectrum.basicOpen_injOn_isIdempotentElem he (Module.isIdempotentElem_rankIdempotent R M i) + (SetLike.ext' (by rw [h, Module.coe_basicOpen_rankIdempotent])) + +/-- Distinct ranks give orthogonal idempotents: the rank loci are disjoint. -/ +theorem Module.rankIdempotent_mul_rankIdempotent {i j : ℕ} (h : i ≠ j) : + Module.rankIdempotent R M i * Module.rankIdempotent R M j = 0 := by + refine eq_zero_of_isIdempotentElem_of_basicOpen_eq_bot + ((Module.isIdempotentElem_rankIdempotent R M i).mul + (Module.isIdempotentElem_rankIdempotent R M j)) ?_ + refine SetLike.ext' (Set.eq_empty_iff_forall_notMem.mpr fun p hp ↦ ?_) + rw [PrimeSpectrum.basicOpen_mul] at hp + exact h ((Module.rankAtStalk_eq_of_mem_basicOpen_rankIdempotent R M hp.1).symm.trans + (Module.rankAtStalk_eq_of_mem_basicOpen_rankIdempotent R M hp.2)) + +/-- Ranks that do not occur give the zero idempotent. -/ +theorem Module.rankIdempotent_eq_zero_of_notMem_range {i : ℕ} + (h : i ∉ Set.range (Module.rankAtStalk (R := R) M)) : + Module.rankIdempotent R M i = 0 := by + refine eq_zero_of_isIdempotentElem_of_basicOpen_eq_bot + (Module.isIdempotentElem_rankIdempotent R M i) (SetLike.ext' ?_) + rw [Module.coe_basicOpen_rankIdempotent] + exact Set.eq_empty_iff_forall_notMem.mpr fun p hp ↦ h ⟨p, hp⟩ + +/-- **`GPR Exc. 9.31(b)`, existence.** For any finite set of naturals containing every rank of +`M`, the corresponding rank idempotents form a complete orthogonal system. + +Feeding this to `CompleteOrthogonalIdempotents.bijective_pi` gives the ring decomposition +`R ≃ ∏ᵢ R ⧸ (1 - εᵢ)`, and to +`CompleteOrthogonalIdempotents.linearEquivPiQuotientTensor` the module decomposition +`M ≃ ∏ᵢ (R ⧸ (1 - εᵢ)) ⊗[R] M`. -/ +theorem Module.completeOrthogonalIdempotents_rankIdempotent (s : Finset ℕ) + (hs : ∀ p : PrimeSpectrum R, Module.rankAtStalk (R := R) M p ∈ s) : + CompleteOrthogonalIdempotents (fun i : s ↦ Module.rankIdempotent R M i) := by + refine CompleteOrthogonalIdempotents.of_prod_one_sub + ⟨fun i ↦ Module.isIdempotentElem_rankIdempotent R M i, fun i j hij ↦ + Module.rankIdempotent_mul_rankIdempotent R M (Subtype.coe_ne_coe.mpr hij)⟩ ?_ + -- The product of the `1 - εᵢ` is an idempotent whose basic open set is empty, since the rank + -- loci for `i ∈ s` cover `Spec R`. + refine eq_zero_of_isIdempotentElem_of_basicOpen_eq_bot + (Finset.prod_induction _ IsIdempotentElem (fun _ _ ↦ IsIdempotentElem.mul) + (IsIdempotentElem.one) fun i _ ↦ (Module.isIdempotentElem_rankIdempotent R M i).one_sub) ?_ + refine SetLike.ext' (Set.eq_empty_iff_forall_notMem.mpr fun p hp ↦ ?_) + rw [SetLike.mem_coe, PrimeSpectrum.mem_basicOpen] at hp + set i₀ : s := ⟨Module.rankAtStalk (R := R) M p, hs p⟩ with hi₀ + -- `1 - ε_{i₀}` divides the product, so it too is outside `p`. + have hone : (1 : R) - Module.rankIdempotent R M i₀ ∉ p.asIdeal := by + intro hmem + obtain ⟨c, hc⟩ := + Finset.dvd_prod_of_mem (fun i : s ↦ 1 - Module.rankIdempotent R M i) (Finset.mem_univ i₀) + exact hp (hc ▸ p.asIdeal.mul_mem_right c hmem) + -- But `ε_{i₀}` is also outside `p`, since `p` lies in the rank-`i₀` locus. + have hidem : Module.rankIdempotent R M (i₀ : ℕ) ∉ p.asIdeal := by + have : p ∈ (basicOpen (Module.rankIdempotent R M (i₀ : ℕ)) : Set (PrimeSpectrum R)) := by + rw [Module.coe_basicOpen_rankIdempotent]; rfl + rwa [SetLike.mem_coe, PrimeSpectrum.mem_basicOpen] at this + have hzero : + Module.rankIdempotent R M (i₀ : ℕ) * (1 - Module.rankIdempotent R M i₀) = 0 := by + rw [mul_sub, mul_one, (Module.isIdempotentElem_rankIdempotent R M i₀).eq, sub_self] + rcases p.isPrime.mem_or_mem (hzero ▸ p.asIdeal.zero_mem) with h | h + · exact hidem h + · exact hone h + +/-- In `R ⧸ (1 - ε)`, an idempotent `ε` becomes `1`. -/ +private theorem algebraMap_quotient_one_sub_eq_one {e : R} : + algebraMap R (R ⧸ Ideal.span {1 - e}) e = 1 := by + rw [Ideal.Quotient.algebraMap_eq] + have h : (Ideal.Quotient.mk (Ideal.span {1 - e})) (1 - e) = 0 := + Ideal.Quotient.eq_zero_iff_mem.mpr (Ideal.mem_span_singleton_self _) + rw [map_sub, map_one, sub_eq_zero] at h + exact h.symm + +/-- **The point of the rank decomposition.** On the factor `R ⧸ (1 - εᵢ)`, the module `M` has +constant rank `i`. + +Every prime of the factor pulls back to a prime of `R` at which `εᵢ` is invertible — it maps to +`1` — hence to a point of `D(εᵢ)`, which is exactly the rank-`i` locus. -/ +theorem Module.rankAtStalk_quotientTensor_rankIdempotent (i : ℕ) : + Module.rankAtStalk (R := R ⧸ Ideal.span {1 - Module.rankIdempotent R M i}) + ((R ⧸ Ideal.span {1 - Module.rankIdempotent R M i}) ⊗[R] M) = fun _ ↦ i := by + funext p + rw [Module.rankAtStalk_baseChange] + refine Module.rankAtStalk_eq_of_mem_basicOpen_rankIdempotent R M ?_ + rw [PrimeSpectrum.mem_basicOpen] + intro hmem + refine p.isPrime.ne_top (Ideal.eq_top_iff_one _ |>.mpr ?_) + rw [← algebraMap_quotient_one_sub_eq_one R (e := Module.rankIdempotent R M i)] + exact hmem + +/-- **`GPR Exc. 9.31(b)`, uniqueness.** A complete orthogonal system of idempotents whose factors +give `M` pairwise distinct constant ranks consists of rank idempotents. + +Injectivity of `r` is needed: without it two factors could carry the same rank, and their +idempotents would sum to — rather than equal — the corresponding rank idempotent. -/ +theorem Module.eq_rankIdempotent_of_completeOrthogonalIdempotents {ι : Type*} [Fintype ι] + (η : ι → R) (hη : CompleteOrthogonalIdempotents η) (r : ι → ℕ) + (hr : Function.Injective r) + (h : ∀ j, Module.rankAtStalk (R := R ⧸ Ideal.span {1 - η j}) + ((R ⧸ Ideal.span {1 - η j}) ⊗[R] M) = fun _ ↦ r j) (j : ι) : + η j = Module.rankIdempotent R M (r j) := by + -- Each `D(η j)` sits inside the rank-`r j` locus. + have hsub : ∀ k : ι, ∀ p ∈ basicOpen (η k), + Module.rankAtStalk (R := R) M p = r k := by + intro k p hp + -- `η k ∉ p` forces `1 - η k ∈ p`, so `p` comes from a prime of `R ⧸ (1 - η k)`. + have hone : (1 : R) - η k ∈ p.asIdeal := by + rcases p.isPrime.mem_or_mem (show η k * (1 - η k) ∈ p.asIdeal by + rw [mul_sub, mul_one, (hη.idem k).eq, sub_self]; exact p.asIdeal.zero_mem) with hk | hk + · exact absurd hk (PrimeSpectrum.mem_basicOpen _ _ |>.mp hp) + · exact hk + have hrange : p ∈ Set.range + (PrimeSpectrum.comap (algebraMap R (R ⧸ Ideal.span {1 - η k}))) := by + rw [Ideal.Quotient.algebraMap_eq, + range_comap_of_surjective _ _ Ideal.Quotient.mk_surjective, Ideal.mk_ker] + rw [PrimeSpectrum.mem_zeroLocus] + exact Ideal.span_le.mpr (Set.singleton_subset_iff.mpr hone) + obtain ⟨q, rfl⟩ := hrange + rw [← Module.rankAtStalk_baseChange (M := M) q, h k] + -- The `D(η k)` cover `Spec R`, because the `η k` sum to `1`. + have hcover : ∀ p : PrimeSpectrum R, ∃ k, p ∈ basicOpen (η k) := by + intro p + by_contra hcon + simp only [not_exists, PrimeSpectrum.mem_basicOpen, not_not] at hcon + exact p.isPrime.ne_top (Ideal.eq_top_iff_one _ |>.mpr + (hη.complete ▸ Ideal.sum_mem _ fun k _ ↦ hcon k)) + refine Module.eq_rankIdempotent_of_coe_basicOpen_eq R M (hη.idem j) (r j) (Set.ext fun p ↦ ?_) + refine ⟨fun hp ↦ hsub j p hp, fun hp ↦ ?_⟩ + obtain ⟨k, hk⟩ := hcover p + have : r k = r j := (hsub k p hk).symm.trans hp + exact hr this ▸ hk + +/-! ### The decomposition, packaged + +Indexing by the set of ranks itself, so that no `Finset` has to be supplied at the call site. -/ + +/-- The set of ranks of `M`, as a `Finset` — finite by `GPR Exc. 9.31(a)`. `GPR` writes +`Rk(M)`. -/ +noncomputable def Module.rankFinset : Finset ℕ := + (Module.finite_range_rankAtStalk R M).toFinset + +@[simp] +theorem Module.mem_rankFinset {i : ℕ} : + i ∈ Module.rankFinset R M ↔ i ∈ Set.range (Module.rankAtStalk (R := R) M) := + Set.Finite.mem_toFinset _ + +theorem Module.rankAtStalk_mem_rankFinset (p : PrimeSpectrum R) : + Module.rankAtStalk (R := R) M p ∈ Module.rankFinset R M := + (Module.mem_rankFinset R M).mpr ⟨p, rfl⟩ + +/-- The rank idempotents indexed by `Rk(M)` form a complete orthogonal system. -/ +theorem Module.completeOrthogonalIdempotents_rankIdempotent_rankFinset : + CompleteOrthogonalIdempotents + (fun i : Module.rankFinset R M ↦ Module.rankIdempotent R M i) := + Module.completeOrthogonalIdempotents_rankIdempotent R M _ (Module.rankAtStalk_mem_rankFinset R M) + +/-- **`GPR Exc. 9.31(b)`(1), the rank decomposition of the ring.** `R` is the product of the +rings `R ⧸ (1 - εᵢ)`, one for each rank `i` of `M`. -/ +noncomputable def Module.rankDecompositionRingEquiv : + R ≃+* ∀ i : Module.rankFinset R M, R ⧸ Ideal.span {1 - Module.rankIdempotent R M i} := + RingEquiv.ofBijective _ + (Module.completeOrthogonalIdempotents_rankIdempotent_rankFinset R M).bijective_pi + +/-- **`GPR Exc. 9.31(b)`(2), the rank decomposition of the module.** `M` is the product of its +base changes to the factor rings, and by +`Module.rankAtStalk_quotientTensor_rankIdempotent` the `i`th of these has **constant rank `i`**. + +This is what licenses "by the rank decomposition we may assume `M` has constant rank". -/ +noncomputable def Module.rankDecompositionLinearEquiv : + M ≃ₗ[R] ∀ i : Module.rankFinset R M, + (R ⧸ Ideal.span {1 - Module.rankIdempotent R M i}) ⊗[R] M := + (Module.completeOrthogonalIdempotents_rankIdempotent_rankFinset R M).linearEquivPiQuotientTensor + M _ + +/-! ### The rank-zero idempotent + +`ε₀ = Module.rankIdempotent R M 0` cuts out the locus where `M` vanishes. Two facts about it are +used, without ever performing the product decomposition of `R` that it induces: + +* it **annihilates** `M` (`Module.rankIdempotent_zero_smul`), and +* it is a **unit** at every maximal ideal where `M` has trivial residue space + (`Module.notMem_rankIdempotent_zero`). + +Together they let an argument treat the vanishing locus of `M` separately while staying over `R`: +multiplying by `ε₀` kills everything coming from `M`, and reducing modulo a maximal ideal in the +vanishing locus turns `ε₀` into `1`. -/ + +/-- **The rank-zero idempotent annihilates `M`.** + +Checked one maximal ideal `P` at a time. If `ε₀ ∈ P` then `1 - ε₀ ∉ P` annihilates `ε₀ • x`; if +`ε₀ ∉ P` then `M` has rank `0` at `P`, so `P` is outside the support of `M` and some `r ∉ P` +already annihilates `x`. An element annihilated modulo every maximal ideal is zero. -/ +theorem Module.rankIdempotent_zero_smul (x : M) : Module.rankIdempotent R M 0 • x = 0 := by + set e := Module.rankIdempotent R M 0 with he + by_contra hx + have hne : (R ∙ (e • x)).annihilator ≠ ⊤ := by + intro h + have h1 : (1 : R) ∈ (R ∙ (e • x)).annihilator := by rw [h]; exact Submodule.mem_top + exact hx (by simpa using (Submodule.mem_annihilator_span_singleton _ _).mp h1) + obtain ⟨P, hP, hle⟩ := Ideal.exists_le_maximal _ hne + have hann : ∃ r ∉ P, r • (e • x) = 0 := by + by_cases hmem : e ∈ P + · refine ⟨1 - e, fun hc ↦ hP.ne_top (Ideal.eq_top_iff_one _ |>.mpr ?_), ?_⟩ + · simpa using P.add_mem hc hmem + · rw [smul_smul, sub_mul, one_mul, (Module.isIdempotentElem_rankIdempotent R M 0).eq, + sub_self, zero_smul] + · have hrank : Module.rankAtStalk (R := R) M ⟨P, hP.isPrime⟩ = 0 := + Module.rankAtStalk_eq_of_mem_basicOpen_rankIdempotent R M + ((PrimeSpectrum.mem_basicOpen _ _).mpr hmem) + obtain ⟨r, hr, hr0⟩ := Module.notMem_support_iff'.mp + ((Module.rankAtStalk_eq_zero_iff_notMem_support _).mp hrank) x + exact ⟨r, hr, by rw [smul_comm, hr0, smul_zero]⟩ + obtain ⟨r, hr, hr0⟩ := hann + exact hr (hle ((Submodule.mem_annihilator_span_singleton _ _).mpr hr0)) + +/-- **The rank-zero idempotent is a unit where `M` vanishes.** If `M ⊗ κ(𝔪)` is trivial at a +maximal ideal `𝔪` then `ε₀ ∉ 𝔪`. + +`M ⊗ R⧸𝔪` is `M ⧸ 𝔪 M`, whose support is `Supp M ∩ V(𝔪)`; triviality makes that empty, and `𝔪` +lies in `V(𝔪)`, so `𝔪 ∉ Supp M` — that is, `M` has rank `0` at `𝔪`, which is exactly membership +in `D(ε₀)`. -/ +theorem Module.notMem_rankIdempotent_zero (𝔪 : Ideal R) [h𝔪 : 𝔪.IsMaximal] + (h : Subsingleton ((R ⧸ 𝔪) ⊗[R] M)) : Module.rankIdempotent R M 0 ∉ 𝔪 := by + have : Subsingleton (M ⧸ (𝔪 • ⊤ : Submodule R M)) := + (TensorProduct.quotTensorEquivQuotSMul M 𝔪).symm.toEquiv.subsingleton + have hsupp : Module.support R M ∩ PrimeSpectrum.zeroLocus (𝔪 : Set R) = ∅ := by + rw [← Module.support_quotient (M := M) 𝔪] + exact Module.support_eq_empty_iff.mpr ‹_› + have hns : (⟨𝔪, h𝔪.isPrime⟩ : PrimeSpectrum R) ∉ Module.support R M := fun hc ↦ + Set.eq_empty_iff_forall_notMem.mp hsupp _ + ⟨hc, (PrimeSpectrum.mem_zeroLocus _ _).mpr le_rfl⟩ + refine (PrimeSpectrum.mem_basicOpen _ (⟨𝔪, h𝔪.isPrime⟩ : PrimeSpectrum R)).mp ?_ + rw [← SetLike.mem_coe, Module.coe_basicOpen_rankIdempotent] + exact (Module.rankAtStalk_eq_zero_iff_notMem_support _).mpr hns + +/-! ### Detecting vanishing on the factors + +The two lemmas the phrase "by the rank decomposition we may assume constant rank" needs when the +statement to be transported is an *equation* rather than a structure: an element of `M` vanishes as +soon as it vanishes in each `(R ⧸ (1 - εᵢ)) ⊗ M`. They are stated separately because the second is +about a single factor and carries no finiteness. -/ + +/-- An element killed by every rank idempotent is zero, the idempotents summing to `1`. -/ +theorem Module.eq_zero_of_forall_rankIdempotent_smul_eq_zero {x : M} + (h : ∀ i : Module.rankFinset R M, Module.rankIdempotent R M i • x = 0) : x = 0 := by + have hsum := (Module.completeOrthogonalIdempotents_rankIdempotent_rankFinset R M).complete + calc x = (∑ i : Module.rankFinset R M, Module.rankIdempotent R M i) • x := by rw [hsum, one_smul] + _ = ∑ i : Module.rankFinset R M, Module.rankIdempotent R M i • x := Finset.sum_smul .. + _ = 0 := by simp [h] + +/-- If `x` dies in the `i`th factor `(R ⧸ (1 - εᵢ)) ⊗ M` of the rank decomposition, then `εᵢ` +kills it. + +Reducing `M` modulo an ideal is tensoring with the quotient ring +(`TensorProduct.quotTensorEquivQuotSMul`), so the hypothesis says `x ∈ span{1 - εᵢ} • ⊤`; and `εᵢ` +annihilates that submodule, since `εᵢ(1 - εᵢ) = 0`. -/ +theorem Module.rankIdempotent_smul_eq_zero_of_one_tmul_eq_zero (i : ℕ) {x : M} + (h : (1 : R ⧸ Ideal.span {1 - Module.rankIdempotent R M i}) ⊗ₜ[R] x = 0) : + Module.rankIdempotent R M i • x = 0 := by + set e := Module.rankIdempotent R M i with he + set I : Ideal R := Ideal.span {1 - e} with hI + have hmk : (Submodule.Quotient.mk x : M ⧸ (I • ⊤ : Submodule R M)) = 0 := by + rw [← TensorProduct.quotTensorEquivQuotSMul_mk_one_tmul (M := M) I x, h, map_zero] + have hmem : x ∈ (I • ⊤ : Submodule R M) := by + rwa [Submodule.Quotient.mk_eq_zero] at hmk + refine Submodule.smul_induction_on hmem ?_ ?_ + · intro r hr n _ + obtain ⟨c, rfl⟩ := Ideal.mem_span_singleton'.mp hr + have hidem : e * e = e := Module.isIdempotentElem_rankIdempotent R M i + rw [smul_smul, show e * (c * (1 - e)) = c * (e - e * e) by ring, hidem, sub_self, mul_zero, + zero_smul] + · intro a b ha hb + rw [smul_add, ha, hb, add_zero] + +/-! ### Constant rank means locally free of that rank -/ + +/-- Constant rank survives base change: if `M` has rank `n` at every prime of `R`, then `S ⊗[R] M` +has rank `n` at every prime of `S`. -/ +theorem Module.rankAtStalk_baseChange_of_eq {R : Type u} {M : Type v} [CommRing R] + [AddCommGroup M] [Module R M] [Module.Flat R M] [Module.Finite R M] (S : Type*) [CommRing S] + [Algebra R S] {n : ℕ} (hM : Module.rankAtStalk (R := R) M = fun _ ↦ n) : + Module.rankAtStalk (R := S) (S ⊗[R] M) = fun _ ↦ n := by + funext p + rw [Module.rankAtStalk_baseChange, hM] + +/-- A finitely generated projective module of constant rank `n` becomes free of rank `n` at every +prime. -/ +theorem Module.nonempty_basis_atPrime_of_rankAtStalk_eq {R : Type u} {M : Type v} [CommRing R] + [AddCommGroup M] [Module R M] [Module.Finite R M] [Module.Projective R M] {n : ℕ} + (hM : Module.rankAtStalk (R := R) M = fun _ ↦ n) (J : Ideal R) [J.IsPrime] : + Nonempty (Module.Basis (Fin n) (Localization.AtPrime J) (Localization.AtPrime J ⊗[R] M)) := by + let S := Localization.AtPrime J + have : Module.Free S (S ⊗[R] M) := Module.free_of_flat_of_isLocalRing + have hfin : Module.finrank S (S ⊗[R] M) = n := by + have h := congrFun hM ⟨J, inferInstance⟩ + rw [Module.rankAtStalk_eq_finrank_tensorProduct] at h + simpa [S] using h + exact ⟨Module.finBasisOfFinrankEq S (S ⊗[R] M) hfin⟩ diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/SelfAnnihilating.lean b/LeanPool/CompositionAlgebrasOverRings/Module/SelfAnnihilating.lean new file mode 100644 index 0000000000..28acac070f --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/SelfAnnihilating.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.Dual.BaseChange +public import Mathlib.LinearAlgebra.TensorProduct.Tower +public import Mathlib.Tactic.LinearCombination +public import Mathlib.Tactic.Module +public import Mathlib.RingTheory.LocalProperties.Basic +public import Mathlib.RingTheory.LocalProperties.Projective +public import Mathlib.RingTheory.LocalRing.Module +public import Mathlib.RingTheory.TensorProduct.Free + +/-! +# Functionals that annihilate their own argument + +A linear form `φ : M → R` is **self-annihilating** if `φ x • x = 0` for every `x`. On a finitely +generated projective module this forces `φ = 0`. + +Over a free module the reason is immediate: a basis vector `e` has `φ e • e = 0`, and a basis +vector is not killed by any nonzero scalar. Over a projective module it is *false* pointwise — +`φ x • x = 0` says only that `φ x` annihilates `x` — and what rescues it is that the hypothesis is +required for *every* `x`, so it survives base change and can be checked after localizing at each +maximal ideal, where the module is free. + +This is the mechanism behind `GPR 16.14(b)`: an identity of the shape `c(x) • x = d(x) • 1`, +which is what flexibility gives in a conic algebra, collapses to `c = 0` as soon as the algebra is +projective — see `CompositionAlgebras/Conic/Projective.lean`. + +## Main results + +* `LinearMap.eq_zero_of_smul_self_eq_zero_of_free` : the free case. +* `LinearMap.eq_zero_of_smul_self_eq_zero` : the finitely generated projective case. + +## Implementation notes + +The projective case is proved by base change to `Localization.AtPrime 𝔪` rather than by +localizing the module: `LinearMap.baseChange` and `TensorProduct.induction_on` are enough, and the +hypothesis transfers to `S ⊗[R] M` in two steps — its linearization `φ u • v + φ v • u = 0` is +bi-additive and so reduces to pure tensors, and the hypothesis itself then follows from the +linearization by induction. This is the same two-step shape as the degree-two identity in +`CompositionAlgebras/Conic/BaseChange.lean`. +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +namespace LinearMap + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-- The linearization of `φ x • x = 0`. -/ +theorem smul_add_smul_eq_zero_of_smul_self_eq_zero {φ : M →ₗ[R] R} + (h : ∀ x : M, φ x • x = 0) (u v : M) : φ u • v + φ v • u = 0 := by + have huv := h (u + v) + rw [map_add, add_smul, smul_add, smul_add, h u, h v] at huv + simpa using huv + +/-- **A self-annihilating functional on a free module is zero.** A basis vector is killed by no +nonzero scalar. -/ +theorem eq_zero_of_smul_self_eq_zero_of_free [Module.Free R M] (φ : M →ₗ[R] R) + (h : ∀ x : M, φ x • x = 0) : φ = 0 := by + classical + set b := Module.Free.chooseBasis R M with hb + refine b.ext fun i ↦ ?_ + have hi := congrArg (fun z ↦ b.repr z i) (h (b i)) + simpa using hi + +section BaseChange + +variable (S : Type*) [CommRing S] [Algebra R S] + +variable {S} + +/-- Moving a scalar of `R` out of the `S`-action on a pure tensor. -/ +private theorem smul_smul_tmul (c : R) (s s' : S) (x : M) : + (c • s) • (s' ⊗ₜ[R] x) = (s * s') ⊗ₜ[R] (c • x) := by + rw [smul_assoc, TensorProduct.smul_tmul', smul_eq_mul, TensorProduct.smul_tmul', + TensorProduct.smul_tmul] + +/-- The linearized hypothesis transfers to the base change: it is bi-additive, so it is enough to +check it on pure tensors. -/ +theorem smul_add_smul_baseChange_eq_zero {φ : M →ₗ[R] R} (h : ∀ x : M, φ x • x = 0) + (z w : S ⊗[R] M) : + Module.Dual.baseChange S φ z • w + Module.Dual.baseChange S φ w • z = 0 := by + induction z with + | add z₁ z₂ h₁ h₂ => + simp only [map_add, add_smul, smul_add] + linear_combination (norm := module) h₁ + h₂ + | tmul s x => + induction w with + | add w₁ w₂ h₁ h₂ => + simp only [map_add, add_smul, smul_add] + linear_combination (norm := module) h₁ + h₂ + | tmul s' x' => + rw [Module.Dual.baseChange_apply_tmul, Module.Dual.baseChange_apply_tmul, smul_smul_tmul, + smul_smul_tmul, mul_comm s' s, ← TensorProduct.tmul_add, + smul_add_smul_eq_zero_of_smul_self_eq_zero h, TensorProduct.tmul_zero] + +/-- Self-annihilation transfers to the base change. -/ +theorem smul_self_baseChange_eq_zero {φ : M →ₗ[R] R} (h : ∀ x : M, φ x • x = 0) + (z : S ⊗[R] M) : Module.Dual.baseChange S φ z • z = 0 := by + induction z with + | tmul s x => + rw [Module.Dual.baseChange_apply_tmul, smul_smul_tmul, h x, TensorProduct.tmul_zero] + | add z w hz hw => + have hlin := smul_add_smul_baseChange_eq_zero (S := S) h z w + simp only [map_add, add_smul, smul_add] + linear_combination (norm := module) hz + hw + hlin + +end BaseChange + +/-- **A self-annihilating functional on a finitely generated projective module is zero.** + +Base change to `Localization.AtPrime 𝔪` preserves the hypothesis, and there the module is free, +so the base-changed functional vanishes; hence `φ x` dies in every localization, hence is `0`. -/ +theorem eq_zero_of_smul_self_eq_zero [Module.Finite R M] [Module.Projective R M] + (φ : M →ₗ[R] R) + (h : ∀ x : M, φ x • x = 0) : φ = 0 := by + ext x + refine eq_zero_of_localization (φ x) fun J hJ ↦ ?_ + set S := Localization.AtPrime J with hS + have : Module.Free S (S ⊗[R] M) := Module.free_of_flat_of_isLocalRing + have hψ : Module.Dual.baseChange S φ = 0 := + eq_zero_of_smul_self_eq_zero_of_free _ (smul_self_baseChange_eq_zero h) + have := congrArg (fun ψ ↦ ψ ((1 : S) ⊗ₜ[R] x)) hψ + simpa [Algebra.smul_def] using this + +end LinearMap diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/Unimodular.lean b/LeanPool/CompositionAlgebrasOverRings/Module/Unimodular.lean new file mode 100644 index 0000000000..b93cbedd11 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/Unimodular.lean @@ -0,0 +1,181 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.Unimodular +public import Mathlib.LinearAlgebra.Dual.Lemmas + +/-! +# Unimodular elements of a module + +An element `m` of an `R`-module `M` is **unimodular** when some linear functional takes the value +`1` at `m`. This is mathlib's `Module.IsUnimodular R m`, which the library uses throughout. +`GPR 9.13` defines unimodularity differently, by asking that `R·m` be free of rank 1 and a direct +summand of `M`, and observes there that the two agree. This file proves that agreement and supplies +the API the rest of the library needs beyond what mathlib provides. + +This is not a norm-theoretic notion — no quadratic form is in sight here — but it is the piece +`QuadraticForm/Isotropic.lean` needs to state GPR-sense isotropy correctly (`GPR 11.17`): a +**unimodular** null vector, not merely a nonzero one. See overview §6(c). + +## Main definitions + +* `LinearMap.equivProdKerOfApplyEqOne` : the splitting `M ≃ R × ker l` determined by a functional + `l` with `l m = 1`. + +## Main results + +* `Module.isUnimodular_iff_injective_toSpanSingleton_and_isComplemented_span` : the equivalence + noted in **`GPR 9.13`** — `m` is unimodular iff `R·m` is free of rank 1 (`toSpanSingleton` + injective) and a direct summand of `M` (`Submodule.span R {m}` is complemented), which is the + definition there. +* `Module.IsUnimodular.map` : unimodularity transports along a linear equivalence. +* `Module.IsUnimodular.units_smul` : unimodularity is unaffected by scaling by a unit. +* `Module.isUnimodular_of_ne_zero` : over a field, unimodular is *exactly* nonzero — every nonzero + vector in a vector space is hit by a functional. This is what collapses GPR-sense isotropy onto + mathlib's `Anisotropic` over a field; see `QuadraticForm/Isotropic.lean`. +* `Module.IsUnimodular.exists_linearEquiv_prod` : a unimodular element splits `M` as `R × M'`. + +## Implementation notes + +GPR also states unimodularity geometrically: `m` is unimodular iff `m ⊗ 1_{κ(𝔭)} ≠ 0` for every +`𝔭 ∈ Spec R` (i.e. `m` survives in every residue field). ⚠ That criterion needs `M` finitely +generated projective (`GPR 9.17`): in the `ℤ`-module `ℤ ⊕ ℤ/2` the element `(2, 1)` survives in +every residue field, but no linear functional takes it to `1`. Only the two algebraic formulations +above are formalized here; the geometric one is not. Note that residue fields cannot detect +whether an element is *nonzero* — `ε` in the free rank-one module over `𝔽₂[ε]/(ε²)` dies in every +residue field — so the geometric criterion genuinely uses unimodularity, not mere non-vanishing. + +We use mathlib's general lattice notion `IsComplemented` (`Mathlib.Order.Disjoint`) for "direct +summand" in the `GPR 9.13` characterization rather than inventing a submodule-specific one, per +overview §0. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.13, 9.17, 11.24. +-/ + +@[expose] public section + +universe u v + +variable {R : Type u} [CommRing R] + +namespace Module + +/-- **`GPR 9.13`**: `m` is unimodular — hit by a functional — exactly when the cyclic submodule +`R·m` is free of rank 1 (equivalently, `r • m = 0 → r = 0`) and a direct summand of `M`, which is +how `GPR 9.13` defines unimodularity. -/ +theorem isUnimodular_iff_injective_toSpanSingleton_and_isComplemented_span {M : Type v} + [AddCommGroup M] [Module R M] {m : M} : + IsUnimodular R m ↔ + Function.Injective (LinearMap.toSpanSingleton R M m) ∧ + IsComplemented (Submodule.span R {m}) := by + constructor + · -- A functional `l` with `l m = 1` splits off `R·m` with complement its kernel, and it + -- witnesses `r • m = 0 → r = 0`. + intro hm + obtain ⟨l, hl⟩ := isUnimodular_iff.mp hm + have hinj : Function.Injective (LinearMap.toSpanSingleton R M m) := by + intro a b hab + have h := congrArg l hab + simpa [LinearMap.toSpanSingleton_apply, hl] using h + refine ⟨hinj, LinearMap.ker l, ?_, ?_⟩ + · rw [disjoint_iff_inf_le] + rintro x ⟨hx1, hx2⟩ + obtain ⟨r, rfl⟩ := Submodule.mem_span_singleton.mp hx1 + have hr : r = 0 := by + have := LinearMap.mem_ker.mp hx2 + simpa [hl] using this + simp [hr] + · rw [codisjoint_iff_le_sup] + intro x _ + refine Submodule.mem_sup.mpr ⟨l x • m, Submodule.mem_span_singleton.mpr ⟨l x, rfl⟩, + x - l x • m, ?_, by abel⟩ + simp [LinearMap.mem_ker, hl] + · -- Project onto `R·m` along a complement and undo the isomorphism `R ≃ R·m`. + rintro ⟨hinj, N, hN⟩ + have hrange : Submodule.span R {m} = LinearMap.range (LinearMap.toSpanSingleton R M m) := by + rw [LinearMap.span_singleton_eq_range] + let e : R ≃ₗ[R] (Submodule.span R {m}) := + (LinearEquiv.ofInjective _ hinj).trans (LinearEquiv.ofEq _ _ hrange.symm) + refine isUnimodular_of_apply_eq_one (f := (e.symm : (Submodule.span R {m}) →ₗ[R] R) ∘ₗ + Submodule.projectionOnto _ _ hN) ?_ + have hmem : m ∈ Submodule.span R {m} := Submodule.mem_span_singleton_self m + have hproj : Submodule.projectionOnto _ _ hN m = ⟨m, hmem⟩ := + Submodule.projectionOnto_apply_left hN ⟨m, hmem⟩ + have he : e 1 = ⟨m, hmem⟩ := by + apply Subtype.ext + simp [e, LinearMap.toSpanSingleton_apply] + rw [LinearMap.comp_apply, hproj, ← he] + exact e.symm_apply_apply 1 + +/-- Unimodularity transports along a linear equivalence: `m` unimodular in `M` and `e : M ≃ₗ N` +give `e m` unimodular in `N`. -/ +theorem IsUnimodular.map {M : Type*} [AddCommGroup M] [Module R M] + {M' : Type*} [AddCommGroup M'] [Module R M'] {m : M} + (hm : IsUnimodular R m) (e : M ≃ₗ[R] M') : IsUnimodular R (e m) := by + obtain ⟨l, hl⟩ := isUnimodular_iff.mp hm + exact isUnimodular_of_apply_eq_one (f := l ∘ₗ e.symm.toLinearMap) (by simpa using hl) + +/-- Unimodularity is unaffected by scaling by a unit: if `m` is unimodular then so is `u • m` for +`u : Rˣ`, since `R·(u • m) = R·m`. -/ +theorem IsUnimodular.units_smul {M : Type*} [AddCommGroup M] [Module R M] {m : M} + (hm : IsUnimodular R m) (u : Rˣ) : IsUnimodular R (u • m) := by + obtain ⟨l, hl⟩ := isUnimodular_iff.mp hm + refine isUnimodular_of_apply_eq_one (f := ((u⁻¹ : Rˣ) : R) • l) ?_ + simp [Units.smul_def, hl] + +/-- Over a field, unimodular is exactly nonzero: every nonzero vector of a vector space is hit by a +functional. -/ +theorem isUnimodular_of_ne_zero {K : Type u} [Field K] {M : Type v} [AddCommGroup M] + [Module K M] {x : M} (hx : x ≠ 0) : IsUnimodular K x := + isUnimodular_iff.mpr (Projective.exists_dual_eq_one K hx) + +end Module + +/-! ### Splitting off a unimodular element + +A unimodular element does not merely span a complemented line — it splits `M` as `R ⊕ M'` with the +free factor *identified*, which is what an induction on the rank needs. -/ + +variable {M : Type v} [AddCommGroup M] [Module R M] + +/-- The **splitting** determined by a functional `l` with `l m = 1`: `M ≃ R × ker l`, by +`x ↦ (l x, x - l x • m)` with inverse `(r, y) ↦ r • m + y`. + +Since such an `l` is exactly a witness for `Module.IsUnimodular R m`, this says a unimodular element +splits off a free rank-one direct summand. The complement is presented concretely as `ker l` +rather than as an abstract summand so that it stays a `Submodule R M`, hence lives in the same +universe as `M` — which is what makes the induction on the rank in +`Module.free_of_rankAtStalk_eq` (`LGRing/ConstantRank.lean`) go through. -/ +noncomputable def LinearMap.equivProdKerOfApplyEqOne (l : M →ₗ[R] R) (m : M) (hl : l m = 1) : + M ≃ₗ[R] R × (LinearMap.ker l) := + LinearEquiv.ofLinearMap + (l.prod ((LinearMap.id - (LinearMap.toSpanSingleton R M m) ∘ₗ l).codRestrict _ fun x ↦ by + simp [LinearMap.mem_ker, LinearMap.toSpanSingleton_apply, hl])) + ((LinearMap.toSpanSingleton R M m).coprod (LinearMap.ker l).subtype) + (by + refine LinearMap.ext fun x ↦ ?_ + obtain ⟨r, y, hy⟩ := x + have hfst : l (r • m + y) = r := by + simp [LinearMap.mem_ker.mp hy, hl] + refine Prod.ext ?_ (Subtype.ext ?_) <;> + simp [LinearMap.toSpanSingleton_apply, hfst] + · simp [LinearMap.mem_ker.mp hy, hl]) + (by refine LinearMap.ext fun x ↦ ?_; simp) + +@[simp] +theorem LinearMap.equivProdKerOfApplyEqOne_symm_apply (l : M →ₗ[R] R) (m : M) (hl : l m = 1) + (x : R × (LinearMap.ker l)) : + (LinearMap.equivProdKerOfApplyEqOne l m hl).symm x = x.1 • m + (x.2 : M) := + rfl + +/-- A unimodular element splits `M` as `R ⊕ M'` for a submodule `M'` of `M`. -/ +theorem Module.IsUnimodular.exists_linearEquiv_prod {m : M} (hm : Module.IsUnimodular R m) : + ∃ M' : Submodule R M, Nonempty (M ≃ₗ[R] R × M') := by + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hm + exact ⟨LinearMap.ker l, ⟨LinearMap.equivProdKerOfApplyEqOne l m hl⟩⟩ diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/VectorProduct.lean b/LeanPool/CompositionAlgebrasOverRings/Module/VectorProduct.lean new file mode 100644 index 0000000000..98e63426ab --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Module/VectorProduct.lean @@ -0,0 +1,679 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.CrossProduct +public import Mathlib.LinearAlgebra.Determinant +public import Mathlib.LinearAlgebra.Dual.Basis +public import Mathlib.LinearAlgebra.Dual.Lemmas +public import Mathlib.LinearAlgebra.ExteriorPower.Basis + +/-! +# Vector product pairs (`GPR 22.14`) + +An **orientation** of a finitely generated projective `k`-module `M` of rank `3` is a `k`-linear +bijection `θ : ⋀³ M → k`. `GPR 22.14` uses `θ` and the induced orientation `θ*⁻¹` +of `M*`, only through the two **associated vector products** + + `M × M → M*`, `(v, w) ↦ v ×θ w`, `θ(u ∧ v ∧ w) = ⟨u ×θ v, w⟩`, + `M* × M* → M`, `(φ, ψ) ↦ φ ×θ ψ`, `θ*⁻¹(φ ∧ ψ ∧ χ) = ⟨χ, φ ×θ ψ⟩`, + +and it uses those only through three identities: both products are alternating, each is orthogonal +to its own arguments, and the two are linked by the Binet–Cauchy identity. This file packages +exactly that much data as `Module.VectorProductPair k M`. It constructs the pair both directly +from a basis of size three and from an orientation together with such a basis. + +Isolating the identities rather than the orientation is the same move as `Module.IsRankOnePairing` +in `Module/Invertible.lean`, which isolates what `GPR 22.12`'s twisted matrices need a line bundle +for. It buys three things: the algebra `ConicAlgebra.TwistedZor` built on a pair is a composition +algebra with *no* hypothesis on the rank of `M` (rank three is what makes pairs exist, not what +makes the axioms work); the free case, which is where `GPR`'s localization argument lands, is +available directly as `Module.VectorProductPair.ofBasis`; and the converse direction of +`GPR 22.15`, where the vector products are *read off* from the multiplication of a reduced +octonion algebra, produces a pair directly and never has to exhibit `θ`. + +## Main definitions + +* `Module.VectorProductPair k M` : a pair of vector products `M × M → M*` and `M* × M* → M` + satisfying the three identities of `GPR (22.14.2)` and Binet–Cauchy. +* `Module.VectorProductPair.ofBasis` : the pair attached to a basis `(u₁, u₂, u₃)` of `M`, + whose orientation is `θ(u₁ ∧ u₂ ∧ u₃) = 1`. +* `Module.VectorProductPair.ofOrientationOfBasis` : the pair induced by an arbitrary orientation + of a based rank-three module. +* `Module.Basis.dualCoord` : the coordinates of a functional along the dual basis, + `M* ≃ (ι → k)`. + +## Main results + +* `Module.VectorProductPair.cross_swap`, `crossDual_swap` : the products are anticommutative. +* `Module.VectorProductPair.cross_apply_right`, `apply_crossDual_right` : orthogonality to the + second argument as well as the first. +* `Module.Basis.apply_eq_dotProduct` : in the coordinates of a finite basis and its dual basis, + the canonical pairing `M* × M → k` is the dot product. This is what makes a basis of size three + produce a vector product pair, and it is stated for an arbitrary finite basis. +* `Module.orientationAlternating_mul_dualOrientationAlternating` : the primal and dual volume + coefficients are inverse, the basis calculation behind Binet–Cauchy. +* `Module.Basis.det_mul_det_dualBasis` : for a finite basis, the product of the determinant forms + of the basis and of its dual basis is the determinant of the matrix of pairings. + +## Implementation notes + +⚠ **The orientation is not part of the data.** `GPR 22.14` starts from `(M, θ)` with `M` of +rank three; a `VectorProductPair` is what `θ` produces. The construction here proves the based +calculation by dualizing `θ` through the canonical exterior-power pairing (`GPR 21.7`) and +checking that the two volume coefficients are inverse. The arbitrary finite-projective case is +proved by localization in `Composition.Reduced.Orientation`. + +The three axioms are stated with the *left* argument in the degenerate position +(`cross_apply_left`, `apply_crossDual_left`); the right-hand versions follow from +anticommutativity, which in turn follows from `cross_self`. Anticommutativity is therefore not an +axiom, and neither is the alternating character of the trilinear form +`(u, v, w) ↦ ⟨u ×θ v, w⟩`, which is the conjunction of the two. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 21.7, 21.8, 22.14. +-/ + +@[expose] public section + +universe u v + +open Matrix + +namespace Module + +variable (k : Type u) (M : Type v) [CommRing k] [AddCommGroup M] [Module k M] + +/-- A **pair of associated vector products** on a `k`-module `M` (`GPR 22.14`): `k`-bilinear maps + + `× : M × M → M*`, `×* : M* × M* → M`, + +both alternating, each orthogonal to its own arguments, and linked by the Binet–Cauchy identity +`⟨v × w, φ ×* ψ⟩ = ⟨φ, v⟩⟨ψ, w⟩ - ⟨φ, w⟩⟨ψ, v⟩`. + +`GPR 22.14` obtains such a pair from an orientation `θ : ⋀³ M ≅ k` of a rank-three projective +module, by `θ(u ∧ v ∧ w) = ⟨u × v, w⟩` and +`θ*⁻¹(φ ∧ ψ ∧ χ) = ⟨χ, φ ×* ψ⟩`; the identities below are exactly the alternating +character of the two orientations and `GPR (22.14.1)`. The rank +plays no role afterwards, so it is not part of this definition — see the module docstring. -/ +structure VectorProductPair where + /-- The vector product `M × M → M*`, `(v, w) ↦ v ×θ w`. -/ + cross : M →ₗ[k] M →ₗ[k] Module.Dual k M + /-- The vector product `M* × M* → M`, `(φ, ψ) ↦ φ ×θ ψ`, of the induced orientation of + `M*`. -/ + crossDual : Module.Dual k M →ₗ[k] Module.Dual k M →ₗ[k] M + /-- The vector product is alternating. -/ + cross_self (v : M) : cross v v = 0 + /-- The dual vector product is alternating. -/ + crossDual_self (φ : Module.Dual k M) : crossDual φ φ = 0 + /-- `⟨v × w, v⟩ = θ(v ∧ w ∧ v) = 0`. -/ + cross_apply_left (v w : M) : cross v w v = 0 + /-- `⟨φ, φ ×* ψ⟩ = θ*⁻¹(φ ∧ ψ ∧ φ) = 0`. -/ + apply_crossDual_left (φ ψ : Module.Dual k M) : φ (crossDual φ ψ) = 0 + /-- The **Binet–Cauchy identity** linking the two products, `GPR (22.14.1)`. -/ + cross_apply_crossDual (v w : M) (φ ψ : Module.Dual k M) : + cross v w (crossDual φ ψ) = φ v * ψ w - φ w * ψ v + +/-- If a ternary function vanishes whenever any pair of its arguments agrees, then it vanishes on +a `Fin 3`-indexed tuple whenever two distinct entries agree. This is the combinatorial half of +`map_eq_zero_of_eq'` for both alternating forms below. For each vector product, two hypotheses +come from fields of `VectorProductPair`; the third is the derived right-orthogonality identity. -/ +theorem fin_three_eq_zero_of_apply_eq {X N : Type*} [Zero N] (f : X → X → X → N) + (h₁ : ∀ v w, f v v w = 0) (h₂ : ∀ v w, f v w v = 0) (h₃ : ∀ v w, f v w w = 0) + (x : Fin 3 → X) {i j : Fin 3} (hij : x i = x j) (hne : i ≠ j) : + f (x 0) (x 1) (x 2) = 0 := by + fin_cases i <;> fin_cases j + · exact (hne rfl).elim + · rw [show x 0 = x 1 from hij]; exact h₁ _ _ + · rw [show x 0 = x 2 from hij]; exact h₂ _ _ + · rw [show x 1 = x 0 from hij]; exact h₁ _ _ + · exact (hne rfl).elim + · rw [show x 1 = x 2 from hij]; exact h₃ _ _ + · rw [show x 2 = x 0 from hij]; exact h₂ _ _ + · rw [show x 2 = x 1 from hij]; exact h₃ _ _ + · exact (hne rfl).elim + +namespace VectorProductPair + +variable {k M} (P : VectorProductPair k M) + +/-- Two vector-product pairs are equal when their two bilinear maps are equal. -/ +@[ext] theorem ext {P Q : VectorProductPair k M} (hcross : P.cross = Q.cross) + (hcrossDual : P.crossDual = Q.crossDual) : P = Q := by + cases P + cases Q + dsimp only at hcross hcrossDual + subst hcross + subst hcrossDual + rfl + +/-- The vector product is anticommutative. -/ +theorem cross_swap (v w : M) : P.cross v w = -P.cross w v := by + have h := P.cross_self (v + w) + simp only [map_add, LinearMap.add_apply, P.cross_self, zero_add, add_zero] at h + exact eq_neg_of_add_eq_zero_right h + +/-- The dual vector product is anticommutative. -/ +theorem crossDual_swap (φ ψ : Module.Dual k M) : P.crossDual φ ψ = -P.crossDual ψ φ := by + have h := P.crossDual_self (φ + ψ) + simp only [map_add, LinearMap.add_apply, P.crossDual_self, zero_add, add_zero] at h + exact eq_neg_of_add_eq_zero_right h + +/-- `⟨v × w, w⟩ = θ(v ∧ w ∧ w) = 0`. -/ +theorem cross_apply_right (v w : M) : P.cross v w w = 0 := by + rw [P.cross_swap, LinearMap.neg_apply, P.cross_apply_left, neg_zero] + +/-- `⟨ψ, φ ×* ψ⟩ = θ*⁻¹(φ ∧ ψ ∧ ψ) = 0`. -/ +theorem apply_crossDual_right (φ ψ : Module.Dual k M) : ψ (P.crossDual φ ψ) = 0 := by + rw [P.crossDual_swap, map_neg, P.apply_crossDual_left, neg_zero] + +/-- The alternating trilinear form `(u, v, w) ↦ ⟨u × v, w⟩` associated to the first +vector product. -/ +def crossAlternating : M [⋀^Fin 3]→ₗ[k] k where + toMultilinearMap := MultilinearMap.mk' (fun x ↦ P.cross (x 0) (x 1) (x 2)) + (by intro x i y z; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + (by intro x i r y; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + map_eq_zero_of_eq' x i j hij hne := + fin_three_eq_zero_of_apply_eq (fun a b c ↦ P.cross a b c) + (fun v w ↦ by rw [P.cross_self, LinearMap.zero_apply]) P.cross_apply_left + P.cross_apply_right x hij hne + +@[simp] theorem crossAlternating_apply (x : Fin 3 → M) : + P.crossAlternating x = P.cross (x 0) (x 1) (x 2) := rfl + +/-- The alternating trilinear form `(φ, ψ, χ) ↦ ⟨φ, ψ ×* χ⟩` associated to the +dual vector product. -/ +def crossDualAlternating : Module.Dual k M [⋀^Fin 3]→ₗ[k] k where + toMultilinearMap := MultilinearMap.mk' (fun x ↦ x 0 (P.crossDual (x 1) (x 2))) + (by intro x i y z; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + (by intro x i r y; fin_cases i <;> simp [Function.update, Fin.ext_iff]) + map_eq_zero_of_eq' x i j hij hne := + fin_three_eq_zero_of_apply_eq (fun a b c ↦ a (P.crossDual b c)) P.apply_crossDual_left + (fun v w ↦ P.apply_crossDual_right w v) + (fun v w ↦ by rw [P.crossDual_self, map_zero]) x hij hne + +@[simp] theorem crossDualAlternating_apply (x : Fin 3 → Module.Dual k M) : + P.crossDualAlternating x = x 0 (P.crossDual (x 1) (x 2)) := rfl + +end VectorProductPair + +/-! ### The pair attached to a basis + +For a basis `(u₁, u₂, u₃)`, the orientation `θ(u₁ ∧ u₂ ∧ u₃) = 1` makes the basis +self-dual, and both vector products become the ordinary cross product of `k³` read in +coordinates. This is the case `GPR 22.14` reduces to, and it is the only construction of a pair +in this file. -/ + +namespace Basis + +variable {k M} {ι : Type*} [Fintype ι] [DecidableEq ι] (b : Module.Basis ι k M) + +/-- The coordinates of a linear functional along the basis dual to `b`, as an equivalence +`M* ≃ (ι → k)`. Together with `b.equivFun : M ≃ (ι → k)` it makes `b` self-dual: the +canonical pairing becomes the dot product (`Module.Basis.apply_eq_dotProduct`). -/ +noncomputable def dualCoord : Module.Dual k M ≃ₗ[k] (ι → k) := b.dualBasis.equivFun + +@[simp] theorem dualCoord_apply (φ : Module.Dual k M) (i : ι) : b.dualCoord φ i = φ (b i) := + b.dualBasis_equivFun φ i + +/-- **In the coordinates of a finite basis and its dual basis, the canonical pairing is the dot +product.** -/ +theorem apply_eq_dotProduct (φ : Module.Dual k M) (u : M) : + φ u = b.dualCoord φ ⬝ᵥ b.equivFun u := by + conv_lhs => rw [← b.sum_repr u] + rw [map_sum] + simp [dotProduct, mul_comm] + +theorem dualCoord_symm_apply (f : ι → k) (u : M) : + b.dualCoord.symm f u = f ⬝ᵥ b.equivFun u := by + rw [apply_eq_dotProduct b, LinearEquiv.apply_symm_apply] + +theorem apply_equivFun_symm (φ : Module.Dual k M) (g : ι → k) : + φ (b.equivFun.symm g) = b.dualCoord φ ⬝ᵥ g := by + rw [apply_eq_dotProduct b, LinearEquiv.apply_symm_apply] + +end Basis + +section OfBasis + +variable {k M} (b : Module.Basis (Fin 3) k M) + +/-- The cross product of `M` induced by a basis of size three: the ordinary cross product of the +coordinate vectors, read back as a linear functional through the dual basis. -/ +noncomputable def crossOfBasis : M →ₗ[k] M →ₗ[k] Module.Dual k M := + (crossProduct.compl₁₂ b.equivFun.toLinearMap b.equivFun.toLinearMap).compr₂ + b.dualCoord.symm.toLinearMap + +/-- The cross product of `M*` induced by a basis of size three. -/ +noncomputable def crossDualOfBasis : Module.Dual k M →ₗ[k] Module.Dual k M →ₗ[k] M := + (crossProduct.compl₁₂ b.dualCoord.toLinearMap b.dualCoord.toLinearMap).compr₂ + b.equivFun.symm.toLinearMap + +@[simp] theorem crossOfBasis_apply (v w : M) : + crossOfBasis b v w = b.dualCoord.symm (b.equivFun v ⨯₃ b.equivFun w) := rfl + +@[simp] theorem crossDualOfBasis_apply (φ ψ : Module.Dual k M) : + crossDualOfBasis b φ ψ = b.equivFun.symm (b.dualCoord φ ⨯₃ b.dualCoord ψ) := rfl + +/-- **The vector product pair attached to a basis** `(u₁, u₂, u₃)` of `M`: the pair of the +orientation `θ` with `θ(u₁ ∧ u₂ ∧ u₃) = 1`. The products become the cross product in the +coordinates of `b`; this is self-dual for that orientation, so the axioms are the +classical identities +`u ⬝ᵥ (u ⨯₃ v) = 0` and the Binet–Cauchy identity `Matrix.cross_dot_cross`. -/ +noncomputable def VectorProductPair.ofBasis : VectorProductPair k M where + cross := crossOfBasis b + crossDual := crossDualOfBasis b + cross_self v := by simp + crossDual_self φ := by simp + cross_apply_left v w := by + rw [crossOfBasis_apply, Basis.dualCoord_symm_apply, dotProduct_comm, dot_self_cross] + apply_crossDual_left φ ψ := by + rw [crossDualOfBasis_apply, Basis.apply_equivFun_symm, dot_self_cross] + cross_apply_crossDual v w φ ψ := by + rw [crossOfBasis_apply, crossDualOfBasis_apply, Basis.dualCoord_symm_apply, + LinearEquiv.apply_symm_apply, cross_dot_cross, Basis.apply_eq_dotProduct b φ v, + Basis.apply_eq_dotProduct b ψ w, Basis.apply_eq_dotProduct b φ w, + Basis.apply_eq_dotProduct b ψ v, + dotProduct_comm (b.equivFun v) (b.dualCoord φ), + dotProduct_comm (b.equivFun v) (b.dualCoord ψ), + dotProduct_comm (b.equivFun w) (b.dualCoord φ), + dotProduct_comm (b.equivFun w) (b.dualCoord ψ)] + ring + +@[simp] theorem VectorProductPair.ofBasis_cross : + (VectorProductPair.ofBasis b).cross = crossOfBasis b := rfl + +@[simp] theorem VectorProductPair.ofBasis_crossDual : + (VectorProductPair.ofBasis b).crossDual = crossDualOfBasis b := rfl + +/-- The trilinear form of the basis-built vector product is the determinant form of the basis. -/ +theorem VectorProductPair.crossAlternating_ofBasis : + (VectorProductPair.ofBasis b).crossAlternating = b.det := by + apply AlternatingMap.ext + intro x + rw [VectorProductPair.crossAlternating_apply, VectorProductPair.ofBasis_cross, + crossOfBasis_apply, Basis.dualCoord_symm_apply, dotProduct_comm, + triple_product_permutation, + triple_product_eq_det, Basis.det_apply, ← Matrix.det_transpose] + congr 1 + ext i j + fin_cases i <;> simp [Matrix.vecCons, Matrix.vecEmpty, Module.Basis.toMatrix] + rfl + +/-- The trilinear form of the basis-built dual vector product is the determinant form of the +dual basis. -/ +theorem VectorProductPair.crossDualAlternating_ofBasis : + (VectorProductPair.ofBasis b).crossDualAlternating = b.dualBasis.det := by + apply AlternatingMap.ext + intro x + rw [VectorProductPair.crossDualAlternating_apply, VectorProductPair.ofBasis_crossDual, + crossDualOfBasis_apply, Basis.apply_equivFun_symm, triple_product_eq_det, + Basis.det_apply, ← Matrix.det_transpose] + congr 1 + ext i j + fin_cases i + · simp [Matrix.vecCons, Matrix.vecEmpty, Basis.dualCoord, Module.Basis.toMatrix] + · simp [Matrix.vecCons, Matrix.vecEmpty, Basis.dualCoord, Module.Basis.toMatrix] + · change b.dualBasis.repr (x 2) j = b.dualBasis.repr (x 2) j + rfl + +/-- Relative to a basis of size three, every first vector product is a scalar multiple of the +basis-built cross product. The scalar is its oriented volume on that basis. -/ +theorem VectorProductPair.cross_eq_smul_crossOfBasis (P : VectorProductPair k M) : + P.cross = P.crossAlternating b • crossOfBasis b := by + ext u v w + have h := DFunLike.congr_fun (P.crossAlternating.eq_smul_basis_det b) ![u, v, w] + rw [← VectorProductPair.crossAlternating_ofBasis b] at h + simpa using h + +/-- Relative to the dual basis, every dual vector product is a scalar multiple of the +basis-built dual cross product. -/ +theorem VectorProductPair.crossDual_eq_smul_crossDualOfBasis (P : VectorProductPair k M) : + P.crossDual = P.crossDualAlternating b.dualBasis • crossDualOfBasis b := by + ext φ ψ + rw [b.ext_elem_iff] + intro i + have h := DFunLike.congr_fun + (P.crossDualAlternating.eq_smul_basis_det b.dualBasis) ![b.dualBasis i, φ, ψ] + rw [← VectorProductPair.crossDualAlternating_ofBasis b] at h + fin_cases i <;> + simpa [Basis.dualBasis_apply, crossDualOfBasis_apply, cross_apply, + Fin.sum_univ_succ] using h + +/-- The two scalar coefficients of a vector-product pair relative to a basis are inverse. This is +Binet–Cauchy evaluated on the first two basis vectors and their duals. -/ +theorem VectorProductPair.cross_coeff_mul_crossDual_coeff (P : VectorProductPair k M) : + P.crossAlternating b * P.crossDualAlternating b.dualBasis = 1 := by + have hcross : P.cross (b 0) (b 1) = + P.crossAlternating b • b.dualBasis 2 := by + rw [P.cross_eq_smul_crossOfBasis b] + simp only [LinearMap.smul_apply] + congr 1 + apply b.dualCoord.injective + rw [crossOfBasis_apply, LinearEquiv.apply_symm_apply] + ext i + fin_cases i <;> simp [cross_apply, Basis.dualCoord_apply] + have hcrossDual : P.crossDual (b.dualBasis 0) (b.dualBasis 1) = + P.crossDualAlternating b.dualBasis • b 2 := by + rw [P.crossDual_eq_smul_crossDualOfBasis b] + simp only [LinearMap.smul_apply] + congr 1 + apply b.equivFun.injective + ext i + fin_cases i <;> simp [crossDualOfBasis_apply, cross_apply, Fin.sum_univ_succ] + have h := P.cross_apply_crossDual (b 0) (b 1) (b.dualBasis 0) (b.dualBasis 1) + rw [hcross, hcrossDual] at h + simpa [Basis.dualBasis_apply, mul_comm] using h + +/-- The volume coefficient of a vector-product pair in any basis is a unit. -/ +theorem VectorProductPair.isUnit_crossAlternating_basis (P : VectorProductPair k M) : + IsUnit (P.crossAlternating b) := + isUnit_iff_exists_inv.mpr + ⟨P.crossDualAlternating b.dualBasis, P.cross_coeff_mul_crossDual_coeff b⟩ + +/-- Every vector-product pair on a free module of rank three is the pair attached to a suitably +rescaled basis. -/ +theorem VectorProductPair.exists_eq_ofBasis (b : Module.Basis (Fin 3) k M) + (P : VectorProductPair k M) : + ∃ b' : Module.Basis (Fin 3) k M, P = VectorProductPair.ofBasis b' := by + let hu := P.isUnit_crossAlternating_basis b + let l : kˣ := hu.unit + let w : Fin 3 → kˣ := fun i ↦ if i = 0 then l⁻¹ else 1 + let b' := b.unitsSMul w + have hl : (l : k) = P.crossAlternating b := hu.unit_spec.symm + have hw : ∏ i, w i = l⁻¹ := by + simp [w] + have hcoeff : (VectorProductPair.ofBasis b').crossAlternating b = + P.crossAlternating b := by + rw [VectorProductPair.crossAlternating_ofBasis, b.det_unitsSMul] + simp [hw, hl, Basis.det_self] + have hcross : (VectorProductPair.ofBasis b').cross = P.cross := by + rw [(VectorProductPair.ofBasis b').cross_eq_smul_crossOfBasis b, + P.cross_eq_smul_crossOfBasis b, hcoeff] + have hdualCoeff : (VectorProductPair.ofBasis b').crossDualAlternating b.dualBasis = + P.crossDualAlternating b.dualBasis := by + apply hu.mul_left_cancel + calc + (l : k) * (VectorProductPair.ofBasis b').crossDualAlternating b.dualBasis = + (VectorProductPair.ofBasis b').crossAlternating b * + (VectorProductPair.ofBasis b').crossDualAlternating b.dualBasis := by + rw [hl, hcoeff] + _ = 1 := (VectorProductPair.ofBasis b').cross_coeff_mul_crossDual_coeff b + _ = P.crossAlternating b * P.crossDualAlternating b.dualBasis := + (P.cross_coeff_mul_crossDual_coeff b).symm + _ = (l : k) * P.crossDualAlternating b.dualBasis := by rw [hl] + have hcrossDual : (VectorProductPair.ofBasis b').crossDual = P.crossDual := by + rw [(VectorProductPair.ofBasis b').crossDual_eq_smul_crossDualOfBasis b, + P.crossDual_eq_smul_crossDualOfBasis b, hdualCoeff] + refine ⟨b', ?_⟩ + exact VectorProductPair.ext hcross.symm hcrossDual.symm + +end OfBasis + +/-! ### The pair attached to an orientation of a based module -/ + +section Orientation + +variable {k M} + +/-- A cyclic permutation of three arguments preserves an alternating trilinear map. -/ +theorem alternating_fin_three_cycle {N : Type*} [AddCommGroup N] [Module k N] + (a : M [⋀^Fin 3]→ₗ[k] N) (x y z : M) : + a ![x, y, z] = a ![y, z, x] := by + have h₁ := a.map_swap ![x, y, z] (show (0 : Fin 3) ≠ 1 by decide) + have h₂ := a.map_swap ![y, x, z] (show (1 : Fin 3) ≠ 2 by decide) + have heq₁ : ![x, y, z] ∘ Equiv.swap (0 : Fin 3) 1 = ![y, x, z] := by + ext i + fin_cases i <;> rfl + have heq₂ : ![y, x, z] ∘ Equiv.swap (1 : Fin 3) 2 = ![y, z, x] := by + ext i + fin_cases i <;> rfl + rw [heq₁] at h₁ + rw [heq₂] at h₂ + rw [h₂, h₁, neg_neg] + +/-- The alternating volume form obtained from an orientation `θ : ⋀³ M ≃ k`. -/ +noncomputable def orientationAlternating + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : M [⋀^Fin 3]→ₗ[k] k := + theta.toLinearMap.compAlternatingMap (exteriorPower.ιMulti k 3) + +@[simp] theorem orientationAlternating_apply + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (x : Fin 3 → M) : + orientationAlternating theta x = theta (exteriorPower.ιMulti k 3 x) := rfl + +/-- The volume form on `M*` dual to an orientation of `M`. It evaluates the canonical pairing +with the oriented volume element `θ⁻¹(1)`; this is the duality of `GPR 21.7`. -/ +noncomputable def dualOrientationAlternating + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : + Module.Dual k M [⋀^Fin 3]→ₗ[k] k := + (Module.Dual.eval k (⋀[k]^3 M) (theta.symm 1)).compAlternatingMap + (exteriorPower.alternatingMapToDual k M 3) + +@[simp] theorem dualOrientationAlternating_apply + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (f : Fin 3 → Module.Dual k M) : + dualOrientationAlternating theta f = + exteriorPower.pairingDual k M 3 (exteriorPower.ιMulti k 3 f) (theta.symm 1) := by + simp [dualOrientationAlternating, exteriorPower.pairingDual] + +/-- The primal and dual volume forms defined by an orientation multiply to the determinant +pairing. This basis-free identity is the scalar form of the perfect exterior-power duality in +`GPR 21.7`. -/ +theorem orientationAlternating_mul_dualOrientationAlternating_apply + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (x : Fin 3 → M) (f : Fin 3 → Module.Dual k M) : + orientationAlternating theta x * dualOrientationAlternating theta f = + Matrix.det (fun i j ↦ f i (x j)) := by + have hx : exteriorPower.ιMulti k 3 x = + theta (exteriorPower.ιMulti k 3 x) • theta.symm 1 := by + apply theta.injective + simp + rw [orientationAlternating_apply, dualOrientationAlternating_apply] + calc + theta (exteriorPower.ιMulti k 3 x) * + exteriorPower.pairingDual k M 3 (exteriorPower.ιMulti k 3 f) (theta.symm 1) = + exteriorPower.pairingDual k M 3 (exteriorPower.ιMulti k 3 f) + (theta (exteriorPower.ιMulti k 3 x) • theta.symm 1) := by + rw [map_smul, smul_eq_mul] + _ = exteriorPower.pairingDual k M 3 (exteriorPower.ιMulti k 3 f) + (exteriorPower.ιMulti k 3 x) := by rw [← hx] + _ = Matrix.det (fun i j ↦ f i (x j)) := by + simp only [exteriorPower.pairingDual_ιMulti_ιMulti] + rw [show (Matrix.of fun i j ↦ f j (x i)) = + (Matrix.of fun i j ↦ f i (x j))ᵀ by rfl, Matrix.det_transpose] + rfl + +/-- The vector product `M × M → M*` induced by an orientation. -/ +noncomputable def crossOfOrientation + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : M →ₗ[k] M →ₗ[k] Module.Dual k M := + let z : M [⋀^Fin 0]→ₗ[k] k ≃ₗ[k] k := + AlternatingMap.constLinearEquivOfIsEmpty.symm + let y₁ : M [⋀^Fin 1]→ₗ[k] k →ₗ[k] Module.Dual k M := + LinearMap.llcomp k M (M [⋀^Fin 0]→ₗ[k] k) k z ∘ₗ + AlternatingMap.curryLeftLinearMap + let y₂ : M [⋀^Fin 2]→ₗ[k] k →ₗ[k] M →ₗ[k] Module.Dual k M := + LinearMap.llcomp k M (M [⋀^Fin 1]→ₗ[k] k) (Module.Dual k M) y₁ ∘ₗ + AlternatingMap.curryLeftLinearMap + LinearMap.llcomp k M (M [⋀^Fin 2]→ₗ[k] k) (M →ₗ[k] Module.Dual k M) y₂ + (orientationAlternating theta).curryLeft + +@[simp] theorem crossOfOrientation_apply + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (v w x : M) : + crossOfOrientation theta v w x = orientationAlternating theta ![v, w, x] := rfl + +/-- The vector product `M* × M* → M` induced by the dual orientation. Projective +reflexivity identifies the bidual value of the curried volume form with an element of `M`. -/ +noncomputable def crossDualOfOrientation [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) : + Module.Dual k M →ₗ[k] Module.Dual k M →ₗ[k] M := + let z : Module.Dual k M [⋀^Fin 0]→ₗ[k] k ≃ₗ[k] k := + AlternatingMap.constLinearEquivOfIsEmpty.symm + let y₁ : Module.Dual k M [⋀^Fin 1]→ₗ[k] k →ₗ[k] + Module.Dual k (Module.Dual k M) := + LinearMap.llcomp k (Module.Dual k M) (Module.Dual k M [⋀^Fin 0]→ₗ[k] k) k z ∘ₗ + AlternatingMap.curryLeftLinearMap + let y₂ : Module.Dual k M [⋀^Fin 2]→ₗ[k] k →ₗ[k] + Module.Dual k M →ₗ[k] Module.Dual k (Module.Dual k M) := + LinearMap.llcomp k (Module.Dual k M) (Module.Dual k M [⋀^Fin 1]→ₗ[k] k) + (Module.Dual k (Module.Dual k M)) y₁ ∘ₗ AlternatingMap.curryLeftLinearMap + let b : Module.Dual k M →ₗ[k] Module.Dual k M →ₗ[k] + Module.Dual k (Module.Dual k M) := + LinearMap.llcomp k (Module.Dual k M) (Module.Dual k M [⋀^Fin 2]→ₗ[k] k) + (Module.Dual k M →ₗ[k] Module.Dual k (Module.Dual k M)) y₂ + (dualOrientationAlternating theta).curryLeft + b.compr₂ (Module.evalEquiv k M).symm.toLinearMap + +@[simp] theorem apply_crossDualOfOrientation [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (f g h : Module.Dual k M) : + h (crossDualOfOrientation theta f g) = dualOrientationAlternating theta ![f, g, h] := by + simp [crossDualOfOrientation] + +/-- In a basis, the orientation-induced vector product is its volume coefficient times the +standard basis cross product. -/ +theorem crossOfOrientation_eq_smul_crossOfBasis + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + crossOfOrientation theta = orientationAlternating theta b • crossOfBasis b := by + ext u v w + have h := DFunLike.congr_fun ((orientationAlternating theta).eq_smul_basis_det b) ![u, v, w] + rw [← VectorProductPair.crossAlternating_ofBasis b] at h + simpa using h + +/-- In the dual basis, the dual orientation-induced product is its volume coefficient times the +standard dual cross product. -/ +theorem crossDualOfOrientation_eq_smul_crossDualOfBasis + [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + crossDualOfOrientation theta = + dualOrientationAlternating theta b.dualBasis • crossDualOfBasis b := by + ext f g + apply (Module.evalEquiv k M).injective + ext h + change h (crossDualOfOrientation theta f g) = + h ((dualOrientationAlternating theta b.dualBasis • crossDualOfBasis b) f g) + simp only [LinearMap.smul_apply, smul_eq_mul, map_smul] + rw [apply_crossDualOfOrientation] + rw [← alternating_fin_three_cycle (dualOrientationAlternating theta) h f g] + have hdet := DFunLike.congr_fun + ((dualOrientationAlternating theta).eq_smul_basis_det b.dualBasis) ![h, f, g] + rw [← VectorProductPair.crossDualAlternating_ofBasis b] at hdet + exact hdet + +/-- The volume coefficients of an orientation and its dual are inverse. This is the based form +of exterior-power duality in `GPR 21.7` and the scalar identity behind `GPR (22.14.1)`. -/ +theorem orientationAlternating_mul_dualOrientationAlternating + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + orientationAlternating theta b * dualOrientationAlternating theta b.dualBasis = 1 := by + rcases subsingleton_or_nontrivial k with hk | hk + · exact Subsingleton.elim _ _ + let s : Set.powersetCard (Fin 3) 3 := + Set.powersetCard.ofFinEmbEquiv (OrderEmbedding.id (Fin 3)) + let omega : ⋀[k]^3 M := exteriorPower.ιMulti k 3 b + have homega : exteriorPower.ιMulti_family k 3 b s = omega := by + simp [s, omega, exteriorPower.ιMulti_family] + have hdual : exteriorPower.ιMulti k 3 b.dualBasis = + exteriorPower.ιMulti_family k 3 b.coord s := by + simp [s, exteriorPower.ιMulti_family] + have hm : (b.exteriorPower 3).repr (theta.symm 1) s = + dualOrientationAlternating theta b.dualBasis := by + rw [exteriorPower.basis_repr_apply, exteriorPower.ιMultiDual] + simp only [dualOrientationAlternating_apply] + rw [hdual] + have hsmul : theta.symm 1 = dualOrientationAlternating theta b.dualBasis • omega := by + apply (b.exteriorPower 3).repr.injective + ext t + have hts : t = s := by + apply Subtype.ext + rw [Finset.eq_univ_of_card t.val (t.prop.trans (Fintype.card_fin 3).symm)] + simp [s, Set.powersetCard.ofFinEmbEquiv_apply] + rw [hts, hm, map_smul] + simp only [Finsupp.smul_apply, smul_eq_mul] + rw [← homega, ← exteriorPower.basis_apply k 3 b s, Module.Basis.repr_self, + Finsupp.single_eq_same, mul_one] + calc + orientationAlternating theta b * dualOrientationAlternating theta b.dualBasis = + dualOrientationAlternating theta b.dualBasis * orientationAlternating theta b := + mul_comm _ _ + _ = theta (dualOrientationAlternating theta b.dualBasis • omega) := by + simp [omega, orientationAlternating_apply] + _ = theta (theta.symm 1) := by rw [hsmul] + _ = 1 := theta.apply_symm_apply 1 + +/-- **The based form of `GPR 22.14`.** An orientation of a finite projective module with a basis +of size three induces a pair of associated vector products. The products are defined directly +from the primal and dual volume forms; the basis is used only to prove Binet–Cauchy. -/ +noncomputable def VectorProductPair.ofOrientationOfBasis + [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + VectorProductPair k M where + cross := crossOfOrientation theta + crossDual := crossDualOfOrientation theta + cross_self v := by + ext w + rw [crossOfOrientation_apply] + change orientationAlternating theta ![v, v, w] = 0 + exact (orientationAlternating theta).map_eq_zero_of_eq ![v, v, w] + (by rfl) (show (0 : Fin 3) ≠ 1 by decide) + crossDual_self f := by + apply (Module.evalEquiv k M).injective + ext h + simp only [Module.evalEquiv_apply, Module.Dual.eval_apply, map_zero] + rw [apply_crossDualOfOrientation] + exact (dualOrientationAlternating theta).map_eq_zero_of_eq ![f, f, h] + (by rfl) (show (0 : Fin 3) ≠ 1 by decide) + cross_apply_left v w := by + rw [crossOfOrientation_apply] + exact (orientationAlternating theta).map_eq_zero_of_eq ![v, w, v] + (by rfl) (show (0 : Fin 3) ≠ 2 by decide) + apply_crossDual_left f g := by + rw [apply_crossDualOfOrientation] + exact (dualOrientationAlternating theta).map_eq_zero_of_eq ![f, g, f] + (by rfl) (show (0 : Fin 3) ≠ 2 by decide) + cross_apply_crossDual v w f g := by + rw [crossOfOrientation_eq_smul_crossOfBasis theta b, + crossDualOfOrientation_eq_smul_crossDualOfBasis theta b] + simp only [LinearMap.smul_apply, smul_eq_mul, map_smul] + rw [← mul_assoc, mul_comm (dualOrientationAlternating theta b.dualBasis) + (orientationAlternating theta b), + orientationAlternating_mul_dualOrientationAlternating theta b, one_mul] + exact (VectorProductPair.ofBasis b).cross_apply_crossDual v w f g + +@[simp] theorem VectorProductPair.ofOrientationOfBasis_cross + [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + (VectorProductPair.ofOrientationOfBasis theta b).cross = crossOfOrientation theta := rfl + +@[simp] theorem VectorProductPair.ofOrientationOfBasis_crossDual + [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b : Module.Basis (Fin 3) k M) : + (VectorProductPair.ofOrientationOfBasis theta b).crossDual = + crossDualOfOrientation theta := rfl + +/-- The pair constructed from an orientation does not depend on the basis used to verify its +axioms. -/ +theorem VectorProductPair.ofOrientationOfBasis_eq + [Module.Finite k M] [Module.Projective k M] + (theta : (⋀[k]^3 M) ≃ₗ[k] k) (b b' : Module.Basis (Fin 3) k M) : + VectorProductPair.ofOrientationOfBasis theta b = + VectorProductPair.ofOrientationOfBasis theta b' := + VectorProductPair.ext rfl rfl + +end Orientation + +/-- In the coordinates of a finite basis and its dual basis, the product of the two determinant +forms is the determinant of the matrix of pairings. -/ +theorem Basis.det_mul_det_dualBasis {R : Type u} [CommRing R] {N : Type v} [AddCommGroup N] + [Module R N] {ι : Type*} [Fintype ι] [DecidableEq ι] (b : Module.Basis ι R N) + (x : ι → N) (f : ι → Module.Dual R N) : + b.det x * b.dualBasis.det f = Matrix.det (.of fun i j ↦ f i (x j)) := by + rw [Basis.det_apply, Basis.det_apply, mul_comm, + ← Matrix.det_transpose (b.dualBasis.toMatrix f), ← Matrix.det_mul] + congr 1 + ext i j + rw [Matrix.mul_apply] + simp only [Matrix.transpose_apply, Basis.toMatrix_apply, Basis.dualBasis_repr, Matrix.of_apply] + conv_rhs => rw [← b.sum_repr (x j)] + simp only [map_sum, map_smul, smul_eq_mul, mul_comm] + +end Module diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean new file mode 100644 index 0000000000..9bb49b4af9 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean @@ -0,0 +1,507 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Moufang +public import Mathlib.RingTheory.NonUnitalSubring.Basic + +/-! +# Artin's theorem + +**Artin's theorem.** A non-associative ring is alternative if and only if every subring generated +by two elements is associative. + +## Proof strategy + +The hard direction follows Schafer's proof of Theorem 3.1. First prove the result for +non-associative monomials in the two generators, by strong induction on the sum of the three +degrees. At a fixed induction stage every shorter monomial can be reassociated so that its first +letter is exposed. Two of the three monomials begin with the same generator, and Schafer's +linearized Moufang identity reduces their associator to associators of smaller total degree. + +Finally, every element of `NonUnitalSubring.closure {a, b}` is an additive combination of such +monomials. Trilinearity of the associator therefore extends the monomial result to the closure. + +## The reduction + +The Teichmüller identity, mathlib's `associator_cocycle`, holds in *any* non-associative ring: + +`w * [x,y,z] - [wx, y, z] + [w, xy, z] - [w, x, yz] + [w,x,y] * z = 0` + +Say `n` is **nuclear in** `S` when `[n, y, z] = 0` for all `y, z ∈ S`. If `S` is closed under +multiplication, then the elements of `S` nuclear in `S` are closed under `0`, `+`, `-` (associator +additivity) and under `*` (Teichmüller — see `IsNuclearIn.mul`, where every term but `[wx, y, z]` +vanishes). So the nucleus of `S` is a subring of `S`. + +Consequently, if the generators `a, b` are nuclear in `S = ⟨a, b⟩`, the nucleus contains +`{a, b}`, hence contains the whole closure, hence equals `S` — exactly associativity of `S`. + +⚠ Note that **none of this uses alternativity**. Alternativity enters in the monomial argument +that proves `generators_nuclear`. + +## References + +* E. Artin, *Zur Theorie der hyperkomplexen Zahlen*, Abh. Math. Sem. Univ. Hamburg **5** (1927), + 251–260. +* Schafer, *An Introduction to Nonassociative Algebras*, §3, Theorem 3.1. +* Zhevlakov, Slin'ko, Shestakov, Shirshov, *Rings That Are Nearly Associative*, ch. 2. +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Ch. 13. +-/ + +@[expose] public section + +universe u + +/-! ## Non-associative monomials -/ + +/-- A nonempty, non-associatively parenthesized word in two letters. -/ +inductive NonAssocWord where + | left + | right + | mul (p q : NonAssocWord) + +namespace NonAssocWord + +/-- The number of letters in a non-associative word. -/ +@[simp] def degree : NonAssocWord → ℕ + | left | right => 1 + | mul p q => p.degree + q.degree + +/-- Evaluate a non-associative word at two elements. -/ +@[simp] def eval {α : Type u} [Mul α] (a b : α) : NonAssocWord → α + | left => a + | right => b + | mul p q => p.eval a b * q.eval a b + +/-- The one-letter word selected by a Boolean. -/ +def ofBool : Bool → NonAssocWord + | false => left + | true => right + +/-- The element selected by a Boolean. -/ +def letter {α : Type u} (a b : α) : Bool → α + | false => a + | true => b + +@[simp] theorem degree_pos (p : NonAssocWord) : 0 < p.degree := by + induction p with + | left => exact Nat.zero_lt_one + | right => exact Nat.zero_lt_one + | mul p q hp _ => + exact Nat.add_pos_left hp q.degree + +@[simp] theorem degree_ofBool (x : Bool) : (ofBool x).degree = 1 := by cases x <;> rfl + +@[simp] theorem eval_ofBool {α : Type u} [Mul α] (a b : α) (x : Bool) : + (ofBool x).eval a b = letter a b x := by + cases x <;> rfl + +/-- Evaluation of a word with its first letter exposed. -/ +def prependEval {α : Type u} [Mul α] (a b : α) (x : Bool) : + Option NonAssocWord → α + | none => letter a b x + | some p => letter a b x * p.eval a b + +/-- Degree of a word with its first letter exposed. -/ +def prependDegree : Option NonAssocWord → ℕ + | none => 1 + | some p => p.degree + 1 + +end NonAssocWord + +/-- Two-generated associativity, as a predicate on a ring. -/ +def TwoGeneratedAssoc (α : Type u) [NonUnitalNonAssocRing α] : Prop := + ∀ (a b : α) {x y z : α}, + x ∈ NonUnitalSubring.closure ({a, b} : Set α) → + y ∈ NonUnitalSubring.closure ({a, b} : Set α) → + z ∈ NonUnitalSubring.closure ({a, b} : Set α) → + (x * y) * z = x * (y * z) + +/-! ## Nuclearity relative to a set -/ + +section Nucleus + +variable {α : Type u} [NonUnitalNonAssocRing α] + +/-- `n` is **nuclear in** `S` if the associator vanishes whenever `n` occupies the first slot and +the other two arguments lie in `S`. + +In an alternative ring the associator is alternating, so this single condition is equivalent to +nuclearity in any of the three slots (`IsAlternative.associator_swap_left`, +`IsAlternative.associator_swap_right`). The proofs below need only the first-slot form. -/ +def IsNuclearIn (S : Set α) (n : α) : Prop := ∀ y ∈ S, ∀ z ∈ S, associator n y z = 0 + +namespace IsNuclearIn + +variable {S : Set α} {m n : α} + +theorem zero : IsNuclearIn S 0 := fun _ _ _ _ ↦ associator_zero_left _ _ + +theorem add (hm : IsNuclearIn S m) (hn : IsNuclearIn S n) : IsNuclearIn S (m + n) := by + intro y hy z hz + rw [associator_add_left, hm y hy z hz, hn y hy z hz, add_zero] + +theorem neg (hm : IsNuclearIn S m) : IsNuclearIn S (-m) := by + intro y hy z hz + rw [associator_neg_left, hm y hy z hz, neg_zero] + +/-- The nucleus is closed under multiplication. This is the Teichmüller identity +(`associator_cocycle`): with `w = m` and `x = n`, every term but `[mn, y, z]` vanishes. + +Requires `S` closed under multiplication, and `m, n ∈ S` (not merely nuclear in `S`). -/ +theorem mul (hS : ∀ x ∈ S, ∀ y ∈ S, x * y ∈ S) + (hm : IsNuclearIn S m) (hn : IsNuclearIn S n) (_hmS : m ∈ S) (hnS : n ∈ S) : + IsNuclearIn S (m * n) := by + intro y hy z hz + have key := associator_cocycle m n y z + have h1 : associator m (n * y) z = 0 := hm _ (hS _ hnS _ hy) _ hz + have h2 : associator m n (y * z) = 0 := hm _ hnS _ (hS _ hy _ hz) + have h3 : associator n y z = 0 := hn _ hy _ hz + have h4 : associator m n y = 0 := hm _ hnS _ hy + rw [h1, h2, h3, h4] at key + simpa using key + +end IsNuclearIn + +end Nucleus + +namespace IsAlternative + +/-! ## Easy direction -/ + +variable {α : Type u} [NonUnitalNonAssocRing α] + +/-- If every two-generated subring is associative, the left alternative law holds. -/ +theorem left_alt_of_two_generated_assoc (h : TwoGeneratedAssoc α) (a b : α) : + a * (a * b) = (a * a) * b := by + refine (h a b ?_ ?_ ?_).symm + · exact NonUnitalSubring.subset_closure (Or.inl rfl) + · exact NonUnitalSubring.subset_closure (Or.inl rfl) + · exact NonUnitalSubring.subset_closure (Or.inr rfl) + +/-- If every two-generated subring is associative, the right alternative law holds. -/ +theorem right_alt_of_two_generated_assoc (h : TwoGeneratedAssoc α) (a b : α) : + (b * a) * a = b * (a * a) := by + refine h a b ?_ ?_ ?_ + · exact NonUnitalSubring.subset_closure (Or.inr rfl) + · exact NonUnitalSubring.subset_closure (Or.inl rfl) + · exact NonUnitalSubring.subset_closure (Or.inl rfl) + +/-- **Artin's theorem, easy direction**: two-generated associativity implies alternativity. -/ +theorem of_two_generated_assoc (h : TwoGeneratedAssoc α) : IsAlternative α where + left_alt := left_alt_of_two_generated_assoc h + right_alt := right_alt_of_two_generated_assoc h + +/-! ## Hard direction -/ + +section Hard +variable [IsAlternative α] + +/-! ### The associator identities used by Schafer's induction -/ + +/-- A form of the right Moufang identity used in the proof of Artin's theorem +[Schafer, (3.7)]. -/ +theorem associator_mul_right_self (y x c : α) : + associator y (x * c) x = -associator y x c * x := by + simp only [associator] + rw [flexible, ← right_moufang x c y] + simp only [neg_mul] + rw [sub_mul] + abel + +/-- The linearization of `associator_mul_right_self` [Schafer, (3.8)]. -/ +theorem associator_mul_right_self_linearized (y x z c : α) : + associator y (x * c) z + associator y (z * c) x = + -associator y x c * z - associator y z c * x := by + have h := associator_mul_right_self y (x + z) c + have hx := associator_mul_right_self y x c + have hz := associator_mul_right_self y z c + simp only [add_mul, mul_add, associator_add_mid, associator_add_right, neg_add_rev, + neg_mul] at h + rw [hx, hz] at h + simp only [neg_mul] at h ⊢ + have h' := congrArg (fun w ↦ + w + associator y x c * x + associator y z c * z) h + abel_nf at h' ⊢ + exact h' + +/-- A cyclic permutation does not change an associator in an alternative ring. -/ +theorem associator_cyclic (x y z : α) : associator x y z = associator y z x := by + rw [associator_swap_left, associator_swap_right, neg_neg] + +/-- Swapping the outside arguments negates an associator. -/ +theorem associator_swap_outer (x y z : α) : associator x y z = -associator z y x := by + rw [associator_cyclic, associator_cyclic, associator_swap_right] + +open NonAssocWord + +omit [IsAlternative α] in +/-- If all associators of words of total degree less than `n` vanish, then every word of degree +less than `n` can be reassociated to expose its first letter. -/ +theorem exists_head (a b : α) {n : ℕ} + (h : ∀ p q r : NonAssocWord, + p.degree + q.degree + r.degree < n → + associator (p.eval a b) (q.eval a b) (r.eval a b) = 0) + (w : NonAssocWord) (hw : w.degree < n) : + ∃ x t, w.eval a b = prependEval a b x t ∧ w.degree = prependDegree t := by + induction w with + | left => exact ⟨false, none, rfl, rfl⟩ + | right => exact ⟨true, none, rfl, rfl⟩ + | mul p q ihp _ => + obtain ⟨x, t, hp, hdegree⟩ := ihp (by simp only [degree] at hw ⊢; omega) + cases t with + | none => + refine ⟨x, some q, ?_, ?_⟩ + · simpa only [eval, prependEval] using congrArg (· * q.eval a b) hp + · simp only [degree, prependDegree] at hdegree ⊢ + omega + | some p' => + have hassoc : + (letter a b x * p'.eval a b) * q.eval a b = + letter a b x * (p'.eval a b * q.eval a b) := by + apply (associator_eq_zero_iff _ _ _).mp + simpa only [eval_ofBool] using h (ofBool x) p' q (by + simp only [degree, degree_ofBool, prependDegree] at hw hdegree ⊢ + omega) + refine ⟨x, some (.mul p' q), ?_, ?_⟩ + · simp only [eval, prependEval] + rw [hp] + exact hassoc + · simp only [degree, prependDegree] at hw hdegree ⊢ + omega + +/-- Schafer's induction step when the last two words start with the same letter. -/ +theorem associator_prepend_same_head (a b : α) {n : ℕ} + (h : ∀ p q r : NonAssocWord, + p.degree + q.degree + r.degree < n → + associator (p.eval a b) (q.eval a b) (r.eval a b) = 0) + (p : NonAssocWord) (x : Bool) (qTail rTail : Option NonAssocWord) + (hdegree : p.degree + prependDegree qTail + prependDegree rTail = n) : + associator (p.eval a b) (prependEval a b x qTail) (prependEval a b x rTail) = 0 := by + cases qTail with + | none => + cases rTail with + | none => exact associator_self_right _ _ + | some r => + simp only [prependEval] + rw [associator_swap_right, associator_mul_right_self] + have hsmall := h p (ofBool x) r (by + simp only [prependDegree, degree_ofBool] at hdegree ⊢ + omega) + simp only [eval_ofBool] at hsmall + rw [hsmall, neg_zero, zero_mul, neg_zero] + | some q => + cases rTail with + | none => + simp only [prependEval] + rw [associator_mul_right_self] + have hsmall := h p (ofBool x) q (by + simp only [prependDegree, degree_ofBool] at hdegree ⊢ + omega) + simp only [eval_ofBool] at hsmall + rw [hsmall, neg_zero, zero_mul] + | some r => + have hpdegree := p.degree_pos + have hleft := h (.mul (ofBool x) r) (ofBool x) q (by + simp only [degree, degree_ofBool, prependDegree] at hdegree ⊢ + omega) + have hmid := h (.mul (ofBool x) r) p q (by + simp only [degree, degree_ofBool, prependDegree] at hdegree ⊢ + omega) + have hright := h (.mul p q) (ofBool x) r (by + simp only [degree, degree_ofBool, prependDegree] at hdegree ⊢ + omega) + simp only [eval, eval_ofBool] at hleft hmid hright + have hlast : + associator (letter a b x * r.eval a b) (p.eval a b * q.eval a b) + (letter a b x) = 0 := by + rw [associator_swap_outer, associator_cyclic, + associator_mul_right_self, hright, neg_zero, zero_mul, neg_zero] + have hlinear := associator_mul_right_self_linearized + (letter a b x * r.eval a b) (letter a b x) (p.eval a b) (q.eval a b) + rw [hleft, hmid, hlast, neg_zero, zero_mul, add_zero] at hlinear + simp only [zero_mul, sub_zero] at hlinear + simp only [prependEval] + calc + associator (p.eval a b) (letter a b x * q.eval a b) + (letter a b x * r.eval a b) = + -associator (letter a b x * r.eval a b) + (letter a b x * q.eval a b) (p.eval a b) := associator_swap_outer _ _ _ + _ = -0 := congrArg Neg.neg hlinear + _ = 0 := neg_zero + +/-- The associator of three non-associative monomials in two elements vanishes. This is the +monomial form of Artin's theorem [Schafer, Theorem 3.1]. -/ +theorem associator_word (a b : α) (p q r : NonAssocWord) : + associator (p.eval a b) (q.eval a b) (r.eval a b) = 0 := by + generalize hn : p.degree + q.degree + r.degree = n + induction n using Nat.strong_induction_on generalizing p q r with + | h n ih => + have lower : ∀ p' q' r' : NonAssocWord, + p'.degree + q'.degree + r'.degree < n → + associator (p'.eval a b) (q'.eval a b) (r'.eval a b) = 0 := by + intro p' q' r' hlt + exact ih _ hlt p' q' r' rfl + obtain ⟨xp, pt, hp, hpDegree⟩ := exists_head a b lower p (by + have hqpos := q.degree_pos + have hrpos := r.degree_pos + omega) + obtain ⟨xq, qt, hq, hqDegree⟩ := exists_head a b lower q (by + have hppos := p.degree_pos + have hrpos := r.degree_pos + omega) + obtain ⟨xr, rt, hr, hrDegree⟩ := exists_head a b lower r (by + have hppos := p.degree_pos + have hqpos := q.degree_pos + omega) + have hpigeon : xp = xq ∨ xq = xr ∨ xp = xr := by + cases xp <;> cases xq <;> cases xr <;> simp + rcases hpigeon with hpq | hqr | hpr + · subst xq + rw [associator_cyclic, associator_cyclic, hp, hq] + apply associator_prepend_same_head a b lower r xp pt qt + omega + · subst xr + rw [hq, hr] + apply associator_prepend_same_head a b lower p xq qt rt + omega + · subst xr + rw [associator_cyclic, hr, hp] + apply associator_prepend_same_head a b lower q xp rt pt + omega + +/-! ### From monomials to the additive closure -/ + +/-- Additive combinations of non-associative monomials in `a` and `b`. -/ +inductive WordSpan (a b : α) : α → Prop where + | word (p : NonAssocWord) : WordSpan a b (p.eval a b) + | zero : WordSpan a b 0 + | add {x y : α} : WordSpan a b x → WordSpan a b y → WordSpan a b (x + y) + | neg {x : α} : WordSpan a b x → WordSpan a b (-x) + +namespace WordSpan + +omit [IsAlternative α] in +/-- The additive span of words is closed under multiplication. -/ +theorem mul {a b x y : α} (hx : WordSpan a b x) (hy : WordSpan a b y) : + WordSpan a b (x * y) := by + induction hx generalizing y with + | word p => + induction hy with + | word q => exact word (.mul p q) + | zero => simpa only [mul_zero] using (zero : WordSpan a b 0) + | add _ _ ihx ihy => simpa only [mul_add] using ihx.add ihy + | neg _ ih => simpa only [mul_neg] using ih.neg + | zero => simpa only [zero_mul] using (zero : WordSpan a b 0) + | add _ _ ihx ihy => + simpa only [add_mul] using (ihx hy).add (ihy hy) + | neg _ ih => simpa only [neg_mul] using (ih hy).neg + +omit [IsAlternative α] in +/-- Every element of the non-associative ring closure is an additive combination of words. -/ +theorem of_mem_closure (a b : α) {x : α} + (hx : x ∈ NonUnitalSubring.closure ({a, b} : Set α)) : WordSpan a b x := by + induction hx using NonUnitalSubring.closure_induction with + | mem x hx => + change x = a ∨ x = b at hx + rcases hx with rfl | rfl + · exact word .left + · exact word .right + | zero => exact zero + | add _ _ _ _ ihx ihy => exact ihx.add ihy + | neg _ _ ih => exact ih.neg + | mul _ _ _ _ ihx ihy => exact ihx.mul ihy + +/-- A word is nuclear relative to the additive span of all words. -/ +theorem word_nuclear (a b : α) (p : NonAssocWord) : + IsNuclearIn {x | WordSpan a b x} (p.eval a b) := by + intro y hy z hz + induction hy generalizing z with + | word q => + induction hz with + | word r => exact associator_word a b p q r + | zero => exact associator_zero_right _ _ + | add _ _ ihx ihy => + rw [associator_add_right, ihx, ihy, add_zero] + | neg _ ih => rw [associator_neg_right, ih, neg_zero] + | zero => exact associator_zero_mid _ _ + | add _ _ ihx ihy => + rw [associator_add_mid, ihx z hz, ihy z hz, add_zero] + | neg _ ih => rw [associator_neg_mid, ih z hz, neg_zero] + +/-- Every additive combination of words is nuclear relative to the span. -/ +theorem nuclear {a b x : α} (hx : WordSpan a b x) : + IsNuclearIn {y | WordSpan a b y} x := by + induction hx with + | word p => exact word_nuclear a b p + | zero => exact IsNuclearIn.zero + | add _ _ ihx ihy => exact ihx.add ihy + | neg _ ih => exact ih.neg + +end WordSpan + +/-- The associator vanishes on any triple drawn from `{a, b}`: two of the three arguments coincide +by pigeonhole, and the associator is alternating. + +This is the base case of `generators_nuclear`. -/ +theorem associator_of_mem_pair (a b : α) {x y z : α} + (hx : x ∈ ({a, b} : Set α)) (hy : y ∈ ({a, b} : Set α)) (hz : z ∈ ({a, b} : Set α)) : + associator x y z = 0 := by + change x = a ∨ x = b at hx + change y = a ∨ y = b at hy + change z = a ∨ z = b at hz + rcases hx with rfl | rfl <;> rcases hy with rfl | rfl <;> rcases hz with rfl | rfl <;> + simp [associator_self_left, associator_self_right, associator_self_mid] + +/-- Each generator is nuclear in the non-associative subring generated by the pair. -/ +theorem generators_nuclear (a b : α) : + IsNuclearIn (NonUnitalSubring.closure ({a, b} : Set α) : Set α) a ∧ + IsNuclearIn (NonUnitalSubring.closure ({a, b} : Set α) : Set α) b := by + constructor + · intro y hy z hz + exact WordSpan.word_nuclear a b .left y (WordSpan.of_mem_closure a b hy) z + (WordSpan.of_mem_closure a b hz) + · intro y hy z hz + exact WordSpan.word_nuclear a b .right y (WordSpan.of_mem_closure a b hy) z + (WordSpan.of_mem_closure a b hz) + +/-- Every element of the closure is nuclear in the closure. + +Pure nucleus bookkeeping on top of `generators_nuclear`: the nuclear elements form a subring +(`IsNuclearIn.zero/add/neg/mul`), so they contain the closure of the generators. -/ +theorem nuclear_of_mem_closure (a b : α) {x : α} + (hx : x ∈ NonUnitalSubring.closure ({a, b} : Set α)) : + IsNuclearIn (NonUnitalSubring.closure ({a, b} : Set α) : Set α) x := by + have hab := generators_nuclear a b + have hS : ∀ u ∈ (NonUnitalSubring.closure ({a, b} : Set α) : Set α), + ∀ v ∈ (NonUnitalSubring.closure ({a, b} : Set α) : Set α), + u * v ∈ (NonUnitalSubring.closure ({a, b} : Set α) : Set α) := + fun _ hu _ hv ↦ mul_mem hu hv + induction hx using NonUnitalSubring.closure_induction with + | mem w hw => + change w = a ∨ w = b at hw + rcases hw with rfl | rfl + · exact hab.1 + · exact hab.2 + | zero => exact IsNuclearIn.zero + | add _ _ _ _ ihx ihy => exact ihx.add ihy + | neg _ _ ih => exact ih.neg + | mul _ _ hx' hy' ihx ihy => exact ihx.mul hS ihy hx' hy' + +/-- **Artin's theorem, hard direction**: in an alternative ring, the subring generated by any two +elements is associative. -/ +theorem artin_two_generated_assoc : TwoGeneratedAssoc α := by + intro a b x y z hx hy hz + exact (associator_eq_zero_iff x y z).mp (nuclear_of_mem_closure a b hx y hy z hz) + +end Hard + +/-- **Artin's theorem.** -/ +theorem isAlternative_iff_two_generated_assoc : + IsAlternative α ↔ TwoGeneratedAssoc α := + ⟨fun _ ↦ artin_two_generated_assoc, of_two_generated_assoc⟩ + +end IsAlternative diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Defs.lean new file mode 100644 index 0000000000..0f390b8a39 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Defs.lean @@ -0,0 +1,185 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.Group.Opposite +public import Mathlib.Algebra.Ring.Opposite +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Associator + +/-! +# Alternative rings and algebras + +An *alternative* multiplication satisfies the two alternative laws + +* **left alternative** `a * (a * b) = (a * a) * b` +* **right alternative** `(b * a) * a = b * (a * a)` + +Every associative multiplication is alternative; the octonions are the standard non-associative +example. Alternativity is the structural hypothesis under which composition algebras live +(`GPR 19.3`: every composition algebra is alternative). + +## Implementation notes + +`IsAlternative` is a **`Prop`-valued mixin on `[Mul α]`**, following `IsJordan` in +`Mathlib.Algebra.Jordan.Basic`. It deliberately does **not** bundle the ring structure: + +* the axioms are multiplicative equations and need neither addition nor negation, so `[Mul α]` is + the honest hypothesis; +* bundling would fuse "is a non-associative ring" with "satisfies the alternative laws", which + overview §2 forbids — algebra structure, norm regularity and module regularity are independent + axes; +* a bundled class carrying its own `NonAssocRing` parent diamonds against `ConicAlgebra`'s + `[NonAssocRing A] [Module k A] [SMulCommClass k A A] [IsScalarTower k A A]` (mathlib's `Algebra` + requires an associative `Semiring`), making `IsComposition → IsAlternative` awkward to state. + +One instance (`Semigroup.isAlternative`) covers every associative case, mirroring +`CommSemigroup.isCommJordan`. + +The associator characterizations live below `[NonUnitalNonAssocRing α]`, where subtraction exists. + +⚠ The linearizations are proved using additivity only — **no `Invertible 2`** — so they hold in +characteristic 2. Do not "simplify" them by halving. + +## Main results + +* `IsAlternative` : the mixin. +* `IsAlternative.associator_self_left/right/mid` : the associator vanishes on repeated arguments. +* `IsAlternative.associator_swap_left/right` : the associator is alternating. +* `IsAlternative.flexible` : `(a * b) * a = a * (b * a)`. +* `IsAlternative.left_alt_linearized`, `right_alt_linearized` : the linearized laws. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 13.2. +* Schafer, *An Introduction to Nonassociative Algebras*, §3. +* Zhevlakov et al., *Rings That Are Nearly Associative*, Ch. 2. +-/ + +@[expose] public section + +universe u + +/-- An **alternative** multiplication: the associator vanishes whenever two adjacent arguments +coincide. Stated on `[Mul α]` as a `Prop` mixin, following `IsJordan`. -/ +class IsAlternative (α : Type u) [Mul α] : Prop where + /-- Left alternative law: `a * (a * b) = (a * a) * b`. -/ + left_alt : ∀ a b : α, a * (a * b) = (a * a) * b + /-- Right alternative law: `(b * a) * a = b * (a * a)`. -/ + right_alt : ∀ a b : α, (b * a) * a = b * (a * a) + +namespace IsAlternative + +section Mul +variable {α : Type u} [Mul α] [IsAlternative α] + +theorem mul_mul_self_left (a b : α) : a * (a * b) = (a * a) * b := IsAlternative.left_alt a b + +theorem mul_self_mul_right (a b : α) : (b * a) * a = b * (a * a) := IsAlternative.right_alt a b + +end Mul + +/-- Every associative multiplication is alternative. This single instance replaces what a bundled +hierarchy would need four instances for. -/ +instance (priority := 100) _root_.Semigroup.isAlternative (α : Type u) [Semigroup α] : + IsAlternative α where + left_alt a b := (mul_assoc a a b).symm + right_alt a b := mul_assoc b a a + +section Ring +variable {α : Type u} [NonUnitalNonAssocRing α] [IsAlternative α] + +/-- The associator vanishes when the first two arguments coincide. -/ +theorem associator_self_left (a b : α) : associator a a b = 0 := by + simp [associator, mul_mul_self_left] + +/-- The associator vanishes when the last two arguments coincide. -/ +theorem associator_self_right (a b : α) : associator b a a = 0 := by + simp [associator, mul_self_mul_right] + +/-! ### The associator is alternating + +Linearizations of the two alternative laws. Additivity only — valid in characteristic 2. -/ + +/-- Linearized left alternative law: `⁅a, b, c⁆ + ⁅b, a, c⁆ = 0`. -/ +theorem associator_add_swap_left (a b c : α) : + associator a b c + associator b a c = 0 := by + have h := associator_self_left (a + b) c + rw [associator_add_left, associator_add_mid, associator_add_mid, + associator_self_left, associator_self_left, zero_add, add_zero] at h + exact h + +/-- Swapping the first two arguments negates the associator. -/ +theorem associator_swap_left (a b c : α) : associator a b c = -associator b a c := + eq_neg_of_add_eq_zero_left (associator_add_swap_left a b c) + +/-- Linearized right alternative law: `⁅a, b, c⁆ + ⁅a, c, b⁆ = 0`. -/ +theorem associator_add_swap_right (a b c : α) : + associator a b c + associator a c b = 0 := by + have h := associator_self_right (b + c) a + rw [associator_add_mid, associator_add_right, associator_add_right, + associator_self_right, associator_self_right, zero_add, add_zero] at h + exact h + +/-- Swapping the last two arguments negates the associator. -/ +theorem associator_swap_right (a b c : α) : associator a b c = -associator a c b := + eq_neg_of_add_eq_zero_left (associator_add_swap_right a b c) + +/-- The associator vanishes when the first and third arguments coincide. -/ +theorem associator_self_mid (a b : α) : associator a b a = 0 := by + rw [associator_swap_left a b a, associator_self_right, neg_zero] + +/-- **Flexible law**: `(a * b) * a = a * (b * a)`. -/ +theorem flexible (a b : α) : (a * b) * a = a * (b * a) := + (associator_eq_zero_iff a b a).mp (associator_self_mid a b) + +/-! ### Linearized alternative laws, multiplicative form -/ + +/-- `a * (b * x) + b * (a * x) = (a * b) * x + (b * a) * x`. -/ +theorem left_alt_linearized (a b x : α) : + a * (b * x) + b * (a * x) = (a * b) * x + (b * a) * x := by + calc + a * (b * x) + b * (a * x) = + ((a * b) * x - associator a b x) + + ((b * a) * x - associator b a x) := by + simp only [associator] + abel + _ = (a * b) * x + (b * a) * x - + (associator a b x + associator b a x) := by + abel + _ = (a * b) * x + (b * a) * x := by + rw [associator_add_swap_left] + simp + +/-- `(x * a) * b + (x * b) * a = x * (a * b) + x * (b * a)`. -/ +theorem right_alt_linearized (x a b : α) : + (x * a) * b + (x * b) * a = x * (a * b) + x * (b * a) := by + calc + (x * a) * b + (x * b) * a = + (x * (a * b) + associator x a b) + + (x * (b * a) + associator x b a) := by + simp only [associator] + abel + _ = x * (a * b) + x * (b * a) + + (associator x a b + associator x b a) := by + abel + _ = x * (a * b) + x * (b * a) := by + rw [associator_add_swap_right] + simp + +end Ring + +/-- The opposite of an alternative multiplication is alternative: the two laws swap. -/ +instance {α : Type u} [Mul α] [IsAlternative α] : IsAlternative αᵐᵒᵖ where + left_alt a b := by + obtain ⟨a⟩ := a; obtain ⟨b⟩ := b + change MulOpposite.op ((b * a) * a) = MulOpposite.op (b * (a * a)) + rw [mul_self_mul_right] + right_alt a b := by + obtain ⟨a⟩ := a; obtain ⟨b⟩ := b + change MulOpposite.op (a * (a * b)) = MulOpposite.op ((a * a) * b) + rw [mul_mul_self_left] + +end IsAlternative diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Moufang.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Moufang.lean new file mode 100644 index 0000000000..60d88e8ff4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Moufang.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs + +/-! +# The Moufang identities + +In any alternative ring the three **Moufang identities** hold: + +1. **left** `a * (b * (a * c)) = ((a * b) * a) * c` +2. **right** `((c * a) * b) * a = c * (a * (b * a))` +3. **middle** `(a * b) * (c * a) = a * ((b * c) * a)` + +Modulo the flexible law (`IsAlternative.flexible`) these agree with the forms in `GPR 13.3`. + +⚠ **Load-bearing for Layer 6.** `GPR 18.1` derives the Cayley–Dickson identities from the *middle* +Moufang identity together with the linearized left alternative law +(`IsAlternative.left_alt_linearized`). Both must remain available in exactly these shapes; if you +restate them, check `Conic/CayleyDickson.lean` still elaborates. + +## Implementation notes + +`right_moufang` is a short `calc` from the linearized alternative laws +(`IsAlternative.left_alt_linearized`, `IsAlternative.right_alt_linearized`); its docstring gives +the computation. `left_moufang` is obtained from `right_moufang` by transport along `MulOpposite`, +using the `IsAlternative αᵐᵒᵖ` instance from `Defs.lean`, and `middle_moufang` from +`left_moufang`, flexibility, the linearized right law and the alternating property of the +associator. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 13.2, 13.3. +* Schafer, *An Introduction to Nonassociative Algebras*, §3. +* Zhevlakov et al., *Rings That Are Nearly Associative*, Ch. 2. +-/ + +@[expose] public section + +universe u + +namespace IsAlternative + +variable {α : Type u} [NonUnitalNonAssocRing α] [IsAlternative α] + +/-- **Right Moufang identity**: `((c * a) * b) * a = c * (a * (b * a))`. + +Expand `((c a) b) a` by the linearized left alternative law at `(c a, b, a)`, and then `(c a)(b a)` +by the linearized right alternative law at `(c, a, b a)`; the right alternative law turns `(c a) a` +and `(b a) a` into `c a²` and `b a²`. What remains beside `c (a (b a))` is +`c (b a²) + b (c a²) - ((c (b a)) a + (b (c a)) a)`, which vanishes because both sums equal +`(c b) a² + (b c) a²`: the first by the linearized left law at `(c, b, a²)`, the second by the +linearized left law at `(c, b, a)` multiplied on the right by `a`, and the right alternative law. -/ +theorem right_moufang (a b c : α) : + ((c * a) * b) * a = c * (a * (b * a)) := by + have key : c * (b * (a * a)) + b * (c * (a * a)) = (c * (b * a)) * a + (b * (c * a)) * a := by + rw [left_alt_linearized c b (a * a), ← mul_self_mul_right a (c * b), + ← mul_self_mul_right a (b * c), ← add_mul, ← left_alt_linearized c b a, add_mul] + have h₁ := left_alt_linearized (c * a) b a + have h₂ := right_alt_linearized c a (b * a) + rw [mul_self_mul_right a c] at h₁ + rw [mul_self_mul_right a b] at h₂ + calc ((c * a) * b) * a + = (c * a) * (b * a) + b * (c * (a * a)) - (b * (c * a)) * a := eq_sub_of_add_eq h₁.symm + _ = c * (a * (b * a)) + (c * (b * (a * a)) + b * (c * (a * a))) + - ((c * (b * a)) * a + (b * (c * a)) * a) := by rw [eq_sub_of_add_eq h₂]; abel + _ = c * (a * (b * a)) := by rw [key, add_sub_cancel_right] + +/-- **Left Moufang identity**: `a * (b * (a * c)) = ((a * b) * a) * c`. + +Proved by applying `right_moufang` in the opposite ring. -/ +theorem left_moufang (a b c : α) : + a * (b * (a * c)) = ((a * b) * a) * c := by + have h := right_moufang (MulOpposite.op a) (MulOpposite.op b) (MulOpposite.op c) + simp only [← MulOpposite.op_mul] at h + exact MulOpposite.op_injective h + +/-- **Middle Moufang identity**: `(a * b) * (c * a) = a * ((b * c) * a)`. + +This is the form consumed by `GPR 18.1` in the Cayley–Dickson construction. -/ +theorem middle_moufang (a b c : α) : + (a * b) * (c * a) = a * ((b * c) * a) := by + -- Cyclic form of the alternating property. + have h_cyclic : ∀ x y z : α, + (y * z) * x - y * (z * x) = (z * x) * y - z * (x * y) := by + intro x y z + change associator y z x = associator z x y + calc + associator y z x = -associator y x z := associator_swap_right y z x + _ = associator x y z := by + rw [associator_swap_left y x z, neg_neg] + _ = -associator x z y := associator_swap_right x y z + _ = associator z x y := (associator_swap_left z x y).symm + have h_linearized := right_alt_linearized a b (c * a) + have h_extra : (a * (c * a)) * b = a * (c * (a * b)) := by + calc + (a * (c * a)) * b = ((a * c) * a) * b := + congrArg (· * b) (flexible a c).symm + _ = a * (c * (a * b)) := (left_moufang a c b).symm + rw [h_extra] at h_linearized + have h_cyclic_mul := congrArg (a * ·) (h_cyclic a b c) + simp only [mul_sub] at h_cyclic_mul + calc + (a * b) * (c * a) = + a * (b * (c * a)) + a * ((c * a) * b) - a * (c * (a * b)) := by + calc + (a * b) * (c * a) = + (a * b) * (c * a) + a * (c * (a * b)) - a * (c * (a * b)) := by + abel + _ = (a * (b * (c * a)) + a * ((c * a) * b)) - a * (c * (a * b)) := by + rw [h_linearized] + _ = a * ((b * c) * a) := by + calc + a * (b * (c * a)) + a * ((c * a) * b) - a * (c * (a * b)) = + a * (b * (c * a)) + + (a * ((c * a) * b) - a * (c * (a * b))) := by abel + _ = a * (b * (c * a)) + + (a * ((b * c) * a) - a * (b * (c * a))) := by + rw [h_cyclic_mul] + _ = a * ((b * c) * a) := by abel + +end IsAlternative diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Peirce.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Peirce.lean new file mode 100644 index 0000000000..33b47ebeba --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Peirce.lean @@ -0,0 +1,396 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.Algebra.Bilinear +public import Mathlib.Algebra.BigOperators.Group.Finset.Sigma +public import Mathlib.Algebra.Module.BigOperators +public import Mathlib.Algebra.Module.Projective +public import Mathlib.RingTheory.Finiteness.Basic +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Defs + +/-! +# Peirce projections in alternative algebras + +Let `c` be an idempotent in a unital alternative algebra and put `c₀ = c` and +`c₁ = 1 - c`. This file constructs the four Peirce projections + +`x ↦ (cᵢ * x) * cⱼ`. + +The projections are complete, idempotent, and pairwise orthogonal. This is the linear-algebraic +core of the singular Peirce decomposition [GPR, Exc. 14.12]. The range of the `(i, j)` projection is +the Peirce component `Aᵢⱼ`. + +## Main definitions + +* `IsAlternative.peirceIdempotent`: the complementary idempotents `c` and `1 - c`. +* `IsAlternative.peirceProjection`: the four Peirce projections. +* `IsAlternative.peirceComponent`: their ranges. + +## Main results + +* `IsAlternative.peirceProjection_idem`: each Peirce projection is idempotent. +* `IsAlternative.peirceProjection_comp_eq_zero`: distinct Peirce projections are orthogonal. +* `IsAlternative.sum_peirceProjection_apply`: the four projections sum to the identity. +* `IsAlternative.mul_mem_peirceComponent_of_opposite`: opposite off-diagonal components + multiply into a diagonal component. +* `IsAlternative.mul_mem_peirceComponent_swap`: one off-diagonal component squares into the + opposite component. +* `IsAlternative.finite_peirceComponent`, `IsAlternative.projective_peirceComponent`: Peirce + components inherit finite projectivity from the ambient module. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 14.12. +-/ + +@[expose] public section + +universe u v + +namespace IsAlternative + +variable {R : Type u} {A : Type v} [CommRing R] [NonAssocRing A] [Module R A] + [SMulCommClass R A A] [IsScalarTower R A A] + +/-- The two complementary idempotents attached to `c`, indexed by `Bool`. The index `false` +denotes `c`, and `true` denotes `1 - c`. -/ +def peirceIdempotent (c : A) : Bool → A + | false => c + | true => 1 - c + +@[simp] theorem peirceIdempotent_false (c : A) : peirceIdempotent c false = c := rfl + +@[simp] theorem peirceIdempotent_true (c : A) : peirceIdempotent c true = 1 - c := rfl + +/-- Both elements of the complementary pair attached to an idempotent are idempotent. -/ +theorem peirceIdempotent_mul_self {c : A} (hc : c * c = c) (i : Bool) : + peirceIdempotent c i * peirceIdempotent c i = peirceIdempotent c i := by + cases i + · exact hc + · simp only [peirceIdempotent_true, sub_mul, mul_sub, one_mul, mul_one, hc] + abel + +/-- Distinct elements of the complementary pair multiply to zero. -/ +theorem peirceIdempotent_mul_eq_zero {c : A} (hc : c * c = c) {i j : Bool} + (hij : i ≠ j) : peirceIdempotent c i * peirceIdempotent c j = 0 := by + cases i <;> cases j <;> simp_all [peirceIdempotent, mul_sub, sub_mul] + +/-- Multiplication on the left by one of the two complementary idempotents. -/ +def peirceLeftProjection (c : A) (i : Bool) : A →ₗ[R] A := + LinearMap.mulLeft R (peirceIdempotent c i) + +/-- Multiplication on the right by one of the two complementary idempotents. -/ +def peirceRightProjection (c : A) (j : Bool) : A →ₗ[R] A := + LinearMap.mulRight R (peirceIdempotent c j) + +/-- The `(i, j)` Peirce projection `x ↦ (cᵢ * x) * cⱼ`. -/ +def peirceProjection (c : A) (i j : Bool) : A →ₗ[R] A := + (peirceRightProjection (R := R) c j).comp (peirceLeftProjection (R := R) c i) + +omit [IsScalarTower R A A] in +@[simp] theorem peirceLeftProjection_apply (c x : A) (i : Bool) : + peirceLeftProjection (R := R) c i x = peirceIdempotent c i * x := rfl + +omit [SMulCommClass R A A] in +@[simp] theorem peirceRightProjection_apply (c x : A) (j : Bool) : + peirceRightProjection (R := R) c j x = x * peirceIdempotent c j := rfl + +@[simp] theorem peirceProjection_apply (c x : A) (i j : Bool) : + peirceProjection (R := R) c i j x = + (peirceIdempotent c i * x) * peirceIdempotent c j := rfl + +section Alternative + +variable [IsAlternative A] + +/-- The two complementary idempotents associate across an arbitrary middle element. This is the +flexible law, expanded linearly when either idempotent is `1 - c`. -/ +theorem peirce_associate (c x : A) (i j : Bool) : + (peirceIdempotent c i * x) * peirceIdempotent c j = + peirceIdempotent c i * (x * peirceIdempotent c j) := by + cases i <;> cases j <;> + simp only [peirceIdempotent_false, peirceIdempotent_true, mul_sub, sub_mul, one_mul, mul_one, + flexible] + +/-- Two complementary left multiplications associate. -/ +theorem peirce_left_associate (c x : A) (i j : Bool) : + peirceIdempotent c i * (peirceIdempotent c j * x) = + (peirceIdempotent c i * peirceIdempotent c j) * x := by + cases i <;> cases j <;> + simp only [peirceIdempotent_false, peirceIdempotent_true, sub_mul, mul_sub, one_mul, mul_one, + mul_mul_self_left] + +/-- Two complementary right multiplications associate. -/ +theorem peirce_right_associate (c x : A) (i j : Bool) : + (x * peirceIdempotent c i) * peirceIdempotent c j = + x * (peirceIdempotent c i * peirceIdempotent c j) := by + cases i <;> cases j <;> + simp only [peirceIdempotent_false, peirceIdempotent_true, sub_mul, mul_sub, one_mul, mul_one, + mul_self_mul_right] + +/-- Each Peirce projection is idempotent. -/ +theorem peirceProjection_idem {c : A} (hc : c * c = c) (i j : Bool) : + (peirceProjection (R := R) c i j).comp (peirceProjection (R := R) c i j) = + peirceProjection (R := R) c i j := by + ext x + simp only [LinearMap.comp_apply, peirceProjection_apply] + rw [← peirce_associate c (peirceIdempotent c i * x) i j] + rw [peirce_right_associate c (peirceIdempotent c i * + (peirceIdempotent c i * x)) j j] + rw [peirce_left_associate c x i i] + simp only [peirceIdempotent_mul_self hc] + +/-- Peirce projections with distinct left indices have zero composite. -/ +theorem peirceProjection_comp_eq_zero_of_left {c : A} (hc : c * c = c) {i j k l : Bool} + (hik : i ≠ k) : + (peirceProjection (R := R) c i j).comp (peirceProjection (R := R) c k l) = 0 := by + ext x + simp only [LinearMap.comp_apply, peirceProjection_apply, LinearMap.zero_apply] + rw [← peirce_associate c (peirceIdempotent c k * x) i l] + rw [peirce_left_associate c x i k] + simp only [peirceIdempotent_mul_eq_zero hc hik, zero_mul] + +/-- Peirce projections with distinct right indices have zero composite. -/ +theorem peirceProjection_comp_eq_zero_of_right {c : A} (hc : c * c = c) {i j k l : Bool} + (hjl : j ≠ l) : + (peirceProjection (R := R) c i j).comp (peirceProjection (R := R) c k l) = 0 := by + ext x + simp only [LinearMap.comp_apply, peirceProjection_apply, LinearMap.zero_apply] + rw [← peirce_associate c (peirceIdempotent c k * x) i l] + rw [peirce_right_associate c (peirceIdempotent c i * + (peirceIdempotent c k * x)) l j] + simp only [peirceIdempotent_mul_eq_zero hc (Ne.symm hjl), mul_zero] + +/-- Distinct Peirce projections are pairwise orthogonal. -/ +theorem peirceProjection_comp_eq_zero {c : A} (hc : c * c = c) {i j k l : Bool} + (h : (i, j) ≠ (k, l)) : + (peirceProjection (R := R) c i j).comp (peirceProjection (R := R) c k l) = 0 := by + by_cases hik : i = k + · exact peirceProjection_comp_eq_zero_of_right hc fun hjl ↦ h (Prod.ext hik hjl) + · exact peirceProjection_comp_eq_zero_of_left hc hik + +end Alternative + +/-- The four Peirce projections decompose every element. -/ +theorem sum_peirceProjection_apply (c x : A) : + peirceProjection (R := R) c false false x + + peirceProjection (R := R) c false true x + + peirceProjection (R := R) c true false x + + peirceProjection (R := R) c true true x = x := by + simp only [peirceProjection_apply, peirceIdempotent_false, peirceIdempotent_true, mul_sub, + sub_mul, one_mul, mul_one] + abel + +/-- The `(i, j)` Peirce component is the range of the corresponding projection. -/ +def peirceComponent (c : A) (i j : Bool) : Submodule R A := + LinearMap.range (peirceProjection (R := R) c i j) + +section Alternative + +variable [IsAlternative A] + +/-- An element belongs to a Peirce component exactly when its projection is itself. -/ +theorem mem_peirceComponent_iff {c : A} (hc : c * c = c) {x : A} (i j : Bool) : + x ∈ peirceComponent (R := R) c i j ↔ peirceProjection (R := R) c i j x = x := by + constructor + · rintro ⟨y, rfl⟩ + exact LinearMap.congr_fun (peirceProjection_idem hc i j) y + · intro hx + exact ⟨x, hx⟩ + +/-- The intrinsic characterization of a Peirce component: `x` lies in `Aᵢⱼ` exactly when +`cᵢ * x = x = x * cⱼ` [GPR, Exc. 14.12]. -/ +theorem mem_peirceComponent_iff_mul_eq {c : A} (hc : c * c = c) {x : A} (i j : Bool) : + x ∈ peirceComponent (R := R) c i j ↔ + peirceIdempotent c i * x = x ∧ x * peirceIdempotent c j = x := by + constructor + · rintro ⟨y, rfl⟩ + constructor + · simp only [peirceProjection_apply] + rw [← peirce_associate c (peirceIdempotent c i * y) i j] + rw [peirce_left_associate c y i i, peirceIdempotent_mul_self hc] + · simp only [peirceProjection_apply] + rw [peirce_right_associate c (peirceIdempotent c i * y) j j] + rw [peirceIdempotent_mul_self hc] + · rintro ⟨hleft, hright⟩ + rw [mem_peirceComponent_iff hc, peirceProjection_apply, hleft, hright] + +/-- Each complementary idempotent belongs to its diagonal Peirce component. -/ +theorem peirceIdempotent_mem_peirceComponent {c : A} (hc : c * c = c) (i : Bool) : + peirceIdempotent c i ∈ peirceComponent (R := R) c i i := + (mem_peirceComponent_iff_mul_eq hc i i).mpr + ⟨peirceIdempotent_mul_self hc i, peirceIdempotent_mul_self hc i⟩ + +/-- A complementary idempotent acts on the left of a Peirce component by either the identity or +zero, according to its left index. -/ +theorem peirceIdempotent_mul_of_mem {c : A} (hc : c * c = c) {x : A} {k l : Bool} + (hx : x ∈ peirceComponent (R := R) c k l) (i : Bool) : + peirceIdempotent c i * x = if i = k then x else 0 := by + have hkx := (mem_peirceComponent_iff_mul_eq hc k l).mp hx |>.1 + by_cases hik : i = k + · simpa [hik] using hkx + · rw [ite_eq_right hik, ← hkx, peirce_left_associate, + peirceIdempotent_mul_eq_zero hc hik, zero_mul] + +/-- A complementary idempotent acts on the right of a Peirce component by either the identity or +zero, according to its right index. -/ +theorem mul_peirceIdempotent_of_mem {c : A} (hc : c * c = c) {x : A} {k l : Bool} + (hx : x ∈ peirceComponent (R := R) c k l) (j : Bool) : + x * peirceIdempotent c j = if j = l then x else 0 := by + have hxl := (mem_peirceComponent_iff_mul_eq hc k l).mp hx |>.2 + by_cases hjl : j = l + · simpa [hjl] using hxl + · rw [ite_eq_right hjl, ← hxl, peirce_right_associate, + peirceIdempotent_mul_eq_zero hc (Ne.symm hjl), mul_zero] + +/-- Opposite off-diagonal Peirce components multiply into the corresponding diagonal component: +`Aᵢⱼ Aⱼᵢ ⊆ Aᵢᵢ` for `i ≠ j` [GPR, Exc. 14.12]. -/ +theorem mul_mem_peirceComponent_of_opposite {c : A} (hc : c * c = c) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ peirceComponent (R := R) c i j) + (hy : y ∈ peirceComponent (R := R) c j i) : + x * y ∈ peirceComponent (R := R) c i i := by + have hxei : x * peirceIdempotent c i = 0 := by + rw [mul_peirceIdempotent_of_mem hc hx, ite_eq_right hij] + have heiy : peirceIdempotent c i * y = 0 := by + rw [peirceIdempotent_mul_of_mem hc hy, ite_eq_right hij] + have heix : peirceIdempotent c i * x = x := by + rw [peirceIdempotent_mul_of_mem hc hx, ite_eq_left rfl] + have hyei : y * peirceIdempotent c i = y := by + rw [mul_peirceIdempotent_of_mem hc hy, ite_eq_left rfl] + apply (mem_peirceComponent_iff_mul_eq hc i i).mpr + constructor + · have ha : associator (peirceIdempotent c i) x y = 0 := by + rw [associator_swap_left, associator, hxei, heiy, zero_mul, mul_zero, sub_self, neg_zero] + exact ((associator_eq_zero_iff _ _ _).mp ha).symm.trans (congr_arg (· * y) heix) + · have ha : associator x y (peirceIdempotent c i) = 0 := by + rw [associator_swap_right, associator, hxei, heiy, zero_mul, mul_zero, sub_self, neg_zero] + exact ((associator_eq_zero_iff _ _ _).mp ha).trans (congr_arg (x * ·) hyei) + +/-- Multiplying two elements of one off-diagonal Peirce component lands in the opposite +component: `Aᵢⱼ Aᵢⱼ ⊆ Aⱼᵢ` for `i ≠ j` [GPR, Exc. 14.12]. -/ +theorem mul_mem_peirceComponent_swap {c : A} (hc : c * c = c) + {x y : A} {i j : Bool} (hij : i ≠ j) + (hx : x ∈ peirceComponent (R := R) c i j) + (hy : y ∈ peirceComponent (R := R) c i j) : + x * y ∈ peirceComponent (R := R) c j i := by + have hejx : peirceIdempotent c j * x = 0 := by + rw [peirceIdempotent_mul_of_mem hc hx, ite_eq_right (Ne.symm hij)] + have hxej : x * peirceIdempotent c j = x := by + rw [mul_peirceIdempotent_of_mem hc hx, ite_eq_left rfl] + have hxei : x * peirceIdempotent c i = 0 := by + rw [mul_peirceIdempotent_of_mem hc hx, ite_eq_right hij] + have hejy : peirceIdempotent c j * y = 0 := by + rw [peirceIdempotent_mul_of_mem hc hy, ite_eq_right (Ne.symm hij)] + have hyei : y * peirceIdempotent c i = 0 := by + rw [mul_peirceIdempotent_of_mem hc hy, ite_eq_right hij] + have heiy : peirceIdempotent c i * y = y := by + rw [peirceIdempotent_mul_of_mem hc hy, ite_eq_left rfl] + apply (mem_peirceComponent_iff_mul_eq hc j i).mpr + constructor + · have hinner : associator x (peirceIdempotent c j) y = x * y := by + rw [associator, hxej, hejy, mul_zero, sub_zero] + have ha := associator_swap_left (peirceIdempotent c j) x y + rw [associator, hejx, zero_mul, zero_sub, hinner] at ha + exact neg_injective ha + · have hinner : associator x (peirceIdempotent c i) y = -(x * y) := by + rw [associator, hxei, heiy, zero_mul, zero_sub] + have ha := associator_swap_right x y (peirceIdempotent c i) + rw [associator, hyei, mul_zero, sub_zero, hinner, neg_neg] at ha + exact ha + +/-- A Peirce projection acts as the identity on its component and as zero on every other +component. -/ +theorem peirceProjection_apply_of_mem {c : A} (hc : c * c = c) {i j k l : Bool} + (x : peirceComponent (R := R) c k l) : + peirceProjection (R := R) c i j x = if (i, j) = (k, l) then x else 0 := by + rcases x.property with ⟨y, hy⟩ + rw [← hy] + by_cases h : (i, j) = (k, l) + · rcases Prod.mk.inj h with ⟨rfl, rfl⟩ + rw [ite_eq_left rfl] + exact (LinearMap.congr_fun (peirceProjection_idem (R := R) hc i j) y).trans hy + · rw [ite_eq_right h] + exact LinearMap.congr_fun (peirceProjection_comp_eq_zero (R := R) hc h) y + +/-- The map sending an element to its four Peirce components. -/ +def peirceDecompose (c : A) : + A →ₗ[R] ((p : Bool × Bool) → peirceComponent (R := R) c p.1 p.2) where + toFun x p := ⟨peirceProjection (R := R) c p.1 p.2 x, ⟨x, rfl⟩⟩ + map_add' x y := by + funext p + exact Subtype.ext (map_add (peirceProjection (R := R) c p.1 p.2) x y) + map_smul' r x := by + funext p + exact Subtype.ext (map_smul (peirceProjection (R := R) c p.1 p.2) r x) + +/-- Sum the four coordinates in a family of Peirce components. -/ +def peirceRecombine (c : A) : + ((p : Bool × Bool) → peirceComponent (R := R) c p.1 p.2) →ₗ[R] A where + toFun x := ∑ p, (x p : A) + map_add' x y := by + simpa only [Pi.add_apply, Submodule.coe_add] using + (Finset.sum_add_distrib : ∑ p, ((x p : A) + y p) = _) + map_smul' r x := by + rw [Finset.smul_sum] + rfl + +omit [IsAlternative A] in +/-- Recombining the Peirce coordinates of an element returns that element. -/ +theorem peirceRecombine_decompose {c : A} (x : A) : + peirceRecombine (R := R) c (peirceDecompose (R := R) c x) = x := by + rw [show peirceRecombine (R := R) c (peirceDecompose (R := R) c x) = + ∑ p : Bool × Bool, peirceProjection (R := R) c p.1 p.2 x by rfl] + rw [Fintype.sum_prod_type] + simpa [Fintype.univ_bool, add_assoc, add_comm, add_left_comm] using + sum_peirceProjection_apply (R := R) c x + +/-- Decomposing a sum of Peirce coordinates returns the original coordinates. -/ +theorem peirceDecompose_recombine {c : A} (hc : c * c = c) + (x : (p : Bool × Bool) → peirceComponent (R := R) c p.1 p.2) : + peirceDecompose (R := R) c (peirceRecombine (R := R) c x) = x := by + funext p + apply Subtype.ext + change peirceProjection (R := R) c p.1 p.2 (∑ q, (x q : A)) = x p + rw [map_sum] + rw [Finset.sum_eq_single p] + · simpa using peirceProjection_apply_of_mem (R := R) hc (i := p.1) (j := p.2) (x p) + · intro q _ hqp + simpa [Ne.symm hqp] using peirceProjection_apply_of_mem (R := R) hc (i := p.1) + (j := p.2) (x q) + · simp + +/-- The singular Peirce decomposition of an alternative algebra [GPR, Exc. 14.12]. -/ +def peirceDecomposition {c : A} (hc : c * c = c) : + A ≃ₗ[R] ((p : Bool × Bool) → peirceComponent (R := R) c p.1 p.2) where + __ := peirceDecompose (R := R) c + invFun := peirceRecombine (R := R) c + left_inv := peirceRecombine_decompose + right_inv := peirceDecompose_recombine hc + +omit [IsAlternative A] in +/-- A Peirce component is finite when the ambient module is finite: it is the image of a +projection. -/ +theorem finite_peirceComponent [Module.Finite R A] {c : A} (i j : Bool) : + Module.Finite R (peirceComponent (R := R) c i j) := + Module.Finite.of_surjective + (peirceProjection (R := R) c i j).rangeRestrict + (by rintro ⟨x, y, rfl⟩; exact ⟨y, rfl⟩) + +/-- A Peirce component is projective when the ambient module is projective: its projection splits +the inclusion. -/ +theorem projective_peirceComponent [Module.Projective R A] {c : A} (hc : c * c = c) + (i j : Bool) : Module.Projective R (peirceComponent (R := R) c i j) := by + let p := (peirceProjection (R := R) c i j).rangeRestrict + have hp : p.comp (peirceComponent (R := R) c i j).subtype = LinearMap.id := by + ext x + exact (mem_peirceComponent_iff hc i j).mp x.property + exact Module.Projective.of_split (peirceComponent (R := R) c i j).subtype p hp + +end Alternative + +end IsAlternative diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/PowerAssociative.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/PowerAssociative.lean new file mode 100644 index 0000000000..808709072c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/PowerAssociative.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Nonassociative.Alternative.Artin +public import Mathlib.Algebra.Group.PNatPowAssoc + +/-! +# Power-associativity of alternative rings + +A multiplication is *power-associative* if every element generates an associative subring, so that +all parenthesizations of `a * a * ⋯ * a` agree and `a ^ n` is well defined. + +## Implementation notes + +⚠ This file deliberately does **not** introduce a hierarchy of power-associative classes. An earlier +draft defined four bundled classes (`NonUnitalPowerAssocSemiring`, `PowerAssocSemiring`, +`NonUnitalPowerAssocRing`, `PowerAssocRing`) whose only content was that associative rings are +power-associative — the trivial direction, and a doubling of the class count for no theorem we need. + +In this development power-associativity is a **corollary of Artin's theorem**: a single element +generates a two-generated (indeed one-generated) subring, which Artin makes associative. That is the +direction we actually use, and it needs no new classes. + +The recursive power below is `private` implementation detail. It exists only because a +non-associative multiplication has no canonical `Monoid.npow`; once associativity is available, +prefer mathlib's `^`. mathlib's power-associativity mixin `PNatPowAssoc` is stated for a type +that already carries a power operation, and an alternative ring carries none; so the left-recursive +power is packaged as `leftRecursivePPow`, a `def` rather than an instance, and +`IsAlternative.pnatPowAssoc` proves `PNatPowAssoc` for it. Installing `leftRecursivePPow` as a +local instance then gives mathlib's API (`ppow_mul_assoc`, `ppow_mul_comm`, `ppow_mul`). + +## Main results + +* `IsAlternative.pow_assoc` : powers of a single element associate. +* `IsAlternative.pnatPowAssoc` : the same, as mathlib's `PNatPowAssoc` for `leftRecursivePPow`. + +## References + +* Schafer, *An Introduction to Nonassociative Algebras*, §3. +-/ + +@[expose] public section + +universe u + +/-- Left-recursive power for positive exponents: `nonassocPow n a = a ^ (n + 1)`. +Private implementation detail — see the module docstring. -/ +def nonassocPow {α : Type u} [Mul α] : ℕ → α → α + | 0, a => a + | n + 1, a => a * nonassocPow n a + +@[simp] +theorem nonassocPow_zero {α : Type u} [Mul α] (a : α) : nonassocPow 0 a = a := rfl + +@[simp] theorem nonassocPow_succ {α : Type u} [Mul α] (n : ℕ) (a : α) : + nonassocPow (n + 1) a = a * nonassocPow n a := rfl + +/-- Positive powers by left recursion, `a ^ 1 = a` and `a ^ (n + 1) = a * a ^ n`, as a power by +`ℕ+`. A non-associative multiplication has no canonical power, so this is a `def` to be installed +as a local instance where wanted, not a global instance. -/ +@[instance_reducible] +def leftRecursivePPow (α : Type u) [Mul α] : Pow α ℕ+ := + ⟨fun a n ↦ nonassocPow n.natPred a⟩ + +namespace IsAlternative + +variable {α : Type u} [NonUnitalNonAssocRing α] [IsAlternative α] + +/-- Powers of a single element associate: `aᵐ⁺¹ * aⁿ⁺¹ = aᵐ⁺ⁿ⁺²`. +-/ +theorem pow_assoc (m n : ℕ) (a : α) : + nonassocPow m a * nonassocPow n a = nonassocPow (m + n + 1) a := by + have hpow : ∀ r : ℕ, nonassocPow r a ∈ NonUnitalSubring.closure ({a, a} : Set α) := by + intro r + induction r with + | zero => exact NonUnitalSubring.subset_closure (Or.inl rfl) + | succ r hr => exact mul_mem (NonUnitalSubring.subset_closure (Or.inl rfl)) hr + induction m with + | zero => + simpa only [nonassocPow_zero, Nat.zero_add] using (nonassocPow_succ n a).symm + | succ m ih => + rw [nonassocPow_succ] + rw [artin_two_generated_assoc a a (NonUnitalSubring.subset_closure (Or.inl rfl)) + (hpow m) (hpow n), ih] + rw [← nonassocPow_succ] + congr 1 + omega + +/-- **Power-associativity in mathlib's sense**: with the left-recursive power `leftRecursivePPow`, +an alternative ring is `PNatPowAssoc`. This is `IsAlternative.pow_assoc` with the exponents shifted +to `ℕ+`. -/ +theorem pnatPowAssoc : @PNatPowAssoc α _ (leftRecursivePPow α) := + letI := leftRecursivePPow α + { ppow_add := fun k n x ↦ by + change nonassocPow (k + n).natPred x = nonassocPow k.natPred x * nonassocPow n.natPred x + rw [pow_assoc] + congr 1 + simp only [PNat.natPred, PNat.add_coe] + have := k.pos + have := n.pos + omega + ppow_one := fun _ ↦ rfl } + +end IsAlternative diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Associator.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Associator.lean new file mode 100644 index 0000000000..f54efb31a5 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Associator.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.Ring.Associator + +/-! +# The associator + +Basic API for the associator `⁅x, y, z⁆ = (x * y) * z - x * (y * z)` on a non-unital, +non-associative ring: additivity in each argument, behaviour under negation and zero. + +⚠ **`associator` is mathlib's, not ours.** Mathlib already defines the ring-theoretic associator; +we import it and only add the multilinearity API. Do not redefine it. (If a future mathlib bump +moves or renames it, fix the import — do not introduce a local copy. See overview §0.) + +## Main results + +* `associator_add_left`, `associator_add_mid`, `associator_add_right` : additivity in each slot. +* `associator_neg_left`, `associator_neg_mid`, `associator_neg_right` : behaviour under negation. +* `associator_zero_left`, `associator_zero_mid`, `associator_zero_right` : vanishing. + +## TODO + +* The nucleus (`LeftNucleus`, `MiddleNucleus`, `RightNucleus`, `Nucleus`), as associative + sub-structures. This is **not** decoration: the nucleus is the tool used to prove the hard + direction of Artin's theorem (`Alternative/Artin.lean`). The centre needs no local definition: + mathlib's `NonUnitalSubring.center` (and `Subring.center`, `NonUnitalSubalgebra.center`) is + built on `Set.center`, whose `IsMulCentral` already asks for associativity as well as + commutativity, and mathlib makes it a `NonUnitalCommRing`. +* Bundle the associator `R`-trilinearly (`associatorₗ`) once a base ring is in play. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Ch. 13. +* Schafer, *An Introduction to Nonassociative Algebras*, §3. +-/ + +@[expose] public section + +universe u + +section AssociatorAdditivity + +variable {α : Type u} [NonUnitalNonAssocRing α] + +@[simp] theorem associator_add_left (x y z w : α) : + associator (x + y) z w = associator x z w + associator y z w := by + simp [associator, add_mul]; abel + +@[simp] theorem associator_add_mid (x y z w : α) : + associator x (y + z) w = associator x y w + associator x z w := by + simp [associator, add_mul, mul_add]; abel + +@[simp] theorem associator_add_right (x y z w : α) : + associator x y (z + w) = associator x y z + associator x y w := by + simp [associator, mul_add]; abel + +@[simp] theorem associator_neg_left (x y z : α) : + associator (-x) y z = -associator x y z := by + simp [associator, neg_mul]; abel + +@[simp] theorem associator_neg_mid (x y z : α) : + associator x (-y) z = -associator x y z := by + simp [associator, mul_neg, neg_mul]; abel + +@[simp] theorem associator_neg_right (x y z : α) : + associator x y (-z) = -associator x y z := by + simp [associator, mul_neg]; abel + +@[simp] theorem associator_zero_left (y z : α) : associator 0 y z = 0 := by simp [associator] + +@[simp] theorem associator_zero_mid (x z : α) : associator x 0 z = 0 := by simp [associator] + +@[simp] theorem associator_zero_right (x y : α) : associator x y 0 = 0 := by simp [associator] + +/-- The associator vanishes exactly when the two bracketings agree. -/ +theorem associator_eq_zero_iff (x y z : α) : + associator x y z = 0 ↔ (x * y) * z = x * (y * z) := by + simp [associator, sub_eq_zero] + +end AssociatorAdditivity diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Division.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Division.lean new file mode 100644 index 0000000000..abf080372c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Division.lean @@ -0,0 +1,76 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.GroupWithZero.Defs +public import Mathlib.Logic.Function.Defs + +/-! +# Division algebras (`GPR 8.6`) + +`GPR 8.6` calls an algebra `A` a **division algebra** if it is non-zero and, for every `u ≠ 0`, +the equations `u x = v` and `y u = v` can be solved uniquely — equivalently, the left and right +multiplication operators `L_u` and `R_u` are bijective. This file states that definition for a +possibly non-associative multiplication. + +⚠ mathlib's `DivisionRing` is an *associative* structure that carries an inverse operation as +data, so it does not apply to the non-associative algebras of this development; that is why the +predicate is defined here. Note also that, once associativity is dropped, `IsDivision` is strictly +stronger than every nonzero element having a two-sided inverse +(`ConicAlgebra.HasTwoSidedInverses`): the real sedenions separate the two (`GPR Exc. 19.29(e)`, +`ConicAlgebra.not_isDivision_realSedenion`). For unital alternative algebras the two agree +(`GPR 13.8`; for conic algebras, `ConicAlgebra.isDivision_iff_hasTwoSidedInverses`). + +## Main definitions + +* `IsDivision A` : `A` is a division algebra in the sense of `GPR 8.6`. + +## Main results + +* `IsDivision.eq_zero_or_eq_zero_of_mul_eq_zero` : a division algebra has no zero divisors + (`GPR 8.6`). +* `not_isDivision_of_mul_eq_zero` : a pair of nonzero elements with product zero rules out + division. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 8.6. +-/ + +@[expose] public section + +universe u + +/-- **`GPR 8.6`**: `A` is a **division algebra** if it is non-zero and, for every `u ≠ 0`, left and +right multiplication by `u` are bijective — that is, `u x = v` and `y u = v` have unique solutions. + +No associativity is assumed. -/ +structure IsDivision (A : Type u) [Mul A] [Zero A] : Prop where + /-- A division algebra is non-zero. -/ + nontrivial : Nontrivial A + /-- Left multiplication by a nonzero element is bijective. -/ + bijective_mul_left : ∀ u : A, u ≠ 0 → Function.Bijective (u * ·) + /-- Right multiplication by a nonzero element is bijective. -/ + bijective_mul_right : ∀ u : A, u ≠ 0 → Function.Bijective (· * u) + +namespace IsDivision + +variable {A : Type u} [MulZeroClass A] + +/-- **A division algebra has no zero divisors** (`GPR 8.6`): left multiplication by `x ≠ 0` is +injective and sends `0` to `0`. -/ +theorem eq_zero_or_eq_zero_of_mul_eq_zero (h : IsDivision A) {x y : A} (hxy : x * y = 0) : + x = 0 ∨ y = 0 := by + by_cases hx : x = 0 + · exact Or.inl hx + · exact Or.inr ((h.bijective_mul_left x hx).1 (hxy.trans (mul_zero x).symm)) + +end IsDivision + +/-- Two nonzero elements with product zero rule out division. -/ +theorem not_isDivision_of_mul_eq_zero {A : Type u} [MulZeroClass A] {x y : A} (hx : x ≠ 0) + (hy : y ≠ 0) (hxy : x * y = 0) : ¬ IsDivision A := fun h ↦ + (h.eq_zero_or_eq_zero_of_mul_eq_zero hxy).elim hx hy diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Subalgebra.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Subalgebra.lean new file mode 100644 index 0000000000..c381ffaaa4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Subalgebra.lean @@ -0,0 +1,66 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.Algebra.Algebra.NonUnitalSubalgebra + +/-! +# Unital subalgebras of non-associative algebras + +Mathlib's `Subalgebra` requires an associative `Semiring`, while its +`NonUnitalSubalgebra` works for a `NonUnitalNonAssocSemiring`. Composition algebras are unital but +need not be associative, so neither object alone represents their unital subalgebras. This file +adds the missing one-field wrapper. + +## Main definitions + +* `NonAssocSubalgebra R A` : a mathlib `NonUnitalSubalgebra R A` containing `1`. + +## Implementation notes + +⚠ This is deliberately not named `Subalgebra`: mathlib owns that name for associative algebras. +The underlying multiplication and scalar-action API is inherited from +`NonUnitalSubalgebra`; only the unit is new. With it a `NonAssocSubalgebra` is a `SubringClass`, +from which mathlib supplies the unit, the casts and the `NonAssocRing` structure on each +subalgebra (`SubringClass.toNonAssocRing`). +-/ + +@[expose] public section + +universe u v + +/-- A unital subalgebra of a possibly non-associative algebra. -/ +structure NonAssocSubalgebra (R : Type u) (A : Type v) [CommRing R] + [NonAssocRing A] [Module R A] extends NonUnitalSubalgebra R A where + /-- The ambient unit belongs to the subalgebra. -/ + one_mem : (1 : A) ∈ carrier + +namespace NonAssocSubalgebra + +variable {R : Type u} {A : Type v} [CommRing R] [NonAssocRing A] [Module R A] + +instance : SetLike (NonAssocSubalgebra R A) A where + coe S := S.carrier + coe_injective S T h := by + cases S with + | mk S hS => + cases T with + | mk T hT => + have : S = T := NonUnitalSubalgebra.ext fun x ↦ Set.ext_iff.mp h x + subst T + rfl + +instance : SubringClass (NonAssocSubalgebra R A) A where + zero_mem {s} := s.toNonUnitalSubalgebra.zero_mem + add_mem {s} := s.toNonUnitalSubalgebra.add_mem + mul_mem {s} := s.toNonUnitalSubalgebra.mul_mem + one_mem {s} := s.one_mem + neg_mem {s} {_} hx := s.toNonUnitalSubalgebra.neg_mem hx + +instance : SMulMemClass (NonAssocSubalgebra R A) R A where + smul_mem {s} r {_} hx := s.toNonUnitalSubalgebra.smul_mem r hx + +end NonAssocSubalgebra diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/BaseChangeProjective.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/BaseChangeProjective.lean new file mode 100644 index 0000000000..d1e355d22a --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/BaseChangeProjective.lean @@ -0,0 +1,437 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.TensorProduct +public import Mathlib.LinearAlgebra.QuadraticForm.Basis +public import Mathlib.LinearAlgebra.QuadraticForm.IsometryEquiv +public import Mathlib.LinearAlgebra.Pi +public import Mathlib.RingTheory.Finiteness.Cardinality +public import Mathlib.Algebra.Module.Projective +public import Mathlib.RingTheory.Flat.TorsionFree +public import Mathlib.RingTheory.Localization.BaseChange + +/-! +# Base change of quadratic maps along `R → A`, without inverting `2` + +Mathlib's `QuadraticForm.baseChange` is built as a special case of the *tensor product* of two +quadratic forms, which is constructed by passing to associated symmetric bilinear forms and +therefore carries an `Invertible (2 : R)` hypothesis. That hypothesis is an artefact of the +construction: base change of a quadratic form exists over an arbitrary commutative ring. +Uniqueness is already unconditional in mathlib (`baseChange_ext`); only existence needs work. + +This file supplies the missing existence, for `M` a finitely generated projective `R`-module, +by the classical device of choosing a (not necessarily symmetric) *bilinear representative* +`B` with `B x x = Q x`, base changing `B` (which is unconditional, `LinearMap.BilinMap.baseChange`) +and taking the diagonal. The choice of `B` is non-canonical, but the result is independent of it +by `baseChange_ext`. + +## Main definitions + +* `QuadraticMap.HasBilinRepr R M N`: every quadratic map `M → N` is of the form `x ↦ B x x`. +* `QuadraticMap.bilinRepr Q`: a chosen bilinear representative of `Q`, for `M` f.g. projective. +* `QuadraticMap.baseChange A Q : QuadraticMap A (A ⊗[R] M) (A ⊗[R] N)`. +* `QuadraticForm.baseChangeOfProjective A Q : QuadraticForm A (A ⊗[R] M)`. + +## Main results + +* `QuadraticMap.exists_bilinMap`: for `M` finitely generated projective, `toQuadraticMap` is + surjective, i.e. every quadratic map is `x ↦ B x x` for some bilinear `B`. +* `QuadraticMap.baseChange_tmul`, `QuadraticForm.baseChangeOfProjective_tmul`: the defining + property `Q_A (a ⊗ₜ m) = (a * a) ⊗ₜ Q m` (resp. `Q m • (a * a)`). +* `QuadraticMap.baseChange_eq_of_toQuadraticMap_eq`: independence of the chosen representative. +* `QuadraticMap.polarBilin_baseChange`, `QuadraticForm.polarBilin_baseChangeOfProjective`: + the polar form of the base change is the base change of the polar form — with *no* hypothesis + on `2`, unlike `QuadraticForm.polarBilin_baseChange`. +* `QuadraticForm.baseChangeOfProjective_eq_baseChange`: agreement with mathlib's + `QuadraticForm.baseChange` when `2` is invertible. +* `QuadraticMap.IsometryEquiv.baseChangeOfProjective`: base change of an isometry. +* `QuadraticForm.anisotropic_baseChangeOfProjective_iff_of_isLocalization`, + `QuadraticForm.anisotropic_baseChangeOfProjective_iff_of_isFractionRing`: `GPR Exc. 12.38(b)` — + anisotropy is unchanged by localizing at non-zero-divisors, in particular by passing to the + fraction field. + +## Implementation notes + +A bilinear representative exists on every free module: that is mathlib's +`LinearMap.BilinMap.toQuadraticMap_surjective`. A finitely generated projective module is a +retract of some `Fin n → R`, and representatives transport along retracts +(`QuadraticMap.HasBilinRepr.of_retract`), which gives the projective case. + +`QuadraticForm` and `LinearMap.BilinForm` are `abbrev`s for `QuadraticMap R M R` and +`LinearMap.BilinMap R M R`, so dot notation such as `Q.baseChange A` can resolve ambiguously +against mathlib's `QuadraticForm.baseChange`. Names are therefore fully qualified throughout, +and the `QuadraticForm`-valued construction is given a distinct name. + +## TODO + +* Drop the projectivity hypothesis entirely by constructing base change through the divided + square `Γ₂(M)` (Roby). mathlib now has the divided power algebra `DividedPowerAlgebra R M` and + polynomial laws `PolynomialLaw`, but not yet `Γ₂(M)` as the universal quadratic map, nor any link + from either to `QuadraticMap`. + +## References + +* overview §6(a): the mandatory warning this file exists to satisfy — `QuadraticMap.associated` + and hence mathlib's `QuadraticForm.baseChange` assume `2 ∈ Rˣ`, which is unusable for the + characteristic-2 examples (`GPR 19.4`) this development needs to state. +* GN's definition of non-singularity (`QuadraticForm/Regularity.lean`) needs base change along + finitely generated projective modules specifically — matching this file's hypothesis exactly. +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 12.38. +-/ + +@[expose] public section + +open scoped TensorProduct +open LinearMap (BilinMap BilinForm) + +universe uR uA uM uN + +namespace QuadraticMap + +/-! ### Bilinear representatives -/ + +section HasBilinRepr + +variable (R : Type uR) (M : Type uM) (N : Type uN) +variable [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] + +/-- `HasBilinRepr R M N` says that every quadratic map `Q : M → N` is the diagonal of some +bilinear map, i.e. `LinearMap.BilinMap.toQuadraticMap` is surjective. + +Beware the clash of terminology with `QuadraticMap.exists_companion`, whose companion `B` +satisfies `Q (x + y) = Q x + Q y + B x y` (so that `B x x = 2 • Q x`). Here we ask instead for +`B x x = Q x`, which is a genuine extra condition in characteristic two. -/ +def HasBilinRepr : Prop := + Function.Surjective (LinearMap.BilinMap.toQuadraticMap : BilinMap R M N → QuadraticMap R M N) + +variable {R M N} + +theorem apply_self_of_toQuadraticMap_eq {B : BilinMap R M N} {Q : QuadraticMap R M N} + (hB : B.toQuadraticMap = Q) (x : M) : B x x = Q x := + QuadraticMap.congr_fun hB x + +/-- Transport along a retract: if `M` is a direct summand of `P` (witnessed by `r ∘ₗ i = id`) +and every quadratic map on `P` has a bilinear representative, then so does every quadratic map +on `M`. -/ +theorem HasBilinRepr.of_retract {P : Type*} [AddCommGroup P] [Module R P] + (h : HasBilinRepr R P N) (i : M →ₗ[R] P) (r : P →ₗ[R] M) + (hir : r ∘ₗ i = LinearMap.id) : HasBilinRepr R M N := by + intro Q + obtain ⟨B, hB⟩ := h (Q.comp r) + refine ⟨B.compl₁₂ i i, QuadraticMap.ext fun x ↦ ?_⟩ + have hx : r (i x) = x := by simpa using DFunLike.congr_fun hir x + rw [LinearMap.BilinMap.toQuadraticMap_apply, LinearMap.compl₁₂_apply, + apply_self_of_toQuadraticMap_eq hB (i x), + QuadraticMap.comp_apply, hx] + +variable (R M N) in +/-- **Existence of bilinear representatives over finitely generated projective modules.** +Every finitely generated projective module is a retract of some `Fin n → R`, which is free, and +on a free module every quadratic map has a bilinear representative +(`LinearMap.BilinMap.toQuadraticMap_surjective`). -/ +theorem hasBilinRepr_of_projective [Module.Finite R M] [Module.Projective R M] : + HasBilinRepr R M N := by + obtain ⟨n, f, hf⟩ := Module.Finite.exists_fin' R M + obtain ⟨g, hg⟩ := f.exists_rightInverse_of_surjective (LinearMap.range_eq_top.2 hf) + exact HasBilinRepr.of_retract LinearMap.BilinMap.toQuadraticMap_surjective g f hg + +/-- For `M` finitely generated projective, `LinearMap.BilinMap.toQuadraticMap` is surjective: +every quadratic map is `x ↦ B x x` for some, generally non-symmetric, bilinear `B`. + +This is the characteristic-free replacement for `QuadraticMap.associated`, which requires `2` +to be invertible in order to pick out the *symmetric* representative. -/ +theorem exists_bilinMap [Module.Finite R M] [Module.Projective R M] (Q : QuadraticMap R M N) : + ∃ B : BilinMap R M N, B.toQuadraticMap = Q := + hasBilinRepr_of_projective R M N Q + +variable [Module.Finite R M] [Module.Projective R M] + +/-- A choice of bilinear representative of `Q`. Non-canonical: only its diagonal is determined +(see `toQuadraticMap_bilinRepr`). Every construction below is proved to be independent of this +choice. -/ +noncomputable def bilinRepr (Q : QuadraticMap R M N) : BilinMap R M N := + (exists_bilinMap Q).choose + +@[simp] +theorem toQuadraticMap_bilinRepr (Q : QuadraticMap R M N) : + (bilinRepr Q).toQuadraticMap = Q := + (exists_bilinMap Q).choose_spec + +@[simp] +theorem bilinRepr_apply_self (Q : QuadraticMap R M N) (x : M) : bilinRepr Q x x = Q x := + apply_self_of_toQuadraticMap_eq (toQuadraticMap_bilinRepr Q) x + +end HasBilinRepr + +/-! ### An extensionality lemma for bilinear maps on a base changed module -/ + +section BilinExt + +variable {R : Type uR} {A : Type uA} {M : Type uM} +variable [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] [Module R M] + +/-- Bilinear maps on `A ⊗[R] M` are determined by their values on pure tensors `1 ⊗ₜ m`. +Compare `baseChange_ext` for quadratic maps. -/ +theorem bilin_ext_of_tmul {N₁ : Type*} [AddCommGroup N₁] [Module A N₁] + ⦃B₁ B₂ : BilinMap A (A ⊗[R] M) N₁⦄ + (h : ∀ m m' : M, + B₁ (1 ⊗ₜ[R] m) (1 ⊗ₜ[R] m') = B₂ (1 ⊗ₜ[R] m) (1 ⊗ₜ[R] m')) : + B₁ = B₂ := by + have key : ∀ (a a' : A) (m m' : M), + B₁ (a ⊗ₜ[R] m) (a' ⊗ₜ[R] m') = B₂ (a ⊗ₜ[R] m) (a' ⊗ₜ[R] m') := by + intro a a' m m' + have ha : (a ⊗ₜ[R] m : A ⊗[R] M) = a • (1 ⊗ₜ[R] m) := by + rw [TensorProduct.smul_tmul', smul_eq_mul, mul_one] + have ha' : (a' ⊗ₜ[R] m' : A ⊗[R] M) = a' • (1 ⊗ₜ[R] m') := by + rw [TensorProduct.smul_tmul', smul_eq_mul, mul_one] + simp only [ha, ha', map_smul, LinearMap.smul_apply, h] + refine LinearMap.ext fun x ↦ LinearMap.ext fun y ↦ ?_ + induction x with + | tmul a m => + induction y with + | tmul a' m' => exact key a a' m m' + | add y z hy hz => simp only [map_add, hy, hz] + | add x z hx hz => simp only [map_add, LinearMap.add_apply, hx, hz] + +end BilinExt + +/-! ### Base change of quadratic maps -/ + +section BaseChange + +variable {R : Type uR} {A : Type uA} {M : Type uM} {N : Type uN} +variable [CommRing R] [CommRing A] [Algebra R A] +variable [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] +variable [Module.Finite R M] [Module.Projective R M] + +variable (A) in +/-- **Base change of a quadratic map** along an algebra map `R → A`, for `M` a finitely generated +projective `R`-module. No invertibility of `2` is required. + +Concretely this is the unique quadratic map with `Q_A (a ⊗ₜ m) = (a * a) ⊗ₜ Q m`; uniqueness +is `baseChange_ext`, and independence of the auxiliary choice is +`baseChange_eq_of_toQuadraticMap_eq`. -/ +noncomputable def baseChange (Q : QuadraticMap R M N) : + QuadraticMap A (A ⊗[R] M) (A ⊗[R] N) := + ((bilinRepr Q).baseChange A).toQuadraticMap + +@[simp] +theorem baseChange_tmul (Q : QuadraticMap R M N) (a : A) (m : M) : + baseChange A Q (a ⊗ₜ[R] m) = (a * a) ⊗ₜ[R] Q m := by + rw [baseChange, LinearMap.BilinMap.toQuadraticMap_apply, + LinearMap.BilinMap.baseChange_tmul, bilinRepr_apply_self] + +/-- The base change does not depend on the choice of bilinear representative: *any* bilinear +`B` with `B x x = Q x` computes it. -/ +theorem baseChange_eq_of_toQuadraticMap_eq (Q : QuadraticMap R M N) {B : BilinMap R M N} + (hB : B.toQuadraticMap = Q) : + baseChange A Q = (B.baseChange A).toQuadraticMap := by + refine baseChange_ext fun m ↦ ?_ + rw [baseChange_tmul, LinearMap.BilinMap.toQuadraticMap_apply, + LinearMap.BilinMap.baseChange_tmul, apply_self_of_toQuadraticMap_eq hB] + +/-- Characterisation of the base change: it is the unique quadratic map on `A ⊗[R] M` taking the +value `(a * a) ⊗ₜ Q m` on pure tensors. -/ +theorem baseChange_eq_iff (Q : QuadraticMap R M N) + (Q' : QuadraticMap A (A ⊗[R] M) (A ⊗[R] N)) : + Q' = baseChange A Q ↔ ∀ m : M, Q' (1 ⊗ₜ[R] m) = 1 ⊗ₜ[R] Q m := by + constructor + · rintro rfl m + rw [baseChange_tmul, mul_one] + · intro h + refine baseChange_ext fun m ↦ ?_ + rw [h, baseChange_tmul, mul_one] + +/-- The polar form of the base change is the base change of the polar form. Unlike +`QuadraticForm.polarBilin_baseChange`, this needs no hypothesis on `2`. -/ +theorem polarBilin_baseChange (Q : QuadraticMap R M N) : + QuadraticMap.polarBilin (baseChange A Q) = + (QuadraticMap.polarBilin Q).baseChange A := by + refine bilin_ext_of_tmul fun m m' ↦ ?_ + simp only [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar, + LinearMap.BilinMap.baseChange_tmul, ← TensorProduct.tmul_add, baseChange_tmul, mul_one, + ← TensorProduct.tmul_sub] + +end BaseChange + +end QuadraticMap + +/-! ### Base change of quadratic forms -/ + +namespace QuadraticForm + +variable {R : Type uR} {A : Type uA} {M : Type uM} +variable [CommRing R] [CommRing A] [Algebra R A] [AddCommGroup M] [Module R M] +variable [Module.Finite R M] [Module.Projective R M] + +variable (A) in +/-- **Base change of a quadratic form** along `R → A`, for `M` finitely generated projective. + +This agrees with mathlib's `QuadraticForm.baseChange` whenever the latter is defined +(`baseChangeOfProjective_eq_baseChange`) but, unlike it, does not require `2` to be invertible. +It is stated separately from `QuadraticMap.baseChange` so as to land in +`QuadraticForm A (A ⊗[R] M)` rather than `QuadraticMap A (A ⊗[R] M) (A ⊗[R] R)`. -/ +noncomputable def baseChangeOfProjective (Q : QuadraticForm R M) : QuadraticForm A (A ⊗[R] M) := + (LinearMap.BilinForm.baseChange A (QuadraticMap.bilinRepr Q)).toQuadraticMap + +@[simp] +theorem baseChangeOfProjective_tmul (Q : QuadraticForm R M) (a : A) (m : M) : + baseChangeOfProjective A Q (a ⊗ₜ[R] m) = Q m • (a * a) := by + rw [baseChangeOfProjective, LinearMap.BilinMap.toQuadraticMap_apply, + LinearMap.BilinForm.baseChange_tmul, QuadraticMap.bilinRepr_apply_self] + +theorem baseChangeOfProjective_eq_of_toQuadraticMap_eq (Q : QuadraticForm R M) + {B : BilinForm R M} (hB : B.toQuadraticMap = Q) : + baseChangeOfProjective A Q = (B.baseChange A).toQuadraticMap := by + refine baseChange_ext fun m ↦ ?_ + rw [baseChangeOfProjective_tmul, LinearMap.BilinMap.toQuadraticMap_apply, + LinearMap.BilinForm.baseChange_tmul, QuadraticMap.apply_self_of_toQuadraticMap_eq hB] + +/-- The polar form of the base change is the base change of the polar form, with no hypothesis +on `2`. -/ +theorem polarBilin_baseChangeOfProjective (Q : QuadraticForm R M) : + QuadraticMap.polarBilin (baseChangeOfProjective A Q) = + LinearMap.BilinForm.baseChange A (QuadraticMap.polarBilin Q) := by + refine QuadraticMap.bilin_ext_of_tmul fun m m' ↦ ?_ + simp only [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar, + LinearMap.BilinForm.baseChange_tmul, ← TensorProduct.tmul_add, + baseChangeOfProjective_tmul, mul_one, sub_smul] + +/-- **Base change commutes with scaling.** Rescaling `Q` by `a ∈ R` and then base changing is the +same as base changing and rescaling by the image of `a` in `A`. Compared on pure tensors `1 ⊗ₜ m`, +where both sides give `(a * Q m) • 1 = algebraMap a * algebraMap (Q m)`. -/ +theorem baseChangeOfProjective_smul (a : R) (Q : QuadraticForm R M) : + baseChangeOfProjective A (a • Q) = algebraMap R A a • baseChangeOfProjective A Q := by + refine baseChange_ext fun m ↦ ?_ + rw [baseChangeOfProjective_tmul, smul_apply, smul_apply, + baseChangeOfProjective_tmul, smul_eq_mul, mul_one, Algebra.smul_def, Algebra.smul_def, + Algebra.smul_def, map_mul] + simp [mul_comm] + +/-- **Base change commutes with pullback along a linear map.** For `f : P →ₗ[R] M` with `P` and +`M` finitely generated projective, base changing `Q ∘ f` is the same as pulling back `Q_A` along +`f_A`. + +Both sides are quadratic forms on `A ⊗[R] P`, so by `baseChange_ext` it is enough to compare them +on the pure tensors `1 ⊗ₜ p`, where both give `Q (f p)`. Note that this holds despite +`baseChangeOfProjective` being built from a *chosen* bilinear representative: the two sides may +well be built from unrelated representatives, but a quadratic form on a base changed module is +determined by its values on `1 ⊗ₜ p`. -/ +theorem baseChangeOfProjective_comp {P : Type*} [AddCommGroup P] [Module R P] [Module.Finite R P] + [Module.Projective R P] (Q : QuadraticForm R M) (f : P →ₗ[R] M) : + baseChangeOfProjective A (Q.comp f) = + (baseChangeOfProjective A Q).comp (LinearMap.baseChange A f) := by + refine baseChange_ext fun p ↦ ?_ + rw [baseChangeOfProjective_tmul, QuadraticMap.comp_apply, QuadraticMap.comp_apply, + LinearMap.baseChange_tmul, baseChangeOfProjective_tmul] + +/-- Base change of an isometry between quadratic forms on finite projective modules. -/ +noncomputable def _root_.QuadraticMap.IsometryEquiv.baseChangeOfProjective + {N : Type uN} [AddCommGroup N] [Module R N] [Module.Finite R N] [Module.Projective R N] + (Q : QuadraticForm R M) (Q' : QuadraticForm R N) (e : Q.IsometryEquiv Q') : + (Q.baseChangeOfProjective A).IsometryEquiv (Q'.baseChangeOfProjective A) where + toLinearEquiv := e.toLinearEquiv.baseChange R A M N + map_app' := by + have he : Q = Q'.comp e.toLinearEquiv.toLinearMap := + QuadraticMap.ext fun x ↦ e.map_app x |>.symm + intro m + change (Q'.baseChangeOfProjective A).comp + (LinearMap.baseChange A e.toLinearEquiv.toLinearMap) m = Q.baseChangeOfProjective A m + rw [← QuadraticForm.baseChangeOfProjective_comp, ← he] + +/-- When `2` is invertible this recovers mathlib's `QuadraticForm.baseChange`. -/ +theorem baseChangeOfProjective_eq_baseChange [Invertible (2 : R)] (Q : QuadraticForm R M) : + baseChangeOfProjective A Q = QuadraticForm.baseChange A Q := by + refine baseChange_ext fun m ↦ ?_ + rw [baseChangeOfProjective_tmul, QuadraticForm.baseChange_tmul] + +/-! ### Transitivity -/ + +section Trans + +variable {S T : Type*} [CommRing S] [Algebra R S] [CommRing T] [Algebra R T] [Algebra S T] + [IsScalarTower R S T] + +variable (S T) in +/-- **Base change is transitive**, in the form that avoids naming the comparison map on the +right-hand side: base changing to `S` and then to `T`, and reading the result back along +`T ⊗[S] (S ⊗[R] M) ≃ T ⊗[R] M`, gives the direct base change to `T`. + +Stated this way round because `QuadraticMap.baseChange_ext` compares two forms on `T ⊗[R] M` by +their values at `1 ⊗ₜ m` only, whereas comparing them on `T ⊗[S] (S ⊗[R] M)` would require +knowing them at `1 ⊗ₜ x` for every `x` in `S ⊗[R] M` — a quadratic condition that does not reduce +to pure tensors. -/ +theorem baseChangeOfProjective_baseChangeOfProjective_comp_symm (Q : QuadraticForm R M) : + ((Q.baseChangeOfProjective S).baseChangeOfProjective T).comp + (TensorProduct.AlgebraTensorModule.cancelBaseChange R S T T M).symm.toLinearMap = + Q.baseChangeOfProjective T := by + refine baseChange_ext fun m ↦ ?_ + rw [QuadraticMap.comp_apply, LinearEquiv.coe_coe, + TensorProduct.AlgebraTensorModule.cancelBaseChange_symm_tmul, baseChangeOfProjective_tmul, + baseChangeOfProjective_tmul, baseChangeOfProjective_tmul, mul_one, mul_one, smul_assoc, + one_smul] + +variable (S T) in +/-- **Base change is transitive**, as an isometry `T ⊗[S] (S ⊗[R] M) ≃ T ⊗[R] M`. + +This is the form the residue-field arguments consume: a predicate on `Q.baseChangeOfProjective F` +for every field `F` over `R` can be tested on `(Q.baseChangeOfProjective S).baseChangeOfProjective +F` for every field `F` over `S`, since the two forms differ by this isometry. -/ +noncomputable def baseChangeOfProjectiveIsometryEquiv (Q : QuadraticForm R M) : + QuadraticMap.IsometryEquiv ((Q.baseChangeOfProjective S).baseChangeOfProjective T) + (Q.baseChangeOfProjective T) where + __ := TensorProduct.AlgebraTensorModule.cancelBaseChange R S T T M + map_app' x := by + conv_lhs => rw [← baseChangeOfProjective_baseChangeOfProjective_comp_symm S T Q] + simp + +end Trans + +end QuadraticForm + +/-! ### Anisotropy and localization (`GPR Exc. 12.38(b)`) -/ + +namespace QuadraticForm + +open scoped nonZeroDivisors + +variable {R : Type uR} {M : Type uM} [CommRing R] [AddCommGroup M] [Module R M] + [Module.Finite R M] [Module.Projective R M] + +/-- **`GPR Exc. 12.38(b)`, for quadratic forms.** Let `L` be the localization of `R` at a +multiplicative set `S` of non-zero-divisors. A quadratic form on a finitely generated projective +`R`-module is anisotropic if and only if its base change to `L` is; equivalently, it represents +zero if and only if its base change does. + +A null vector `m ≠ 0` gives the null vector `1 ⊗ m ≠ 0`, since a projective module has no +`S`-torsion. Conversely a null vector `x` of `L ⊗[R] M` satisfies `s • x = 1 ⊗ m` for some `s ∈ S` +and `m ∈ M`, and then `Q m` maps to `s² Q_L(x) = 0`. -/ +theorem anisotropic_baseChangeOfProjective_iff_of_isLocalization (S : Submonoid R) (hS : S ≤ R⁰) + (L : Type*) [CommRing L] [Algebra R L] [IsLocalization S L] (Q : QuadraticForm R M) : + (Q.baseChangeOfProjective L).Anisotropic ↔ Q.Anisotropic := by + have hval (m : M) : + Q.baseChangeOfProjective L (TensorProduct.mk R L M 1 m) = algebraMap R L (Q m) := by + rw [TensorProduct.mk_apply, baseChangeOfProjective_tmul, mul_one, Algebra.smul_def, mul_one] + refine ⟨fun h m hm ↦ ?_, fun h x hx ↦ ?_⟩ + · obtain ⟨s, hs⟩ := (IsLocalizedModule.eq_zero_iff S (TensorProduct.mk R L M 1)).mp <| + h _ (by rw [hval, hm, map_zero]) + exact Module.Flat.isSMulRegular_of_nonZeroDivisors (hS s.2) (hs.trans (smul_zero _).symm) + · obtain ⟨⟨m, s⟩, hms⟩ := IsLocalizedModule.surj S (TensorProduct.mk R L M 1) x + rw [Submonoid.smul_def, ← algebraMap_smul L] at hms + have hm : m = 0 := h m <| IsLocalization.injective L hS <| by + rw [map_zero, ← hval, ← hms, QuadraticMap.map_smul, hx, smul_zero] + rw [hm, map_zero] at hms + exact (IsLocalization.map_units L s).smul_eq_zero.mp hms + +/-- **`GPR Exc. 12.38(b)` over the fraction field.** A quadratic form on a finitely generated +projective module is anisotropic if and only if its base change to the fraction field is. -/ +theorem anisotropic_baseChangeOfProjective_iff_of_isFractionRing (F : Type*) [CommRing F] + [Algebra R F] [IsFractionRing R F] (Q : QuadraticForm R M) : + (Q.baseChangeOfProjective F).Anisotropic ↔ Q.Anisotropic := + anisotropic_baseChangeOfProjective_iff_of_isLocalization R⁰ le_rfl F Q + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Cancellation.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Cancellation.lean new file mode 100644 index 0000000000..efd2b42219 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Cancellation.lean @@ -0,0 +1,148 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import TauCeti.LinearAlgebra.QuadraticForm.Prod + +/-! +# Witt cancellation: the reduction to the hyperbolic case + +**Witt cancellation over LG rings** (`GN 6.5`; cf. `GPR 11.27`) is the capstone result of Layer 0 +and the reason this project builds quadratic-form regularity theory in the first place (see the +overview, "Results of independent interest"). + +## The target statement + +Over an LG ring `R`, for `q₁, q₂` **nonsingular** and `q₃` **regular**: +``` +-- theorem QuadraticForm.cancel (hLG : IsLGRing R) {q₁ : QuadraticForm R M₁} ... +-- (h₁ : q₁.IsGPRNonsingular) (h₂ : q₂.IsGPRNonsingular) (h₃ : q₃.IsGPRRegular) +-- (h : Nonempty (IsometryEquiv (q₁.prod q₃) (q₂.prod q₃))) : +-- Nonempty (IsometryEquiv q₁ q₂) +``` +The hypothesis asymmetry is load-bearing, not a simplification we can drop: cancellation is +**false** if `q₃` is merely nonsingular rather than regular (counterexample: Elman–Karpenko– +Merkurjev, p. 49 — see overview trap 5). `GPR 11.27` is the weaker all-regular +version (GPR's "quadratic space" means regular throughout); `GN 6.5` subsumes it. + +## What is proved here + +`QuadraticForm.isometryEquiv_prod_dualProd_of_isometryEquiv_prod`: cancelling a **regular** form +`q₃` reduces to cancelling a **hyperbolic** one. Adding `-q₃` to both sides of +`q₁ ⊥ q₃ ≅ q₂ ⊥ q₃` and reassociating turns it into + + `q₁ ⊥ (q₃ ⊥ -q₃) ≅ q₂ ⊥ (q₃ ⊥ -q₃)`, + +and `q₃ ⊥ -q₃` is hyperbolic (`QuadraticForm.isometryEquivDualProd`, `Baeza I (4.7)`, +`QuadraticForm/Hyperbolic.lean`). This is the same first move `GN` makes at the start of the proof +of 6.5, and it is where regularity of `q₃` — as opposed to non-singularity — is consumed: the +comparison map `q ⊥ -q → h` is bijective exactly when the polar map of `q` is. + +Note that this reduction needs no LG hypothesis at all. + +## Where the theorem itself is + +`QuadraticForm.cancel` — the statement displayed above — and `QuadraticForm.cancel_dualProd` are +in `QuadraticForm/WittCancellation.lean`, which imports this file. `GN 6.5`'s hypothesis that `q₁` +be non-singular is not carried, since it is implied by the others: `q₂ ⊥ q₃` is non-singular, so +`q₁ ⊥ q₃` is too, and non-singularity passes to summands +(`QuadraticForm.IsGPRNonsingular.of_prod_left`). + +The route is Dias's, following Baeza's direct proof in III §4, which Baeza labels "Second proof +(after Knebusch)" and traces to Knebusch's *Isometrien über semi-lokalen Ringen*. It is +deliberately *not* `GN`'s own cohomological proof via reductive group schemes and +`SO(q)`-torsors, per overview §8. Its four steps are all formalized, and they combine into +**cancellation of a single hyperbolic plane** +(`QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing`): + +1. **Siegel–Eichler transvections and dilations**, and the unit case of `Dias II.6.2`: + *if the `u`-coefficient of `i` is a unit then some self-isometry carries the standard hyperbolic + pair `(u, v)` to `(i, j)`*. Over an arbitrary commutative ring, no hypothesis on `2` — + `QuadraticForm/HyperbolicPair.lean`, + `QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit`. +2. **`Dias II.6.1`**, the LG step and the only place the LG axiom is used: given `i = ((α, β), m)` + in `plane ⊥ q₀`, produce `y ∈ M₀` making `α - q₀(y, m) - β q₀(y)` — the new `u`-coefficient + after applying `E(u, (0, y))` — a **unit**. `QuadraticForm/PlaneTransitivity.lean`, + `QuadraticForm.exists_isUnit_sub_polar_sub_smul`. The residue-field case analysis uses + `exists_isHyperbolicPair_of_radical_eq_bot` (the non-singular field form of `GPR 11.17`) and + `exists_apply_ne_zero_of_radical_eq_bot` (from `GPR 11.26`); globally, the LG axiom is applied + to `QuadraticForm.eichlerMvPolynomial` written in the standard basis of a presentation + `Rⁿ ↠ M₀`, so `M₀` never has to be free. +3. **`Dias II.6.2`** in general — `QuadraticForm.exists_isometryEquiv_of_isHyperbolicPair`. Baeza + and Dias assume the complement `M₀` nonzero at every residue field (`Baeza III (2.3)`'s rank + hypothesis, Dias's `V₀ ≠ 0`); that hypothesis is *not* assumed here. Where `M₀` dies the switch + is needed, and `QuadraticForm.switchIdem` supplies it on exactly that locus — clopen, cut out by + `Module.rankIdempotent R M₀ 0` — as a single isometry over `R`, with no product decomposition of + `R`. This matters for step 5: the last plane to be cancelled has bare `q₂` as its complement, + and `M₂ = 0` is a case `GN 6.5` has to cover. +4. **`Dias II.6.4`**, cancellation of a plane given step 3 — `QuadraticForm/PlaneCancellation.lean`, + `QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod`. This step needs no regularity of `q₁` + or `q₂` at all: membership in the second summand is detected by orthogonality to the pair. +5. **From one plane to `dualProd R N`** — `QuadraticForm/WittCancellation.lean`. Choose `N'` with + `N × N' ≅ Rⁿ`, add `dualProd R N'` to both sides, and use + `dualProd R (M × N) ≅ dualProd R M ⊥ dualProd R N` with `dualProd R R ≅ plane R` to + reduce to `n` planes, then induct. This needs `N` neither free nor of constant rank, so it + avoids `GN 2.6(b)` and the rank decomposition. The intermediate forms + `dualProd R (Rᵏ) ⊥ q₂` are non-singular by `GN (C.8.3)` + (`QuadraticForm.IsGPRRegular.prod_isGPRNonsingular`) — which is why the hyperbolic summand is + kept on the left, where a *regular* form is what that lemma wants. + +The prerequisites this file used to list are all in place: `LGRing/` is complete through +`GPR 11.22` (semilocal ⇒ LG), `GN 2.6(a)` and `GN 2.6(b)`, the representation lemma `GPR 11.26` +holds in full generality, and the rank decomposition `GPR Exc. 9.31` is available. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.11, 11.27. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, §6 (`6.1`, `6.5`). +* [Baeza] R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Mathematics **655**, + Springer, 1978, I (4.7), III §4, and Corollary III.4.3. +* [Dias] I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de + Campinas, 1988, II.6.1–II.6.4. +* [Knebusch] M. Knebusch, *Isometrien über semi-lokalen Ringen*, Mathematische Zeitschrift + **108** (1969), 255–268. Baeza III §4 cites this as `[K]₂` for the direct proof. +* [EKM] R. Elman, N. Karpenko, A. Merkurjev, *The Algebraic and Geometric Theory of Quadratic + Forms*, AMS Colloquium Publications **56**, 2008, p. 49: the counterexample bounding the + hypothesis on `q₃`. +-/ + +@[expose] public section + +universe u v₁ v₂ v₃ + +variable {R : Type u} [CommRing R] +variable {M₁ : Type v₁} [AddCommGroup M₁] [Module R M₁] +variable {M₂ : Type v₂} [AddCommGroup M₂] [Module R M₂] +variable {M₃ : Type v₃} [AddCommGroup M₃] [Module R M₃] + +/-- **Cancelling a regular form reduces to cancelling a hyperbolic one.** + +From `q₁ ⊥ q₃ ≅ q₂ ⊥ q₃` with `q₃` regular, add `-q₃` to both sides and reassociate: since +`q₃ ⊥ -q₃` is hyperbolic (`QuadraticForm.isometryEquivDualProd`), the result is +`q₁ ⊥ h ≅ q₂ ⊥ h` with `h` the hyperbolic form of `M₃`. + +This is the opening move of `GN`'s proof of 6.5, and it needs no LG hypothesis. Regularity of +`q₃` — rather than mere non-singularity — is consumed here and nowhere else. -/ +theorem QuadraticForm.isometryEquiv_prod_dualProd_of_isometryEquiv_prod + [Module.Finite R M₃] [Module.Projective R M₃] {q₁ : QuadraticForm R M₁} + {q₂ : QuadraticForm R M₂} {q₃ : QuadraticForm R M₃} + (h₃ : QuadraticForm.IsGPRRegular q₃) + (h : Nonempty (QuadraticMap.IsometryEquiv (q₁.prod q₃) (q₂.prod q₃))) : + Nonempty (QuadraticMap.IsometryEquiv (q₁.prod (QuadraticForm.dualProd R M₃)) + (q₂.prod (QuadraticForm.dualProd R M₃))) := by + obtain ⟨e⟩ := h + refine ⟨?_⟩ + -- `q₁ ⊥ h ≅ q₁ ⊥ (q₃ ⊥ -q₃) ≅ (q₁ ⊥ q₃) ⊥ -q₃` + -- `≅ (q₂ ⊥ q₃) ⊥ -q₃ ≅ q₂ ⊥ (q₃ ⊥ -q₃) ≅ q₂ ⊥ h` + refine ((QuadraticMap.IsometryEquiv.prod (QuadraticMap.IsometryEquiv.refl q₁) + (QuadraticForm.isometryEquivDualProd q₃ h₃).symm).trans ?_).trans + (QuadraticMap.IsometryEquiv.prod (QuadraticMap.IsometryEquiv.refl q₂) + (QuadraticForm.isometryEquivDualProd q₃ h₃)) + refine (QuadraticMap.IsometryEquiv.prodAssoc q₁ q₃ (-q₃)).symm.trans ?_ + exact (QuadraticMap.IsometryEquiv.prod e (QuadraticMap.IsometryEquiv.refl (-q₃))).trans + (QuadraticMap.IsometryEquiv.prodAssoc q₂ q₃ (-q₃)) diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/FiniteField.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/FiniteField.lean new file mode 100644 index 0000000000..fa609cc441 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/FiniteField.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Polynomial +public import Mathlib.FieldTheory.ChevalleyWarning + +/-! +# Quadratic forms over finite fields are isotropic in three or more variables + +Over a finite field every quadratic form in at least three variables has a nonzero null vector. +This is the Chevalley–Warning theorem applied to the polynomial `GPR 11.8` attaches to the form: +its total degree is `2`, which is smaller than the number of variables, so the number of solutions +of `q = 0` is divisible by the characteristic. The zero vector is one solution, hence there are at +least `p ≥ 2` of them. + +Over a field the two isotropy notions of the literature agree +(`QuadraticMap.isGPRIsotropic_iff_not_anisotropic`), so this also produces a *unimodular* null +vector in the sense of `GPR 11.17`. + +## Main results + +* `QuadraticForm.not_anisotropic_of_two_lt_finrank` : over a finite field, a quadratic form on a + space of dimension greater than two is not anisotropic. +* `QuadraticForm.exists_ne_zero_apply_eq_zero_of_two_lt_finrank` : the same, stated as the + existence of a nonzero null vector. + +## Implementation notes + +The count is run on the solution *subtype* `{x : Fin n → K // eval x f = 0}` that +`char_dvd_card_solutions` speaks about. Rather than exhibiting two solutions +directly, the proof assumes anisotropy, deduces that the subtype is a singleton, and concludes +`p ∣ 1`; this avoids having to produce a second solution by hand. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.8, 23.14. +* [EKM] Elman, Karpenko, Merkurjev, *The Algebraic and Geometric Theory of Quadratic Forms*. +-/ + +@[expose] public section + +universe u v + +namespace QuadraticForm + +variable {K : Type u} [Field K] [Finite K] {V : Type v} [AddCommGroup V] [Module K V] + [FiniteDimensional K V] + +/-- **Chevalley–Warning for quadratic forms.** Over a finite field, a quadratic form on a vector +space of dimension greater than two is not anisotropic. + +The polynomial `GPR 11.8` attaches to `q` in a basis has total degree at most two, which is less +than the number of variables, so the characteristic divides the number of its zeros. Anisotropy +would make the zero vector the only one. -/ +theorem not_anisotropic_of_two_lt_finrank (q : QuadraticForm K V) + (h : 2 < Module.finrank K V) : ¬ q.Anisotropic := by + classical + have : Fintype K := Fintype.ofFinite K + intro hani + set n := Module.finrank K V with hn + let b : Module.Basis (Fin n) K V := Module.finBasis K V + let f : MvPolynomial (Fin n) K := q.toMvPolynomial b + have hval : ∀ x : Fin n → K, MvPolynomial.eval x f = q (b.equivFun.symm x) := by + intro x + rw [b.equivFun_symm_apply, ← QuadraticForm.aeval_toMvPolynomial_self (q := q) (bm := b) x] + rfl + -- Anisotropy makes the solution subtype a singleton. + have hzero : MvPolynomial.eval (0 : Fin n → K) f = 0 := by + rw [hval, map_zero, map_zero] + have hcard : Fintype.card { x : Fin n → K // MvPolynomial.eval x f = 0 } = 1 := by + rw [Fintype.card_eq_one_iff] + refine ⟨⟨0, hzero⟩, fun y ↦ ?_⟩ + have hy : q (b.equivFun.symm (y : Fin n → K)) = 0 := (hval _).symm.trans y.2 + exact Subtype.ext (b.equivFun.symm.injective ((hani _ hy).trans (map_zero _).symm)) + -- Chevalley–Warning says the characteristic divides that count. + set p := ringChar K with hp + have : CharP K p := ringChar.charP K + have hdeg : f.totalDegree < Fintype.card (Fin n) := by + rw [Fintype.card_fin] + exact lt_of_le_of_lt (QuadraticForm.totalDegree_toMvPolynomial_le q b) h + have hdvd : p ∣ Fintype.card { x : Fin n → K // MvPolynomial.eval x f = 0 } := + char_dvd_card_solutions p hdeg + rw [hcard] at hdvd + exact CharP.char_ne_one K p (Nat.dvd_one.mp hdvd) + +/-- **Chevalley–Warning for quadratic forms**, stated as the existence of a nonzero null vector. -/ +theorem exists_ne_zero_apply_eq_zero_of_two_lt_finrank (q : QuadraticForm K V) + (h : 2 < Module.finrank K V) : ∃ v : V, v ≠ 0 ∧ q v = 0 := by + by_contra hcon + exact q.not_anisotropic_of_two_lt_finrank h fun v hv ↦ by + by_contra hv0 + exact hcon ⟨v, hv0, hv⟩ + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Hyperbolic.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Hyperbolic.lean new file mode 100644 index 0000000000..b1d9187381 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Hyperbolic.lean @@ -0,0 +1,310 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import Mathlib.LinearAlgebra.QuadraticForm.Dual + +/-! +# Hyperbolic quadratic forms + +The **hyperbolic form** of an `R`-module `M` is mathlib's `QuadraticForm.dualProd R M`, the +quadratic form `(f, m) ↦ f m` on `M* ⊕ M`. (GPR writes it on `M ⊕ M*`; we follow mathlib's order +of the factors.) It is the basic example of a regular quadratic form that exists over *every* +commutative ring with no hypothesis on `2`, and it is what Witt cancellation is ultimately about: +the reduction of `GN 6.5` to the hyperbolic case (via `q ⊥ (-q)` hyperbolic) is what makes the +elementary route to cancellation possible in characteristic `2`, where a regular form need not +split off any rank-one piece at all. + +mathlib supplies the form and its functoriality (`QuadraticForm.dualProdIsometry`, +`QuadraticForm.dualProdProdIsometry`). This file adds its regularity, and the +characteristic-free isometry `q ⊥ (-q) ≅ dualProd R M` for `q` regular. + +## Main definitions + +* `QuadraticForm.dualProdPolarEquiv R M` : the polar map of `dualProd R M`, as a linear + equivalence `M* ⊕ M ≃ (M* ⊕ M)*`. +* `QuadraticForm.toDualProdMap q`, `QuadraticForm.isometryEquivDualProd q hq` : the comparison + map `M ⊕ M → M* ⊕ M`, and the isometry `q ⊥ (-q) ≅ dualProd R M` it gives for `q` regular. + +## Main results + +* `QuadraticForm.polar_dualProd` : the polar form is the canonical pairing, + `((f, m), (f', m')) ↦ f m' + f' m`. It is *symmetric and nondegenerate over any ring*, with no + hypothesis on `2` — which is exactly why hyperbolic forms survive characteristic `2`. +* `QuadraticForm.isGPRRegular_dualProd` : the hyperbolic form of a finitely generated projective + module is regular. +* `QuadraticForm.isGPRNonsingular_dualProd` : hence non-singular. +* `QuadraticForm.dualProd_apply_inl`, `QuadraticForm.dualProd_apply_inr` : `M* ⊕ 0` and + `0 ⊕ M` are totally isotropic — the two standard Lagrangians. +* `QuadraticForm.isGPRNonsingular_of_basis_pairing` : a form on `M ⊕ M` pairing the two summands + against each other in the coordinates of a finite basis, `Q (x, y) = ∑ᵢ xᵢ yᵢ`, is hyperbolic + and therefore non-singular. This is how a hyperbolic form is recognized in practice. +* `QuadraticForm.isGPRNonsingular_of_linearEquiv_basis_pairing` : the same, for a form on a module + presented as `M ⊕ M` by an explicit equivalence. +* `QuadraticForm.isGPRRegular_of_basis_pairing` : such a form is in fact *regular*, which is the + stronger conclusion the orthogonal splitting of a submodule needs. + +## Implementation notes + +Regularity is proved by factoring the polar map as a composition of two linear equivalences: + + `M* ⊕ M ≃ M** ⊕ M* ≃ (M* ⊕ M)*` + +The first is `Prod.comm` followed by `Module.evalEquiv` on the first factor — this is where +finiteness and projectivity of `M` enter, through mathlib's `Module.IsReflexive` instance for +finitely generated projective modules. The second is mathlib's +`Module.dualProdDualEquivDual`. No determinant, no localization, and no assumption on `2`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Exc. 11.30. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, 6.5. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Math. **655**, Springer 1978, + I, (4.7). +-/ + +@[expose] public section + +universe u v w t₁ + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-- `M* ⊕ 0` is totally isotropic: it is one of the two standard Lagrangians of the hyperbolic +form. (Not a `simp` lemma: `dualProd_apply` already reduces both sides.) -/ +theorem dualProd_apply_inl (f : Module.Dual R M) : dualProd R M (f, 0) = 0 := + map_zero f + +/-- `0 ⊕ M` is totally isotropic: it is the other standard Lagrangian. -/ +theorem dualProd_apply_inr (m : M) : dualProd R M (0, m) = 0 := + rfl + +/-- The polar form of the hyperbolic form is the canonical pairing between `M* ⊕ M` and itself, +`((f, m), (f', m')) ↦ f m' + f' m`. Note there is no factor of `2` anywhere: this is a +nondegenerate *symmetric* bilinear form over an arbitrary commutative ring. -/ +theorem polar_dualProd (x y : Module.Dual R M × M) : + QuadraticMap.polar (dualProd R M) x y = x.1 y.2 + y.1 x.2 := by + simp only [QuadraticMap.polar, dualProd_apply, Prod.fst_add, Prod.snd_add, + LinearMap.add_apply, map_add] + ring + +variable (R M) + +/-- The linear equivalence `M* ⊕ M ≃ (M* ⊕ M)*` underlying regularity of the hyperbolic form. +Reflexivity of `M` — automatic for `M` finitely generated projective — is the only input. -/ +noncomputable def dualProdPolarEquiv [Module.Finite R M] [Module.Projective R M] : + (Module.Dual R M × M) ≃ₗ[R] Module.Dual R (Module.Dual R M × M) := + ((LinearEquiv.prodComm R (Module.Dual R M) M).trans + ((Module.evalEquiv R M).prodCongr (LinearEquiv.refl R (Module.Dual R M)))).trans + (Module.dualProdDualEquivDual R (Module.Dual R M) M) + +theorem dualProdPolarEquiv_apply [Module.Finite R M] [Module.Projective R M] + (x y : Module.Dual R M × M) : dualProdPolarEquiv R M x y = x.1 y.2 + y.1 x.2 := by + simp [dualProdPolarEquiv, Module.dualProdDualEquivDual_apply, add_comm] + +/-- **The hyperbolic form of a finitely generated projective module is regular.** + +The polar map is the canonical isomorphism `M* ⊕ M ≃ (M* ⊕ M)*`, which exists because `M` is +reflexive. Unlike the criteria in `QuadraticForm/Regularity.lean`, this needs no assumption on +`2`, no determinant computation and no localization. -/ +theorem isGPRRegular_dualProd [Module.Finite R M] [Module.Projective R M] : + QuadraticForm.IsGPRRegular (dualProd R M) := by + have h : (QuadraticMap.polarBilin (dualProd R M) : + (Module.Dual R M × M) →ₗ[R] Module.Dual R (Module.Dual R M × M)) = + (dualProdPolarEquiv R M).toLinearMap := by + refine LinearMap.ext fun x ↦ LinearMap.ext fun y ↦ ?_ + rw [QuadraticMap.polarBilin_apply_apply, polar_dualProd, LinearEquiv.coe_coe, + dualProdPolarEquiv_apply] + rw [QuadraticForm.IsGPRRegular, h] + exact (dualProdPolarEquiv R M).bijective + +/-- The hyperbolic form of a finitely generated projective module is non-singular +(`GN (C.8.1)` applied to `QuadraticForm.isGPRRegular_dualProd`). -/ +theorem isGPRNonsingular_dualProd [Module.Finite R M] [Module.Projective R M] : + QuadraticForm.IsGPRNonsingular (dualProd R M) := + (isGPRRegular_dualProd R M).isGPRNonsingular + +end QuadraticForm + +/-! ### `q ⊥ (-q)` is hyperbolic + +This is the reduction that makes the elementary route to Witt cancellation work: from +`q₁ ⊥ q₃ ≅ q₂ ⊥ q₃` one gets `q₁ ⊥ h ≅ q₂ ⊥ h` with `h` hyperbolic by adding `-q₃` to both sides, +so cancelling an arbitrary regular form reduces to cancelling a hyperbolic one. -/ + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] +variable [Module.Finite R M] [Module.Projective R M] (q : QuadraticForm R M) + +/-- The comparison map `M ⊕ M → M* ⊕ M` witnessing that `q ⊥ (-q)` is hyperbolic: +`(x, y) ↦ (B(x - y, ·) + polar q y, x - y)`, where `B` is the bilinear representative of `q`. + +This is a characteristic-free version of mathlib's `QuadraticForm.toDualProd`, which is built from +`QuadraticMap.associated` and so needs `2` to be invertible. The `B(x - y, ·)` summand is what +makes this work in characteristic `2`: the naive map `(x, y) ↦ (polar q y, x - y)` computes +`q x - q y - q (x - y)`, and it is precisely a *bilinear representative* — which +`QuadraticForm/BaseChangeProjective.lean` provides for any finitely generated projective module, +with no hypothesis on `2` — that supplies the missing `q (x - y)` linearly. -/ +noncomputable def toDualProdMap : (M × M) →ₗ[R] (Module.Dual R M × M) := + LinearMap.prod + (QuadraticMap.bilinRepr q ∘ₗ (LinearMap.fst R M M - LinearMap.snd R M M) + + QuadraticMap.polarBilin q ∘ₗ LinearMap.snd R M M) + (LinearMap.fst R M M - LinearMap.snd R M M) + +@[simp] +theorem toDualProdMap_apply (x : M × M) : + toDualProdMap q x = + (QuadraticMap.bilinRepr q (x.1 - x.2) + QuadraticMap.polarBilin q x.2, x.1 - x.2) := + rfl + +/-- The comparison map is an isometry onto the hyperbolic form: `q x - q y` is computed by the +hyperbolic pairing. -/ +theorem dualProd_toDualProdMap (x : M × M) : + dualProd R M (toDualProdMap q x) = (q.prod (-q)) x := by + simp only [toDualProdMap_apply, dualProd_apply, LinearMap.add_apply, + QuadraticMap.bilinRepr_apply_self, QuadraticMap.polarBilin_apply_apply, + QuadraticMap.prod_apply, neg_apply, QuadraticMap.polar] + abel_nf + +/-- When `q` is regular the comparison map is bijective: solving `B(u, ·) + polar q y = φ` for `y` +is exactly inverting the polar map, which is what regularity provides. -/ +theorem bijective_toDualProdMap (hq : QuadraticForm.IsGPRRegular q) : + Function.Bijective (toDualProdMap q) := by + set E := LinearEquiv.ofBijective (QuadraticMap.polarBilin q : + M →ₗ[R] Module.Dual R M) hq with hE + have hEq : ∀ y : M, QuadraticMap.polarBilin q y = E y := fun _ ↦ rfl + set s : (Module.Dual R M × M) →ₗ[R] M := + E.symm.toLinearMap ∘ₗ (LinearMap.fst R (Module.Dual R M) M - + QuadraticMap.bilinRepr q ∘ₗ LinearMap.snd R (Module.Dual R M) M) with hs + have hsapp : ∀ z : Module.Dual R M × M, + QuadraticMap.polarBilin q (s z) = z.1 - QuadraticMap.bilinRepr q z.2 := by + intro z + rw [hEq, hs] + simp only [LinearMap.comp_apply, LinearMap.sub_apply, LinearMap.snd_apply, + LinearMap.fst_apply, LinearEquiv.coe_coe] + exact E.apply_symm_apply _ + constructor + · intro x y hxy + simp only [toDualProdMap_apply, Prod.mk.injEq] at hxy + obtain ⟨h2, h1⟩ := hxy + rw [h1, add_right_inj] at h2 + have hsnd : x.2 = y.2 := hq.1 h2 + rw [hsnd, sub_left_inj] at h1 + exact Prod.ext h1 hsnd + · intro z + have hfst : (z.2 + s z) - s z = z.2 := by abel + refine ⟨(z.2 + s z, s z), ?_⟩ + rw [toDualProdMap_apply] + refine Prod.ext ?_ hfst + simp only [hfst, hsapp z] + abel + +/-- **`q ⊥ (-q)` is hyperbolic**, for `q` regular on a finitely generated projective module +(`Baeza I, (4.7)`; used in the proof of `GN 6.5`). + +Regularity is exactly what is needed, and not merely a convenience: the comparison map is +bijective if and only if the polar map is. This answers, without any hypothesis on `2`, the TODO +in mathlib's `Mathlib/LinearAlgebra/QuadraticForm/Dual.lean` asking for `QuadraticForm.toDualProd` +to be upgraded to an isometry equivalence. -/ +noncomputable def isometryEquivDualProd (hq : QuadraticForm.IsGPRRegular q) : + QuadraticMap.IsometryEquiv (q.prod (-q)) (dualProd R M) where + __ := LinearEquiv.ofBijective (toDualProdMap q) (bijective_toDualProdMap q hq) + map_app' := dualProd_toDualProdMap q + +end QuadraticForm + +/-! ### Recognizing a hyperbolic form in coordinates + +A quadratic form on `M ⊕ M` given by the *pairing of the two summands against each other* is +hyperbolic: the second summand is being used as a copy of `M*`, along the self-duality supplied by +a finite basis. This is the shape in which hyperbolic forms actually turn up — the norm of a split +octonion algebra is one — and it is the one place a basis is used, so that the +coordinate form `∑ᵢ xᵢ yᵢ` can be recognized without unfolding any duality by hand. -/ + +namespace Module.Basis + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] +variable {ι : Type*} [Fintype ι] [DecidableEq ι] + +/-- The self-duality attached to a finite basis is the **coordinate pairing** +`⟪m, n⟫ = ∑ᵢ mᵢ nᵢ`: mathlib's `Module.Basis.toDual` sends `bᵢ ↦ bᵢ*`, and evaluating it at a +second vector expands both arguments in the basis. Symmetric, and with no hypothesis on `2`. -/ +theorem toDual_apply_eq_sum (b : Basis ι R M) (m n : M) : + b.toDual m n = ∑ i, b.repr n i * b.repr m i := by + conv_lhs => rw [← b.sum_repr n] + rw [map_sum] + exact Finset.sum_congr rfl fun i _ ↦ by + rw [map_smul, smul_eq_mul, b.toDual_apply_left] + +end Module.Basis + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] +variable [Module.Finite R M] [Module.Projective R M] + +/-- **A form pairing two copies of `M` against each other is hyperbolic**, hence non-singular. + +The hypothesis is the coordinate identity `Q (x, y) = ∑ᵢ xᵢ yᵢ` for the coordinates of some finite +basis of `M`; the conclusion needs no hypothesis on `2`, since +`QuadraticForm.isGPRNonsingular_dualProd` needs none. -/ +theorem isGPRNonsingular_of_basis_pairing {ι : Type*} [Fintype ι] + (b : Module.Basis ι R M) {Q : QuadraticForm R (M × M)} + (hQ : ∀ x : M × M, Q x = ∑ i, b.repr x.1 i * b.repr x.2 i) : + QuadraticForm.IsGPRNonsingular.{u, v, w} Q := by + classical + have hcomp : Q = (dualProd R M).comp + (LinearEquiv.prodCongr b.toDualEquiv (LinearEquiv.refl R M)).toLinearMap := by + refine QuadraticMap.ext fun x ↦ ?_ + rw [hQ x, QuadraticMap.comp_apply] + simp [b.toDual_apply_eq_sum, mul_comm] + rw [hcomp] + exact (isGPRNonsingular_dualProd R M).comp_linearEquiv _ + +/-- **A form pairing two copies of `M` against each other is regular**, being the hyperbolic form +of `M` in the coordinates of the given basis. + +Regularity, unlike non-singularity, is what the orthogonal splitting of +`QuadraticForm/OrthogonalComplement.lean` consumes; it needs no hypothesis on `2` either. -/ +theorem isGPRRegular_of_basis_pairing {ι : Type*} [Fintype ι] + (b : Module.Basis ι R M) {Q : QuadraticForm R (M × M)} + (hQ : ∀ x : M × M, Q x = ∑ i, b.repr x.1 i * b.repr x.2 i) : + QuadraticForm.IsGPRRegular Q := by + classical + have hcomp : Q = (dualProd R M).comp + (LinearEquiv.prodCongr b.toDualEquiv (LinearEquiv.refl R M)).toLinearMap := by + refine QuadraticMap.ext fun x ↦ ?_ + rw [hQ x, QuadraticMap.comp_apply] + simp [b.toDual_apply_eq_sum, mul_comm] + rw [hcomp] + exact QuadraticForm.IsGPRRegular.comp_linearEquiv (isGPRRegular_dualProd R M) _ + +/-- **A form that becomes a pairing of two copies of `M` in suitable coordinates is hyperbolic**, +hence non-singular. + +The same statement as `QuadraticForm.isGPRNonsingular_of_basis_pairing`, but for a form on any +module `N` presented as `M ⊕ M` by an explicit equivalence — which is how the split quaternion +algebra meets it: `Mat₂(k)` becomes `k² ⊕ k²` by reading off `(a₀₀, a₀₁)` and `(a₁₁, -a₁₀)`, and +the determinant becomes the standard pairing of the two. -/ +theorem isGPRNonsingular_of_linearEquiv_basis_pairing {ι : Type*} [Fintype ι] + (b : Module.Basis ι R M) {N : Type t₁} [AddCommGroup N] [Module R N] [Module.Finite R N] + [Module.Projective R N] (e : N ≃ₗ[R] M × M) {Q : QuadraticForm R N} + (hQ : ∀ x : N, Q x = ∑ i, b.repr (e x).1 i * b.repr (e x).2 i) : + QuadraticForm.IsGPRNonsingular.{u, t₁, w} Q := by + have hcomp : Q = (Q.comp e.symm.toLinearMap).comp e.toLinearMap := by + refine QuadraticMap.ext fun x ↦ ?_ + simp [QuadraticMap.comp_apply] + rw [hcomp] + refine QuadraticForm.IsGPRNonsingular.comp_linearEquiv ?_ e + refine isGPRNonsingular_of_basis_pairing b fun x ↦ ?_ + rw [QuadraticMap.comp_apply, hQ] + simp + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/HyperbolicPair.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/HyperbolicPair.lean new file mode 100644 index 0000000000..cda208191b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/HyperbolicPair.lean @@ -0,0 +1,313 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.Basic +public import Mathlib.Tactic.LinearCombination +public import Mathlib.Tactic.Module +public import Mathlib.LinearAlgebra.QuadraticForm.Prod +public import TauCeti.LinearAlgebra.QuadraticForm.OrthogonalGroup.HyperbolicPair +public import TauCeti.LinearAlgebra.QuadraticForm.Transvection.Basic + +/-! +# Hyperbolic pairs and Siegel–Eichler transvections + +The two elementary ingredients of the Witt extension theorem, and hence of Witt cancellation +(`Dias II.6.1–6.4`, `Baeza III.2–III.4`): + +* a **hyperbolic pair** in a quadratic module is a pair `u, v` with `q u = q v = 0` and + `polar q u v = 1`; +* the **Siegel–Eichler transvection** `E(x, y)` attached to `x` isotropic and `y` orthogonal to + `x` is the isometry `z ↦ z + b(z,x) • y - (b(z,y) + q y * b(z,x)) • x`. + +Transvections are the characteristic-2-safe substitute for hyperplane reflections: they are defined +for *every* commutative ring and need no invertible scalar, whereas the reflection `σ_x` requires +`q x` to be a unit. This is why the Dias/Baeza/Knebusch route to cancellation survives +characteristic 2, and it is the reason overview §8 prescribes it over `GN`'s cohomological +proof. + +## Main definitions + +* `QuadraticForm.plane R` : the hyperbolic plane `(a, b) ↦ a * b` on `R × R`. This is the + elementary model, defined without dual modules, of `QuadraticForm.dualProd R R`. +* `QuadraticMap.IsHyperbolicPair Q u v` : `Q u = 0`, `Q v = 0`, `polar Q u v = 1`. +* `QuadraticMap.eichler hx hxy` : the transvection, TauCeti's `QuadraticMap.transvection`, as a + self-isometry of `Q`. +* `QuadraticMap.IsHyperbolicPair.dilation` : the dilation along a hyperbolic pair, TauCeti's + `TauCeti.QuadraticMap.hyperbolicPairTorus`, as a self-isometry of `Q`. + +## Main results + +* `QuadraticMap.eichler_apply` : the formula for `E(x, y)`. +* `QuadraticMap.IsHyperbolicPair.decomposition` : any `w` is `b(w,v) • u + b(w,u) • v` plus a + vector orthogonal to both `u` and `v`. This replaces, in explicit form, the splitting + `V = ⟨u, v⟩ ⊥ ⟨u, v⟩^⊥` that `Dias II.6.2` uses. +* `QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit` : **the unit case of + `Dias II.6.2`**. If `i = α • u + β • v + z` with `α` a unit and `z` orthogonal to `u` and `v`, + then some self-isometry of `Q` carries the hyperbolic pair `(u, v)` to the hyperbolic pair + `(i, j)`. Reducing the general case to this one is what needs the LG axiom, and is done in + `QuadraticForm/PlaneTransitivity.lean`. + +## References + +* I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de Campinas, + 1988, II.6. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Math. **655**, Springer 1978, + III, (1.5), (1.6), (2.2), (4.2). +-/ + +@[expose] public section + +universe u v w + +namespace QuadraticForm + +variable (R : Type u) [CommRing R] + +/-- The **hyperbolic plane** `(a, b) ↦ a * b` on `R × R`. + +This is the elementary model of `QuadraticForm.dualProd R R`, written without dual modules so +that computations with an explicit hyperbolic pair stay computational. -/ +def plane : QuadraticForm R (R × R) := + QuadraticMap.linMulLin (LinearMap.fst R R R) (LinearMap.snd R R R) + +variable {R} + +@[simp] theorem plane_apply (x : R × R) : plane R x = x.1 * x.2 := rfl + +theorem polar_plane (x y : R × R) : + QuadraticMap.polar (plane R) x y = x.1 * y.2 + x.2 * y.1 := by + simp only [QuadraticMap.polar, plane_apply, Prod.fst_add, Prod.snd_add] + ring + +/-- The polar form of the hyperbolic plane at the unit of `R × R` is the sum of the coordinates. +This is the trace of the split quadratic étale algebra. -/ +@[simp] theorem polar_plane_one (x : R × R) : + QuadraticMap.polar (plane R) 1 x = x.1 + x.2 := by + rw [polar_plane] + simp [add_comm] + +end QuadraticForm + +namespace QuadraticMap + +variable {R : Type u} [CommRing R] {V : Type v} [AddCommGroup V] [Module R V] +variable {Q : QuadraticForm R V} + +/-! ### Hyperbolic pairs -/ + +/-- A **hyperbolic pair** of a quadratic module: two isotropic vectors pairing to `1` under the +un-halved polar form. The submodule they span is a hyperbolic plane. -/ +structure IsHyperbolicPair (Q : QuadraticForm R V) (u v : V) : Prop where + /-- The first vector is isotropic. -/ + apply_left : Q u = 0 + /-- The second vector is isotropic. -/ + apply_right : Q v = 0 + /-- The two vectors pair to `1`. -/ + polar_eq_one : polar Q u v = 1 + +namespace IsHyperbolicPair + +variable {u v : V} + +theorem symm (h : IsHyperbolicPair Q u v) : IsHyperbolicPair Q v u := + ⟨h.apply_right, h.apply_left, by rw [polar_comm]; exact h.polar_eq_one⟩ + +theorem polar_self_left (h : IsHyperbolicPair Q u v) : polar Q u u = 0 := by + rw [polar_self, h.apply_left, smul_zero] + +theorem polar_self_right (h : IsHyperbolicPair Q u v) : polar Q v v = 0 := by + rw [polar_self, h.apply_right, smul_zero] + +/-- The standard hyperbolic pair of the hyperbolic plane. -/ +theorem plane (R : Type u) [CommRing R] : + IsHyperbolicPair (QuadraticForm.plane R) (1, 0) (0, 1) where + apply_left := mul_zero 1 + apply_right := zero_mul 1 + polar_eq_one := by rw [QuadraticForm.polar_plane]; ring + +/-- **The explicit splitting along a hyperbolic pair.** Every `w` is the sum of its components +along `u` and `v` and a vector orthogonal to both. + +This is the computational form of `V = ⟨u, v⟩ ⊥ ⟨u, v⟩^⊥`, and it is all that `Dias II.6.2` uses +of that decomposition. -/ +theorem decomposition (h : IsHyperbolicPair Q u v) (w : V) : + polar Q (w - polar Q w v • u - polar Q w u • v) u = 0 ∧ + polar Q (w - polar Q w v • u - polar Q w u • v) v = 0 := by + have huv : polar Q u v = 1 := h.polar_eq_one + have hvu : polar Q v u = 1 := by rw [polar_comm]; exact huv + constructor + · rw [polar_sub_left, polar_sub_left, polar_smul_left, polar_smul_left, h.polar_self_left, hvu] + simp + · rw [polar_sub_left, polar_sub_left, polar_smul_left, polar_smul_left, h.polar_self_right, huv] + simp + +end IsHyperbolicPair + +/-! ### Siegel–Eichler transvections + +The transvection, its isometry property and its bijectivity are TauCeti's +`QuadraticMap.transvection`; here it is packaged as a self-isometry of `Q`, with its formula in +the variables used below. -/ + +/-- The **Siegel–Eichler transvection** `E(x, y)` attached to an isotropic `x` and a vector `y` +orthogonal to it, as a self-isometry of `Q`: +`E(x, y) z = z + b(z, x) • y - (b(z, y) + q y * b(z, x)) • x`. It is TauCeti's +`QuadraticMap.transvection`. Unlike a hyperplane reflection it needs no unit, so it is available +in characteristic 2 and over any commutative ring. -/ +noncomputable def eichler {x y : V} (hx : Q x = 0) (hxy : polar Q x y = 0) : Q.IsometryEquiv Q := + TauCeti.QuadraticMap.orthogonalGroupEquivIsometryEquiv Q + ⟨QuadraticMap.transvection Q hx hxy, QuadraticMap.transvection_mem_orthogonalGroup hx hxy⟩ + +@[simp] theorem eichler_apply {x y : V} (hx : Q x = 0) (hxy : polar Q x y = 0) (z : V) : + eichler hx hxy z = z + polar Q x z • y - (polar Q y z + Q y * polar Q x z) • x := by + simp only [eichler, TauCeti.QuadraticMap.coe_orthogonalGroupEquivIsometryEquiv, + QuadraticMap.transvection_apply] + rw [polar_comm Q z x, polar_comm Q z y] + module + +/-- **Building a hyperbolic pair from a dual vector.** If `u` is isotropic and some `w` pairs with +it to `1`, then `(u, -q(w) • u + w)` is a hyperbolic pair. This is the construction in the proof of +`GPR 11.17`, isolated from the hypotheses used to *produce* `w`. + +Only additivity is used, so this is valid in characteristic 2: the correction term `-q(w) • u` +replaces the "complete the square" step that would divide by `2`. -/ +theorem isHyperbolicPair_neg_smul_add {u w : V} (hu : Q u = 0) (huw : polar Q u w = 1) : + IsHyperbolicPair Q u (-Q w • u + w) where + apply_left := hu + apply_right := by + have key : ∀ (a : R) (x y : V), Q (a • x + y) = (a * a) * Q x + Q y + a * polar Q x y := by + intro a x y + rw [show Q (a • x + y) = Q (a • x) + Q y + polar Q (a • x) y from by rw [polar]; ring, + Q.map_smul, polar_smul_left, smul_eq_mul, smul_eq_mul] + rw [key, hu, huw] + ring + polar_eq_one := by + rw [polar_add_right, polar_smul_right, polar_self, hu, huw] + simp + +/-! ### The expansion of `Q` along a hyperbolic pair -/ + +namespace IsHyperbolicPair + +variable {u v : V} + +/-- Expanding `Q` on a vector shifted by the two members of a hyperbolic pair. All the identities +below are corollaries of this one computation. -/ +theorem apply_add_smul_add_smul (h : IsHyperbolicPair Q u v) (w : V) (s t : R) : + Q (w + s • u + t • v) = Q w + s * polar Q w u + t * polar Q w v + s * t := by + have key : ∀ a b : V, Q (a + b) = Q a + Q b + polar Q a b := fun a b ↦ by + rw [polar]; ring + rw [key, key, Q.map_smul, Q.map_smul, h.apply_left, h.apply_right] + simp only [polar_add_left, polar_smul_left, polar_smul_right, h.polar_eq_one, smul_eq_mul, + mul_zero, add_zero] + ring + +/-- A hyperbolic pair is carried to a hyperbolic pair by an isometry. -/ +theorem map {V' : Type w} [AddCommGroup V'] [Module R V'] {Q' : QuadraticForm R V'} + (h : IsHyperbolicPair Q u v) (f : Q.IsometryEquiv Q') : + IsHyperbolicPair Q' (f u) (f v) where + apply_left := by rw [f.map_app]; exact h.apply_left + apply_right := by rw [f.map_app]; exact h.apply_right + polar_eq_one := by + rw [polar, ← map_add, f.map_app, f.map_app, f.map_app, ← polar] + exact h.polar_eq_one + +end IsHyperbolicPair + +/-! ### Dilations along a hyperbolic pair -/ + +namespace IsHyperbolicPair + +variable {u v : V} + +/-- The **dilation** `φ(l)` attached to a hyperbolic pair `(u, v)` and a unit `l`: it scales `u` by +`l`, scales `v` by `l⁻¹`, and fixes every vector orthogonal to both (`Baeza III §2`'s `P(λ)`, +`Dias II.6`'s `φ(λ)`). It is TauCeti's `TauCeti.QuadraticMap.hyperbolicPairTorus`, packaged as a +self-isometry of `Q`. Unlike a Siegel–Eichler transvection it needs a unit, but only a unit of +`R`, never an invertible value of the form. -/ +noncomputable def dilation (h : IsHyperbolicPair Q u v) (l : Rˣ) : Q.IsometryEquiv Q := + TauCeti.QuadraticMap.orthogonalGroupEquivIsometryEquiv Q + (TauCeti.QuadraticMap.hyperbolicPairTorus Q h.apply_left h.apply_right h.polar_eq_one l) + +/-- The dilation `φ(l)` scales `u` by `l`. -/ +theorem dilation_left (h : IsHyperbolicPair Q u v) (l : Rˣ) : h.dilation l u = (l : R) • u := by + simp only [dilation, TauCeti.QuadraticMap.coe_orthogonalGroupEquivIsometryEquiv, + TauCeti.QuadraticMap.hyperbolicPairTorus_apply_left] + +/-! ### Moving one hyperbolic pair to another: the unit case -/ + +/-- **The unit case of `Dias II.6.2`.** Let `(u, v)` be a hyperbolic pair and let `(i, j)` be +another one whose first vector `i = z + α • u + β • v` has `α` a **unit**, with `z` orthogonal to +`u` and `v`. Then a self-isometry of `Q` carries `(u, v)` to `(i, j)`. + +The isometry is an explicit product `E(i, z') ∘ E(v, α⁻¹ • z) ∘ φ(α)` of two Siegel–Eichler +transvections and a dilation, exactly as in `Dias II.6.2` (`Baeza III (4.2)`). Nothing here needs +the base ring to be an LG ring: that hypothesis enters only in reducing the general case to this +one, by producing the unit `α` (`Dias II.6.1`). -/ +theorem exists_isometryEquiv_of_isUnit (huv : IsHyperbolicPair Q u v) + {i j : V} (hij : IsHyperbolicPair Q i j) {a : Rˣ} {b : R} {z : V} + (hzu : polar Q u z = 0) (hzv : polar Q v z = 0) + (hi : i = z + (a : R) • u + b • v) : + ∃ σ : Q.IsometryEquiv Q, σ u = i ∧ σ v = j := by + set c : R := ((a⁻¹ : Rˣ) : R) with hc + have hainv : (a : R) * c = 1 := by + rw [hc, ← Units.val_mul, mul_inv_cancel, Units.val_one] + have hvu : polar Q v u = 1 := by rw [polar_comm]; exact huv.polar_eq_one + -- `Q i = 0` pins down the coefficient `b`. + have hb : (a : R) * b = -Q z := by + have hexp := huv.apply_add_smul_add_smul z (a : R) b + rw [← hi, hij.apply_left, polar_comm Q z u, hzu, polar_comm Q z v, hzv] at hexp + linear_combination -hexp + have hb' : b = -(c * Q z) := by linear_combination c * hb - b * hainv + -- Step 1: `ψ = E(v, α⁻¹ • z) ∘ φ(α)` carries `u` to `i`. + set y : V := c • z with hy + have hvy : polar Q v y = 0 := by rw [hy, polar_smul_right, hzv, smul_zero] + have hyu : polar Q y u = 0 := by + rw [hy, polar_smul_left, polar_comm Q z u, hzu, smul_zero] + set ψ : Q.IsometryEquiv Q := (huv.dilation a).trans (eichler huv.apply_right hvy) with hψ + have hψu : ψ u = i := by + have hstep : ψ u = eichler huv.apply_right hvy ((a : R) • u) := by + rw [hψ] + change eichler huv.apply_right hvy (huv.dilation a u) = _ + rw [huv.dilation_left] + have hay : (a : R) • y = z := by rw [hy, smul_smul, hainv, one_smul] + have hQya : Q y * (a : R) = c * Q z := by + rw [hy, Q.map_smul, smul_eq_mul] + linear_combination (c * Q z) * hainv + rw [hstep, eichler_apply, polar_smul_right, hvu, polar_smul_right, hyu, hi, hb'] + simp only [smul_eq_mul, mul_one] + rw [hQya, hay] + module + -- Step 2: `(i, ψ v)` is a hyperbolic pair. + set w : V := ψ v with hw + have hiw : IsHyperbolicPair Q i w := by + have hmap := huv.map ψ + rwa [hψu] at hmap + -- Step 3: correct `ψ v` to `j` by one more transvection. + set z' : V := j - polar Q j w • i - polar Q j i • w with hz' + obtain ⟨hz'i, hz'w⟩ := hiw.decomposition j + rw [← hz'] at hz'i hz'w + have hji : polar Q j i = 1 := by rw [polar_comm]; exact hij.polar_eq_one + have hjdec : j = z' + polar Q j w • i + (1 : R) • w := by + rw [hz', hji]; module + have hlam : polar Q j w = -Q z' := by + have hexp := hiw.apply_add_smul_add_smul z' (polar Q j w) 1 + rw [← hjdec, hij.apply_right, hz'i, hz'w] at hexp + linear_combination -hexp + have hiz' : polar Q i z' = 0 := by rw [polar_comm]; exact hz'i + refine ⟨ψ.trans (eichler hiw.apply_left hiz'), ?_, ?_⟩ + · change eichler hiw.apply_left hiz' (ψ u) = i + rw [hψu, eichler_apply, polar_self, hiw.apply_left, polar_comm Q z' i, hiz'] + simp + · change eichler hiw.apply_left hiz' (ψ v) = j + rw [← hw, eichler_apply, hiw.polar_eq_one, hz'w, mul_one, zero_add] + conv_rhs => rw [hjdec, hlam] + module + +end IsHyperbolicPair + +end QuadraticMap diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Isotropic.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Isotropic.lean new file mode 100644 index 0000000000..8eb957cea4 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Isotropic.lean @@ -0,0 +1,277 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.Radical +public import Mathlib.LinearAlgebra.FreeModule.PID +public import Mathlib.RingTheory.Flat.TorsionFree +public import LeanPool.CompositionAlgebrasOverRings.Module.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.HyperbolicPair +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity + +/-! +# GPR-sense isotropy + +Defines `QuadraticMap.IsGPRIsotropic`: `Q` is isotropic iff it has a **unimodular** null vector +(`GPR 11.17`), not merely a nonzero one. + +⚠ **This is not mathlib's `QuadraticMap.Anisotropic`.** `¬ Q.Anisotropic` unfolds to "there is a +*nonzero* `x` with `Q x = 0`". GPR's isotropy demands a *unimodular* null vector — strictly stronger +over a general ring, since unimodularity (mathlib's `Module.IsUnimodular`: some functional takes the +value `1` at `u`, equivalently `R·u` is a free rank-1 direct summand, `GPR 9.13`) asks +for more than `u ≠ 0`. The two notions coincide over a field, and `GPR Exc. 12.38(c)` shows they +also coincide for finitely generated projective (that is, finite free) modules over a PID (the +module hypothesis is needed: the zero form on the `ℤ`-module `ℤ/2` has a nonzero null vector but no +unimodular element); in general they do not, and the reduced-composition-algebra layer (`GPR 22.9` +ff.) needs the GPR notion specifically. See overview §6(c). + +The name carries its source, as for the regularity ladder (`QuadraticForm.IsGPRNondegenerate`, +`IsGPRNonsingular`, `IsGPRRegular` in `QuadraticForm/Regularity.lean`): there is no bare +`IsIsotropic` here, precisely because "isotropic" means two different things in mathlib and in +`GPR` and a bare name would hide which one is meant. + +## Main definitions + +* `QuadraticMap.IsGPRIsotropic` : `Q` has a unimodular null vector. + +## `GPR 11.17`: isotropic vectors extend to hyperbolic pairs + +`GPR 11.17` proves that for a *quadratic space* — a **regular** form in the sense of +`QuadraticForm.IsGPRRegular` — a vector is isotropic exactly when it is the first member of a +hyperbolic pair. That is `QuadraticForm.isGPRIsotropic_iff_exists_isHyperbolicPair` below, with +`exists_isHyperbolicPair_of_isUnimodular` for the substantive direction: regularity solves +`l = q(·, w)` for the functional `l` witnessing unimodularity, and then `-q(w) • u + w` completes +`u` to a pair. + +⚠ Over a field, **non-singularity is enough and regularity is not necessary**: a non-singular form +of odd rank in characteristic 2 is not regular (`QuadraticForm.rankOne`), yet its isotropic vectors +still extend. So `exists_isHyperbolicPair_of_radical_eq_bot` is *not* a special case of `GPR 11.17`; +it is the version the Witt-cancellation chain consumes at each residue field, where the forms being +cancelled are only assumed non-singular (`GN 6.5`, not `GPR 11.27`). + +## Main results + +* `QuadraticMap.IsGPRIsotropic.not_anisotropic` : over a nontrivial ring, GPR-isotropic implies + not mathlib-anisotropic. (This is the direction that always holds.) +* `QuadraticMap.IsGPRIsotropic.map_isometryEquiv` : isotropy transports along an isometry + equivalence. +* `QuadraticForm.isGPRIsotropic_dualProd` : the hyperbolic form `dualProd R M` is isotropic + whenever `M` contains a unimodular element. +* `QuadraticMap.isGPRIsotropic_iff_not_anisotropic` : over a **field**, the two notions coincide — + every nonzero vector is unimodular (`Module.isUnimodular_of_ne_zero`), so the extra strength GPR's + definition carries over a general ring disappears entirely over a field. + +`GPR Exc. 12.38(c)` — that the two notions already coincide for a finitely generated projective, +hence finite free, module over a **PID**, more generally than a field — is proved below by +generating the ideal of the coordinates of a nonzero vector. A generator divides every coordinate; +dividing by it gives a primitive, hence unimodular, vector. Homogeneity and the domain hypothesis +preserve the null-vector equation. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 9.13, + 11.17, Exc. 12.38, 22.19. +* [GN] Gille, Neher, *Group schemes over LG-rings…*, European Journal of Mathematics **11** (2025), + article 42, 6.5. +-/ + +@[expose] public section + +universe u v w + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + {N : Type w} [AddCommGroup N] [Module R N] + +/-- `Q` is **isotropic** in the GPR sense: it has a *unimodular* null vector (`GPR 11.17`). -/ +def QuadraticMap.IsGPRIsotropic (Q : QuadraticMap R M N) : Prop := + ∃ u : M, Module.IsUnimodular R u ∧ Q u = 0 + +namespace QuadraticMap.IsGPRIsotropic + +/-- GPR-sense isotropy transports along an isometry equivalence. The null vector is carried by +the underlying linear equivalence, which also preserves unimodularity. -/ +theorem map_isometryEquiv {Q₁ : QuadraticMap R M N} {M' : Type*} [AddCommGroup M'] [Module R M'] + {Q₂ : QuadraticMap R M' N} (h : Q₁.IsGPRIsotropic) (e : Q₁.IsometryEquiv Q₂) : + Q₂.IsGPRIsotropic := by + obtain ⟨u, hu, hQu⟩ := h + exact ⟨e u, hu.map e.toLinearEquiv, by rw [e.map_app, hQu]⟩ + +theorem not_anisotropic [Nontrivial R] {Q : QuadraticMap R M N} (h : Q.IsGPRIsotropic) : + ¬ Q.Anisotropic := by + obtain ⟨u, hu, hQu⟩ := h + intro hA + obtain rfl := hA u hQu + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hu + rw [map_zero] at hl + exact zero_ne_one hl + +end QuadraticMap.IsGPRIsotropic + +/-- Over a field, a not-anisotropic quadratic map is GPR-isotropic: the nonzero null vector mathlib +gives you is automatically unimodular. -/ +theorem QuadraticMap.isGPRIsotropic_of_not_anisotropic {K : Type u} [Field K] {M : Type v} + [AddCommGroup M] [Module K M] {N : Type w} [AddCommGroup N] [Module K N] + {Q : QuadraticMap K M N} (h : ¬ Q.Anisotropic) : Q.IsGPRIsotropic := by + obtain ⟨x, hx, hQx⟩ := (QuadraticMap.not_anisotropic_iff_exists Q).mp h + exact ⟨x, Module.isUnimodular_of_ne_zero hx, hQx⟩ + +/-- Over a field, GPR-sense isotropy and mathlib's `¬ Anisotropic` are the same notion. -/ +theorem QuadraticMap.isGPRIsotropic_iff_not_anisotropic {K : Type u} [Field K] {M : Type v} + [AddCommGroup M] [Module K M] {N : Type w} [AddCommGroup N] [Module K N] + {Q : QuadraticMap K M N} : Q.IsGPRIsotropic ↔ ¬ Q.Anisotropic := + ⟨fun h ↦ h.not_anisotropic, QuadraticMap.isGPRIsotropic_of_not_anisotropic⟩ + +/-! ### `GPR Exc. 12.38(c)`: isotropy over a PID -/ + +private theorem exists_smul_isUnimodular_of_ne_zero_of_pid + {R : Type u} [CommRing R] [IsDomain R] [IsPrincipalIdealRing R] + {M : Type v} [AddCommGroup M] [Module R M] [Module.Finite R M] [Module.Projective R M] + {x : M} (hx : x ≠ 0) : + ∃ d : R, d ≠ 0 ∧ ∃ u : M, Module.IsUnimodular R u ∧ x = d • u := by + classical + let : Module.IsTorsionFree R M := inferInstance + obtain ⟨n, b⟩ := Module.basisOfFiniteTypeTorsionFree' (R := R) (M := M) + let f : Fin n → R := fun i ↦ b.equivFun x i + let I : Ideal R := Ideal.span (Set.range f) + obtain ⟨d, hdI⟩ := (IsPrincipalIdealRing.principal I).principal + have hdiv (i : Fin n) : d ∣ f i := by + rw [← Ideal.mem_span_singleton] + have hfi : f i ∈ I := Ideal.subset_span (Set.mem_range_self i) + rwa [hdI] at hfi + choose g hg using hdiv + let u : M := b.equivFun.symm g + have hxu : x = d • u := by + apply b.equivFun.injective + funext i + simp only [map_smul, b.equivFun.apply_symm_apply, Pi.smul_apply, smul_eq_mul, u] + change f i = d * g i + exact hg i + have hd : d ≠ 0 := by + intro hd + apply hx + rw [hxu, hd, zero_smul] + have hdmem : d ∈ Ideal.span (Set.range f) := by + change d ∈ I + rw [hdI] + exact Ideal.mem_span_singleton_self d + obtain ⟨a, ha⟩ := Ideal.mem_span_range_iff_exists_fun.mp hdmem + have hsum : ∑ i, g i * a i = 1 := by + apply mul_left_cancel₀ hd + calc + d * (∑ i, g i * a i) = ∑ i, a i * f i := by + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro i _ + rw [hg i] + ring + _ = d := ha + _ = d * 1 := by rw [mul_one] + let l : Module.Dual R M := b.constr R a + have hlu : l u = 1 := by + rw [Module.Basis.constr_apply_fintype] + simp only [u, b.equivFun.apply_symm_apply, smul_eq_mul] + exact hsum + exact ⟨d, hd, u, Module.isUnimodular_of_apply_eq_one (f := l) hlu, hxu⟩ + +/-- **`GPR Exc. 12.38(c)`**, for quadratic forms and with its trivial converse: over a PID, a +quadratic form has a unimodular null vector if and only if it has a nonzero null vector. The module +is only assumed finitely generated projective, which over a PID means finite free. `GPR 22.19` +applies this to the norm of a composition algebra (its conditions (ii) and (iii)). -/ +theorem QuadraticMap.isGPRIsotropic_iff_not_anisotropic_of_pid + {R : Type u} [CommRing R] [IsDomain R] [IsPrincipalIdealRing R] + {M : Type v} [AddCommGroup M] [Module R M] [Module.Finite R M] [Module.Projective R M] + {Q : QuadraticForm R M} : Q.IsGPRIsotropic ↔ ¬ Q.Anisotropic := by + refine ⟨fun h ↦ h.not_anisotropic, fun h ↦ ?_⟩ + obtain ⟨x, hx, hQx⟩ := (QuadraticMap.not_anisotropic_iff_exists Q).mp h + obtain ⟨d, hd, u, hu, hxu⟩ := + exists_smul_isUnimodular_of_ne_zero_of_pid (R := R) (M := M) hx + refine ⟨u, hu, ?_⟩ + have hzero : d ^ 2 * Q u = 0 := by + simpa only [hxu, QuadraticMap.map_smul, smul_eq_mul, pow_two] using hQx + exact (mul_eq_zero.mp hzero).resolve_left (pow_ne_zero 2 hd) + +/-! ### `GPR 11.17`: isotropic vectors and hyperbolic pairs -/ + +namespace QuadraticForm + +open _root_.QuadraticMap (polar polar_comm polar_smul_right IsHyperbolicPair + isHyperbolicPair_neg_smul_add) + +variable {Q : QuadraticForm R M} + +/-- The hyperbolic form `dualProd R M` is GPR-isotropic as soon as `M` contains a unimodular +element `m`. The null vector is `(0, m)`; a functional taking `m` to `1` extends across the product +by the second projection. -/ +theorem isGPRIsotropic_dualProd {m : M} (hm : Module.IsUnimodular R m) : + (dualProd R M).IsGPRIsotropic := by + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hm + refine ⟨(0, m), Module.isUnimodular_of_apply_eq_one + (f := l.comp (LinearMap.snd R (Module.Dual R M) M)) ?_, ?_⟩ + · simpa only [LinearMap.comp_apply, LinearMap.snd_apply] using hl + · simp only [dualProd_apply, LinearMap.zero_apply] + +/-- **`GPR 11.17`, `(i) ⇒ (ii)`.** In a **regular** quadratic module an isotropic vector — a +unimodular `u` with `q u = 0` — extends to a hyperbolic pair. + +Regularity is used exactly once, to solve `l = q(·, w)` for the functional `l` with `l u = 1` +supplied by unimodularity (`GPR 9.13`); then `GPR`'s formula `v = -q(w) • u + w` finishes the job +(`QuadraticMap.isHyperbolicPair_neg_smul_add`). -/ +theorem exists_isHyperbolicPair_of_isUnimodular (hQ : Q.IsGPRRegular) {u : M} + (hu : Module.IsUnimodular R u) (hqu : Q u = 0) : ∃ v : M, IsHyperbolicPair Q u v := by + obtain ⟨l, hl⟩ := Module.isUnimodular_iff.mp hu + obtain ⟨w, hw⟩ := hQ.2 l + have huw : polar Q u w = 1 := by + have h := DFunLike.congr_fun hw u + rw [QuadraticMap.polarBilin_apply_apply, hl] at h + rw [polar_comm] + exact h + exact ⟨_, isHyperbolicPair_neg_smul_add hqu huw⟩ + +/-- **`GPR 11.17`, `(ii) ⇒ (i)`.** The first member of a hyperbolic pair is isotropic in the GPR +sense: it is unimodular, since `q(·, v)` sends it to `1`. No hypothesis on `Q`. -/ +theorem isUnimodular_of_isHyperbolicPair {u v : M} (h : IsHyperbolicPair Q u v) : + Module.IsUnimodular R u := + Module.isUnimodular_of_apply_eq_one (f := QuadraticMap.polarBilin Q v) <| by + rw [QuadraticMap.polarBilin_apply_apply, polar_comm] + exact h.polar_eq_one + +/-- **`GPR 11.17`.** A regular quadratic module is isotropic in the GPR sense exactly when it +contains a hyperbolic pair. -/ +theorem isGPRIsotropic_iff_exists_isHyperbolicPair (hQ : Q.IsGPRRegular) : + Q.IsGPRIsotropic ↔ ∃ u v : M, IsHyperbolicPair Q u v := by + constructor + · rintro ⟨u, hu, hqu⟩ + obtain ⟨v, hv⟩ := exists_isHyperbolicPair_of_isUnimodular hQ hu hqu + exact ⟨u, v, hv⟩ + · rintro ⟨u, v, huv⟩ + exact ⟨u, isUnimodular_of_isHyperbolicPair huv, huv.apply_left⟩ + +/-- **The non-singular analogue of `GPR 11.17` over a field.** A nonzero null vector of a form with +vanishing radical extends to a hyperbolic pair. + +⚠ This is not an instance of `GPR 11.17`: over a field of characteristic 2 a non-singular form of +odd rank has a *degenerate* polar form, so it is not regular, and `GPR 11.17` does not apply. What +replaces regularity is that `u ∉ radical Q` while `Q u = 0`, which forces `q(u, ·) ≠ 0` directly. +This is the form of the statement that the Witt-cancellation chain uses at each residue field +(`Dias II.6.1`), where the forms being cancelled are only non-singular. -/ +theorem exists_isHyperbolicPair_of_radical_eq_bot {F : Type*} [Field F] {V : Type*} + [AddCommGroup V] [Module F V] {q : QuadraticForm F V} (hq : q.radical = ⊥) {u : V} + (hu : u ≠ 0) (hqu : q u = 0) : ∃ v : V, IsHyperbolicPair q u v := by + have hpol : ∃ x : V, polar q u x ≠ 0 := by + by_contra hc + push Not at hc + refine hu ?_ + have hmem : u ∈ q.radical := + ⟨hqu, LinearMap.ext fun x ↦ by rw [QuadraticMap.polarBilin_apply_apply, hc x, + LinearMap.zero_apply]⟩ + rwa [hq, Submodule.mem_bot] at hmem + obtain ⟨x, hx⟩ := hpol + have huw : polar q u ((polar q u x)⁻¹ • x) = 1 := by + rw [polar_smul_right, smul_eq_mul, inv_mul_cancel₀ hx] + exact ⟨_, isHyperbolicPair_neg_smul_add hqu huw⟩ + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/NonsingularOverFields.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/NonsingularOverFields.lean new file mode 100644 index 0000000000..10205eb8eb --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/NonsingularOverFields.lean @@ -0,0 +1,549 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import Mathlib.LinearAlgebra.QuadraticForm.Radical +public import Mathlib.LinearAlgebra.QuadraticForm.Prod +public import Mathlib.FieldTheory.IsAlgClosed.AlgebraicClosure +public import Mathlib.RingTheory.Flat.Equalizer +public import Mathlib.Algebra.Polynomial.Degree.SmallDegree + +/-! +# Non-singular quadratic forms over fields: `EKM Lemma 7.16` and `GPR Exercise 11.37` + +Over a field, the base-change-stable regularity condition `QuadraticForm.IsGPRNonsingular` admits +a finite, checkable characterisation: `Q` is non-singular iff its radical vanishes *and* the +radical of its polar form is at most a line. That is `EKM Lemma 7.16`, and `GPR Exercise 11.37` +with one extra rung. This file proves both, and the part of `GPR Exc. 11.37`'s Remark (1) that +describes what the two cases look like. + +## Relation to mathlib + +Both mathlib notions from `Mathlib/LinearAlgebra/QuadraticForm/Radical.lean` are used directly; +this development defines no competing radical or non-degeneracy predicate. + +* `QuadraticMap.radical` — the submodule of vectors on which both `Q` and its polar form vanish — + is *the* radical throughout, including in `QuadraticForm/Regularity.lean`, where the whole + regularity ladder (`IsGPRNondegenerate`, `IsGPRNonsingular`, `IsEKMNondegenerate`) is phrased + as `radical … = ⊥`. +* `QuadraticMap.Nondegenerate` *is* `EKM`'s condition (3), taken as mathlib's definition. Our + `QuadraticForm.IsEKMNondegenerate` formalizes `EKM`'s condition (1) instead, since that is the + one that reads verbatim as a base-change statement, and `IsGPRNonsingular` is its ring-level + generalisation, which mathlib has no name for. `EKM 7.16` is exactly the assertion that + condition (1) and mathlib's predicate agree; that is + `QuadraticForm.isEKMNondegenerate_iff_nondegenerate` below. + +⚠ Do not read mathlib's `QuadraticMap.Nondegenerate` as GPR's "non-degenerate": it is strictly +stronger, and over a field it is GPR's **non-singular** rung. GPR's "non-degenerate" is the bare +`radical Q = ⊥`, i.e. `QuadraticForm.IsGPRNondegenerate`. + +## Main results + +* `QuadraticForm.finrank_le_one_of_anisotropic_of_isAlgClosed` : over an algebraically closed + field an anisotropic quadratic form has dimension at most `1`. Proved in every characteristic + by finding a root of `Q(e) t² + b(e, f) t + Q(f)`, so it applies in the characteristic-`2` case + that mathlib's `QuadraticForm/AlgClosed.lean` (which assumes `Invertible (2 : K)`) does not + cover. +* `QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective` : the radical of the polar form + commutes with base change, hence has the same dimension. Flatness of `L` over `F`, via + mathlib's `LinearMap.tensorKerEquiv`. +* `QuadraticForm.isGPRNonsingular_iff_nondegenerate`, + `QuadraticForm.isEKMNondegenerate_iff_nondegenerate` : **`EKM Lemma 7.16`**, as the equivalence + of conditions (1) and (3), and its restatement for `IsEKMNondegenerate`. +* `QuadraticForm.isGPRNonsingular_tfae` : **`GPR Exercise 11.37`**, all four conditions. +* `QuadraticForm.isGPRNonsingular_of_isAlgClosed` : `GPR Exc. 11.37` (iii) ⇒ (i) for an arbitrary + algebraically closed `K`, which is what makes the "for some `K`" reading of (iii) legitimate. +* `QuadraticForm.isGPRRegular_xor_finrank_ker_polarBilin_eq_one`, + `QuadraticForm.ringChar_eq_two_of_finrank_ker_polarBilin_eq_one`, + `QuadraticForm.exists_isometryEquiv_rankOne_prod` : **`GPR Exc. 11.37`, Remark (1)** — see below. + +## `GPR Exc. 11.37`, Remark (1), and what is missing + +Remark (1) says that for finite-dimensional `V`, condition (ii) holds iff *exactly one* of + +(a) `char F = 2`, `dim V` is odd, and `Q ≅ ⟨α⟩ ⊥ Q₀` with `Q₀` regular and `α ∈ Fˣ`; +(b) `Q` is regular + +holds. Everything here is proved except **the parity clause "`dim V` is odd" in (a)**: + +* the dichotomy — the polar radical of a non-degenerate form is either `0` (case (b)) or a line + (case (a)), exclusively — is `isGPRRegular_xor_finrank_ker_polarBilin_eq_one`; +* `char F = 2` in case (a) is `ringChar_eq_two_of_finrank_ker_polarBilin_eq_one`; +* the decomposition in case (a) is `exists_isometryEquiv_rankOne_prod`, and needs no + orthogonalisation: the generator `u` of the polar radical is orthogonal to everything already, + so *any* complement of `F u` splits `Q` orthogonally. + +The missing clause is not about quadratic forms at all. In characteristic `2` the polar form is +alternating, and "`dim V` odd" is the statement that an alternating bilinear form on a +finite-dimensional space has `dim V ≡ dim (rad b) (mod 2)` — equivalently that a non-degenerate +alternating form forces even dimension, the symplectic-basis theorem. mathlib has neither that +nor the Pfaffian, and proving it means the usual induction: split off a hyperbolic plane +`span {v, w}` with `b v w = 1`, pass to `{x | b v x = 0 ∧ b w x = 0}`, and induct. That is a +self-contained piece of bilinear algebra, better placed in a file of its own (or upstreamed) +than bolted on here. It is not attempted in this file. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +/-! ## Part A: isotropy over an algebraically closed field -/ + +section AlgClosed + +variable {K : Type*} [Field K] [IsAlgClosed K] + {W : Type*} [AddCommGroup W] [Module K W] + +theorem QuadraticForm.exists_ne_zero_eq_zero_of_isAlgClosed (Q : QuadraticForm K W) + {e f : W} (he : e ≠ 0) (hf : ∀ t : K, t • e + f ≠ 0) : + ∃ w, w ≠ 0 ∧ Q w = 0 := by + by_cases hQe : Q e = 0 + · exact ⟨e, he, hQe⟩ + · obtain ⟨t, ht⟩ := IsAlgClosed.exists_root + (Polynomial.C (Q e) * Polynomial.X ^ 2 + + Polynomial.C (QuadraticMap.polar Q e f) * Polynomial.X + Polynomial.C (Q f)) + (by rw [Polynomial.degree_quadratic hQe]; decide) + refine ⟨t • e + f, hf t, ?_⟩ + have hroot : Q e * t ^ 2 + QuadraticMap.polar Q e f * t + Q f = 0 := by + simpa using ht + rw [QuadraticMap.map_add (⇑Q) (t • e) f, QuadraticMap.map_smul, + QuadraticMap.polar_smul_left, smul_eq_mul, smul_eq_mul] + rw [← hroot]; ring + +theorem QuadraticForm.finrank_le_one_of_anisotropic_of_isAlgClosed [FiniteDimensional K W] + (Q : QuadraticForm K W) (hQ : Q.Anisotropic) : Module.finrank K W ≤ 1 := by + by_contra hlt + rw [not_le] at hlt + set b := Module.finBasis K W with hb + set i₀ : Fin (Module.finrank K W) := ⟨0, by omega⟩ with hi₀ + set i₁ : Fin (Module.finrank K W) := ⟨1, hlt⟩ with hi₁ + have hne : i₀ ≠ i₁ := by simp [hi₀, hi₁, Fin.ext_iff] + obtain ⟨x, hx, hQx⟩ := Q.exists_ne_zero_eq_zero_of_isAlgClosed (b.ne_zero i₀) (f := b i₁) + (fun t ht ↦ by + have := congrArg (fun y ↦ b.repr y i₁) ht + simp [Module.Basis.repr_self, hne] at this) + exact hx (hQ x hQx) + +end AlgClosed + +/-! ## Part B: base change of the radical of the polar form -/ + +section PolarKernel + +variable {F : Type u} [Field F] {V : Type v} [AddCommGroup V] [Module F V] + [Module.Finite F V] [Module.Projective F V] + {L : Type*} [Field L] [Algebra F L] + +/-- The polar form of a base-changed quadratic form has the same kernel as the base change of +the polar form as a plain linear map: the two differ by the dual-comparison isomorphism of +`GPR 9.15`, which is injective. -/ +theorem QuadraticForm.ker_polarBilin_baseChangeOfProjective (Q : QuadraticForm F V) : + LinearMap.ker (QuadraticMap.polarBilin (Q.baseChangeOfProjective L)) = + LinearMap.ker (LinearMap.baseChange L + (QuadraticMap.polarBilin Q : V →ₗ[F] Module.Dual F V)) := by + rw [QuadraticForm.polarBilin_baseChangeOfProjective, + LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange] + exact LinearMap.ker_comp_of_ker_eq_bot _ + (LinearMap.ker_eq_bot_of_injective + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := F) (M := V) (A := L)).injective) + +/-- **The radical of the polar form is compatible with base change.** Its dimension is unchanged: +`L` is flat over the field `F`, so `L ⊗[F] ker b ≃ ker b_L` (`LinearMap.tensorKerEquiv`). -/ +theorem QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective (Q : QuadraticForm F V) : + Module.finrank L (LinearMap.ker (QuadraticMap.polarBilin (Q.baseChangeOfProjective L))) = + Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) := by + rw [QuadraticForm.ker_polarBilin_baseChangeOfProjective] + have e : L ⊗[F] (LinearMap.ker (QuadraticMap.polarBilin Q)) ≃ₗ[L] + LinearMap.ker (LinearMap.baseChange L + (QuadraticMap.polarBilin Q : V →ₗ[F] Module.Dual F V)) := + LinearMap.tensorKerEquiv (R := F) L L _ + rw [← e.finrank_eq, Module.finrank_baseChange] + +/-- A vector killed by the polar form stays killed after base change. -/ +theorem QuadraticForm.one_tmul_mem_ker_polarBilin_baseChangeOfProjective (Q : QuadraticForm F V) + {u : V} (hu : u ∈ LinearMap.ker (QuadraticMap.polarBilin Q)) : + (1 : L) ⊗ₜ[F] u ∈ + LinearMap.ker (QuadraticMap.polarBilin (Q.baseChangeOfProjective L)) := by + rw [QuadraticForm.ker_polarBilin_baseChangeOfProjective, LinearMap.mem_ker, + LinearMap.baseChange_tmul, LinearMap.mem_ker.mp hu, TensorProduct.tmul_zero] + +end PolarKernel + +/-! ## Part C: the two substantive implications -/ + +section TFAE + +variable {F : Type u} [Field F] {V : Type v} [AddCommGroup V] [Module F V] + [FiniteDimensional F V] + +omit [FiniteDimensional F V] in +/-- A nonzero vector stays nonzero in `L ⊗[F] V`: apply a functional separating it from `0`. -/ +theorem QuadraticForm.one_tmul_ne_zero {L : Type*} [Field L] [Algebra F L] {u : V} (hu : u ≠ 0) : + (1 : L) ⊗ₜ[F] u ≠ 0 := by + obtain ⟨φ, hφ⟩ : ∃ φ : Module.Dual F V, φ u ≠ 0 := by + by_contra hcon + simp only [not_exists, not_not] at hcon + exact hu ((Module.forall_dual_apply_eq_zero_iff F u).mp hcon) + intro hzero + have h1 := congrArg (TensorProduct.rid F L ∘ LinearMap.baseChange L φ) hzero + simp only [Function.comp_apply, LinearMap.baseChange_tmul, TensorProduct.rid_tmul, + map_zero] at h1 + exact hφ ((injective_iff_map_eq_zero _).mp (algebraMap F L).injective _ + (by simpa [Algebra.smul_def] using h1)) + +/-- **`EKM 7.16`, (3) ⇒ (1); `GPR Exc. 11.37`, (ii) ⇒ (i).** If the radical of `Q` vanishes and the +radical of its polar form has dimension at most `1`, then `Q` is non-singular. + +If `dim (rad b_Q) = 0` the polar radical stays `0` after base change and there is nothing to +kill. If `dim (rad b_Q) = 1`, say `rad b_Q = F u`, then `Q u ≠ 0` (else `u` would lie in the +radical of `Q`), and after base change `rad b_{Q_L} = L (1 ⊗ u)`; an element `a ⊗ u` of the +radical of `Q_L` has `0 = Q_L (a ⊗ u) = Q(u) a²`, forcing `a = 0`. -/ +theorem QuadraticForm.isGPRNonsingular_of_radical_eq_bot_of_finrank_ker_le_one + (Q : QuadraticForm F V) (hrad : Q.radical = ⊥) + (hdim : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) ≤ 1) : + Q.IsGPRNonsingular := by + intro L _ _ + have : Module.Finite L (L ⊗[F] V) := Module.Finite.base_change F L V + refine ((Q.baseChangeOfProjective L).radical.eq_bot_iff).mpr fun x hx ↦ ?_ + set QL := Q.baseChangeOfProjective L with hQL + have hxker : x ∈ LinearMap.ker (QuadraticMap.polarBilin QL) := LinearMap.mem_ker.mpr hx.2 + have hdimL : Module.finrank L (LinearMap.ker (QuadraticMap.polarBilin QL)) ≤ 1 := by + rw [hQL, QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective]; exact hdim + rcases Nat.eq_zero_or_pos (Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q))) + with h0 | h1 + · -- The polar radical is already zero over `F`, hence over `L`. + have : LinearMap.ker (QuadraticMap.polarBilin QL) = ⊥ := by + rw [← Submodule.finrank_eq_zero, hQL, + QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective] + exact h0 + rw [this] at hxker + simpa using hxker + · -- The polar radical is a line `F u`, and `Q u ≠ 0`. + have hone : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1 := + le_antisymm hdim h1 + obtain ⟨u, hu, hune⟩ : ∃ u ∈ LinearMap.ker (QuadraticMap.polarBilin Q), u ≠ 0 := by + by_contra hcon + simp only [not_exists, not_and, not_not] at hcon + rw [(LinearMap.ker (QuadraticMap.polarBilin Q)).eq_bot_iff.mpr hcon, + finrank_bot] at hone + exact one_ne_zero hone.symm + have hQu : Q u ≠ 0 := fun hQu0 ↦ hune (by + have : u ∈ Q.radical := ⟨hQu0, LinearMap.mem_ker.mp hu⟩ + rwa [hrad, Submodule.mem_bot] at this) + -- `rad b_{Q_L}` is the line spanned by `1 ⊗ u`. + have htmul := Q.one_tmul_mem_ker_polarBilin_baseChangeOfProjective (L := L) hu + have hspan : LinearMap.ker (QuadraticMap.polarBilin QL) = L ∙ ((1 : L) ⊗ₜ[F] u) := by + refine (Submodule.eq_of_le_of_finrank_eq ?_ ?_).symm + · rw [Submodule.span_le, Set.singleton_subset_iff]; exact htmul + · rw [finrank_span_singleton (QuadraticForm.one_tmul_ne_zero hune)] + refine (le_antisymm hdimL ?_).symm + rw [hQL, QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective, hone] + rw [hspan, Submodule.mem_span_singleton] at hxker + obtain ⟨a, rfl⟩ := hxker + have hxa : a • ((1 : L) ⊗ₜ[F] u) = a ⊗ₜ[F] u := by + rw [TensorProduct.smul_tmul', smul_eq_mul, mul_one] + rw [hxa] at hx ⊢ + have hQ0 : QL (a ⊗ₜ[F] u) = 0 := hx.1 + rw [hQL, QuadraticForm.baseChangeOfProjective_tmul, Algebra.smul_def] at hQ0 + have ha : a = 0 := by + rcases mul_eq_zero.mp hQ0 with h | h + · exact absurd ((injective_iff_map_eq_zero _).mp (algebraMap F L).injective _ h) hQu + · exact mul_self_eq_zero.mp h + rw [ha, TensorProduct.zero_tmul] + +/-- Half of **`EKM 7.16`, (2) ⇒ (3); `GPR Exc. 11.37`, (iii) ⇒ (ii)**: the radical of `Q` already +vanishes as soon as it vanishes after *one* base change, algebraically closed or not. +`(rad Q)_K ⊆ rad Q_K`, and `1 ⊗ u = 0` forces `u = 0`. -/ +theorem QuadraticForm.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot + {K : Type*} [Field K] [Algebra F K] (Q : QuadraticForm F V) + (hK : (Q.baseChangeOfProjective K).radical = ⊥) : Q.radical = ⊥ := by + rw [(Q.radical).eq_bot_iff] + intro u hu + have hmem : (1 : K) ⊗ₜ[F] u ∈ (Q.baseChangeOfProjective K).radical := by + refine ⟨?_, ?_⟩ + · rw [QuadraticForm.baseChangeOfProjective_tmul, hu.1, zero_smul] + · exact LinearMap.mem_ker.mp + (Q.one_tmul_mem_ker_polarBilin_baseChangeOfProjective (L := K) + (LinearMap.mem_ker.mpr hu.2)) + rw [hK, Submodule.mem_bot] at hmem + by_contra hune + exact QuadraticForm.one_tmul_ne_zero hune hmem + +/-- The other half of **`EKM 7.16`, (2) ⇒ (3); `GPR Exc. 11.37`, (iii) ⇒ (ii)**: over an +algebraically closed `K`, vanishing of `rad Q_K` bounds the dimension of the polar radical by `1`. + +`Q_K` restricted to `rad b_{Q_K}` is anisotropic — an isotropic vector there would lie in +`rad Q_K` — and over an algebraically closed field an anisotropic form has dimension at most one +(`QuadraticForm.finrank_le_one_of_anisotropic_of_isAlgClosed`). The dimension then descends to +`F` because the polar radical commutes with base change. -/ +theorem QuadraticForm.finrank_ker_polarBilin_le_one_of_isAlgClosed + {K : Type*} [Field K] [IsAlgClosed K] [Algebra F K] (Q : QuadraticForm F V) + (hK : (Q.baseChangeOfProjective K).radical = ⊥) : + Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) ≤ 1 := by + have : Module.Finite K (K ⊗[F] V) := Module.Finite.base_change F K V + rw [← QuadraticForm.finrank_ker_polarBilin_baseChangeOfProjective (L := K) Q] + refine QuadraticForm.finrank_le_one_of_anisotropic_of_isAlgClosed + ((Q.baseChangeOfProjective K).comp + (LinearMap.ker (QuadraticMap.polarBilin (Q.baseChangeOfProjective K))).subtype) ?_ + intro w hw + have hmem : (w : K ⊗[F] V) ∈ (Q.baseChangeOfProjective K).radical := + ⟨hw, LinearMap.mem_ker.mp w.2⟩ + rw [hK, Submodule.mem_bot] at hmem + exact Subtype.ext hmem + +/-- **`GPR Exc. 11.37`, (iii) ⇒ (i).** A single algebraically closed base change suffices: if +`rad Q_K = 0` for one algebraically closed `K ⊇ F`, then `Q` is non-singular. -/ +theorem QuadraticForm.isGPRNonsingular_of_isAlgClosed {K : Type*} [Field K] [IsAlgClosed K] + [Algebra F K] (Q : QuadraticForm F V) (hK : (Q.baseChangeOfProjective K).radical = ⊥) : + Q.IsGPRNonsingular := + Q.isGPRNonsingular_of_radical_eq_bot_of_finrank_ker_le_one + (Q.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot hK) + (Q.finrank_ker_polarBilin_le_one_of_isAlgClosed hK) + +/-- **`EKM Lemma 7.16`, (1) ↔ (3); `GPR Exercise 11.37`, (i) ↔ (ii).** `Q` is non-singular +exactly when its radical vanishes and the radical of its polar form is at most a line. + +The right-hand side is mathlib's `QuadraticMap.Nondegenerate`, which is `EKM`'s condition (3) +taken as the definition. So this identifies our base-change-stable `IsGPRNonsingular` — and +therefore `QuadraticForm.IsEKMNondegenerate` — with mathlib's predicate. -/ +theorem QuadraticForm.isGPRNonsingular_iff_nondegenerate (Q : QuadraticForm F V) : + Q.IsGPRNonsingular.{u, v, u} ↔ QuadraticMap.Nondegenerate (Q := Q) := by + constructor + · intro h + have hK := h (AlgebraicClosure F) + refine ⟨Q.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot hK, ?_⟩ + rw [← Module.finrank_eq_rank, Nat.cast_le_one] + exact Q.finrank_ker_polarBilin_le_one_of_isAlgClosed hK + · rintro ⟨h1, h2⟩ + refine Q.isGPRNonsingular_of_radical_eq_bot_of_finrank_ker_le_one h1 ?_ + rwa [← Module.finrank_eq_rank, Nat.cast_le_one] at h2 + +/-- **`EKM Definition 7.17` is mathlib's `QuadraticMap.Nondegenerate`.** `EKM` defines +non-degeneracy by condition (1) of `Lemma 7.16` — the reading `QuadraticForm.IsEKMNondegenerate` +formalizes — while mathlib takes condition (3). `EKM 7.16` says they agree. -/ +theorem QuadraticForm.isEKMNondegenerate_iff_nondegenerate (Q : QuadraticForm F V) : + QuadraticForm.IsEKMNondegenerate.{u, v, u} Q ↔ QuadraticMap.Nondegenerate (Q := Q) := + Q.isGPRNonsingular_iff_nondegenerate + +/-- **`GPR Exercise 11.37`.** For a quadratic form over a field, on a finite-dimensional space, +the following are equivalent: + +(i) `Q` is non-singular; +(ii) `Q` is non-degenerate and the radical of its polar form has dimension at most `1`; +(iii) `Q_K` is non-degenerate for *some* algebraically closed `K ⊇ F`; +(iv) `Q_K` is non-degenerate for *every* algebraically closed `K ⊇ F`. + +Condition (ii) is `QuadraticMap.Nondegenerate`, so this is `EKM Lemma 7.16` with the extra +rung (iv). Condition (iii) is stated at the canonical choice `AlgebraicClosure F`; that this +really captures "some" is `QuadraticForm.isGPRNonsingular_of_isAlgClosed`, which accepts any +algebraically closed `K`. -/ +theorem QuadraticForm.isGPRNonsingular_tfae (Q : QuadraticForm F V) : + List.TFAE + [Q.IsGPRNonsingular.{u, v, u}, + Q.radical = ⊥ ∧ Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) ≤ 1, + (Q.baseChangeOfProjective (AlgebraicClosure F)).radical = ⊥, + ∀ (K : Type u) [Field K] [Algebra F K] [IsAlgClosed K], + (Q.baseChangeOfProjective K).radical = ⊥] := by + tfae_have 1 → 4 := fun h K _ _ _ ↦ h K + tfae_have 4 → 3 := fun h ↦ h (AlgebraicClosure F) + tfae_have 3 → 2 := fun h ↦ + ⟨Q.radical_eq_bot_of_radical_baseChangeOfProjective_eq_bot h, + Q.finrank_ker_polarBilin_le_one_of_isAlgClosed h⟩ + tfae_have 2 → 1 := fun h ↦ + Q.isGPRNonsingular_of_radical_eq_bot_of_finrank_ker_le_one h.1 h.2 + tfae_finish + +end TFAE + +/-! ## Part D: `GPR Exc. 11.37`, Remark (1) -/ + +section Remark + +variable {F : Type u} [Field F] {V : Type v} [AddCommGroup V] [Module F V] + [FiniteDimensional F V] + +/-- Over a finite-dimensional space regularity is exactly vanishing of the polar radical: +`polarBilin Q` is injective iff bijective, `V` and `Module.Dual F V` having equal dimension. -/ +theorem QuadraticForm.isGPRRegular_iff_ker_polarBilin_eq_bot (Q : QuadraticForm F V) : + Q.IsGPRRegular ↔ LinearMap.ker (QuadraticMap.polarBilin Q) = ⊥ := by + constructor + · exact fun h ↦ LinearMap.ker_eq_bot.mpr h.1 + · intro h + have hinj := LinearMap.ker_eq_bot.mp h + exact ⟨hinj, (LinearMap.injective_iff_surjective_of_finrank_eq_finrank + Subspace.dual_finrank_eq.symm).mp hinj⟩ + +/-- Regularity in terms of the dimension of the polar radical. -/ +theorem QuadraticForm.isGPRRegular_iff_finrank_ker_polarBilin_eq_zero (Q : QuadraticForm F V) : + Q.IsGPRRegular ↔ Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 0 := by + rw [QuadraticForm.isGPRRegular_iff_ker_polarBilin_eq_bot, ← Submodule.finrank_eq_zero] + +/-- **Remark (1), the dichotomy.** For a non-degenerate `Q` on a finite-dimensional space, the +polar radical is either `0` — the regular case, (b) — or a line, case (a). The two are mutually +exclusive, so *exactly* one holds. -/ +theorem QuadraticForm.isGPRRegular_xor_finrank_ker_polarBilin_eq_one (Q : QuadraticForm F V) + (hnd : QuadraticMap.Nondegenerate (Q := Q)) : + Xor Q.IsGPRRegular (Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1) := by + have hle : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) ≤ 1 := by + have := hnd.rank_rad_polar_le + rwa [← Module.finrank_eq_rank, Nat.cast_le_one] at this + rw [QuadraticForm.isGPRRegular_iff_finrank_ker_polarBilin_eq_zero] + rcases Nat.lt_or_ge (Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q))) 1 with h | h + · exact Or.inl ⟨Nat.lt_one_iff.mp h, by omega⟩ + · exact Or.inr ⟨le_antisymm hle h, by omega⟩ + +/-- **Remark (1), case (a) forces characteristic `2`.** If `2` is invertible then a non-degenerate +form is automatically regular, by `GN (C.8.2)`'s non-base-changed half +(`QuadraticForm.radical_eq_bot_iff_injective_polarBilin`): with `2` invertible the extra +`Q m = 0` clause in the radical is redundant, so `radical Q = ⊥` already says `polarBilin Q` is +injective. -/ +theorem QuadraticForm.isGPRRegular_of_radical_eq_bot_of_invertible_two [Invertible (2 : F)] + (Q : QuadraticForm F V) (hrad : Q.radical = ⊥) : Q.IsGPRRegular := by + rw [QuadraticForm.isGPRRegular_iff_ker_polarBilin_eq_bot, LinearMap.ker_eq_bot] + exact (QuadraticForm.radical_eq_bot_iff_injective_polarBilin Q).mp hrad + +/-- **Remark (1), case (a) forces characteristic `2`**, stated as `(2 : F) = 0`. -/ +theorem QuadraticForm.two_eq_zero_of_finrank_ker_polarBilin_eq_one (Q : QuadraticForm F V) + (hrad : Q.radical = ⊥) + (hdim : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1) : + (2 : F) = 0 := by + by_contra h2 + have : Invertible (2 : F) := invertibleOfNonzero h2 + have hreg := Q.isGPRRegular_of_radical_eq_bot_of_invertible_two hrad + rw [QuadraticForm.isGPRRegular_iff_finrank_ker_polarBilin_eq_zero, hdim] at hreg + exact one_ne_zero hreg + +/-- The same conclusion as `ringChar F = 2`, matching `GPR`'s phrasing "char `F` = 2". -/ +theorem QuadraticForm.ringChar_eq_two_of_finrank_ker_polarBilin_eq_one (Q : QuadraticForm F V) + (hrad : Q.radical = ⊥) + (hdim : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1) : + ringChar F = 2 := by + have h2 : ((2 : ℕ) : F) = 0 := by + push_cast + exact Q.two_eq_zero_of_finrank_ker_polarBilin_eq_one hrad hdim + rcases (Nat.prime_two.eq_one_or_self_of_dvd _ (ringChar.dvd h2)) with h | h + · exact absurd h (CharP.ringChar_ne_one) + · exact h + +/-- **Remark (1), case (a): the orthogonal decomposition `q = q₀ ⊥ ⟨α⟩`.** + +If the polar radical of a non-degenerate `Q` is the line `F u`, then `α := Q u ≠ 0` and `Q` splits +as `⟨α⟩ ⊥ Q|W` for *any* complement `W` of `F u`, with `Q|W` regular. + +No orthogonalisation is needed: `u` is in the radical of the polar form, so `polar Q u w = 0` +already holds for every `w`, making the decomposition orthogonal automatically. `Q|W` is regular +because a vector of `W` killed by `Q|W` is killed by all of `Q`'s polar form — it is orthogonal to +`u` for free — hence lies in `F u ⊓ W = 0`. -/ +theorem QuadraticForm.exists_isometryEquiv_rankOne_prod (Q : QuadraticForm F V) + (hrad : Q.radical = ⊥) + (hdim : Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1) : + ∃ (W : Submodule F V) (α : F), α ≠ 0 ∧ + QuadraticForm.IsGPRRegular (Q.comp W.subtype) ∧ + Nonempty (QuadraticMap.IsometryEquiv + (QuadraticMap.prod (QuadraticForm.rankOne α) (Q.comp W.subtype)) Q) := by + -- A generator `u` of the polar radical, and `α = Q u ≠ 0`. + obtain ⟨u, hu, hune⟩ : ∃ u ∈ LinearMap.ker (QuadraticMap.polarBilin Q), u ≠ 0 := by + by_contra hcon + simp only [not_exists, not_and, not_not] at hcon + rw [(LinearMap.ker (QuadraticMap.polarBilin Q)).eq_bot_iff.mpr hcon, finrank_bot] at hdim + exact zero_ne_one hdim + have hpolar : ∀ w, QuadraticMap.polar Q u w = 0 := fun w ↦ by + have h := DFunLike.congr_fun (LinearMap.mem_ker.mp hu) w + rwa [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] at h + have hQu : Q u ≠ 0 := fun h ↦ hune (by + have : u ∈ Q.radical := ⟨h, LinearMap.mem_ker.mp hu⟩ + rwa [hrad, Submodule.mem_bot] at this) + have hker : LinearMap.ker (QuadraticMap.polarBilin Q) = F ∙ u := by + refine (Submodule.eq_of_le_of_finrank_eq ?_ ?_).symm + · rw [Submodule.span_le, Set.singleton_subset_iff]; exact hu + · rw [finrank_span_singleton hune, hdim] + -- Any complement `W` of the line `F u` works. + obtain ⟨W, hW⟩ := (F ∙ u).exists_isCompl + have hinf : (F ∙ u) ⊓ W = ⊥ := hW.inf_eq_bot + refine ⟨W, Q u, hQu, ?_, ?_⟩ + · -- `Q|W` is regular. + rw [QuadraticForm.isGPRRegular_iff_ker_polarBilin_eq_bot, Submodule.eq_bot_iff] + intro w hw + have hwW : ∀ w' : W, QuadraticMap.polar Q w (w' : V) = 0 := fun w' ↦ by + have h := DFunLike.congr_fun (LinearMap.mem_ker.mp hw) w' + rwa [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] at h + have hall : (w : V) ∈ LinearMap.ker (QuadraticMap.polarBilin Q) := by + refine LinearMap.mem_ker.mpr (LinearMap.ext fun v ↦ ?_) + obtain ⟨x, hx, y, hy, rfl⟩ := + Submodule.mem_sup.mp (hW.sup_eq_top ▸ Submodule.mem_top : v ∈ _) + obtain ⟨a, rfl⟩ := Submodule.mem_span_singleton.mp hx + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_add_right, + QuadraticMap.polar_smul_right, QuadraticMap.polar_comm Q (w : V) u, hpolar, + smul_zero, zero_add, hwW ⟨y, hy⟩, LinearMap.zero_apply] + rw [hker] at hall + have hbot : (w : V) ∈ (F ∙ u) ⊓ W := Submodule.mem_inf.mpr ⟨hall, w.2⟩ + rw [hinf, Submodule.mem_bot] at hbot + exact Submodule.coe_eq_zero.mp hbot + · -- The isometry `⟨α⟩ ⊥ Q|W ≃ Q`, via `(a, w) ↦ a • u + w`. + set f : F × W →ₗ[F] V := (LinearMap.toSpanSingleton F V u).coprod W.subtype with hf + have hbij : Function.Bijective f := by + constructor + · rw [injective_iff_map_eq_zero] + rintro ⟨a, w⟩ hzero + have hmem : a • u ∈ (F ∙ u) ⊓ W := by + refine ⟨Submodule.mem_span_singleton.mpr ⟨a, rfl⟩, ?_⟩ + have : a • u = -(w : V) := by + rw [eq_neg_iff_add_eq_zero]; simpa [hf, LinearMap.toSpanSingleton_apply] using hzero + rw [this] + exact Submodule.neg_mem _ w.2 + rw [hinf, Submodule.mem_bot] at hmem + have hw : (w : V) = 0 := by + have := hzero + simp only [hf, LinearMap.coprod_apply, LinearMap.toSpanSingleton_apply, + Submodule.coe_subtype, hmem, zero_add] at this + exact this + exact Prod.ext ((smul_eq_zero.mp hmem).resolve_right hune) (Submodule.coe_eq_zero.mp hw) + · intro v + obtain ⟨x, hx, y, hy, rfl⟩ := + Submodule.mem_sup.mp (hW.sup_eq_top ▸ Submodule.mem_top : v ∈ _) + obtain ⟨a, rfl⟩ := Submodule.mem_span_singleton.mp hx + exact ⟨(a, ⟨y, hy⟩), by simp [hf, LinearMap.toSpanSingleton_apply]⟩ + refine ⟨⟨LinearEquiv.ofBijective f hbij, ?_⟩⟩ + rintro ⟨a, w⟩ + change Q (f (a, w)) = _ + rw [hf] + simp only [LinearMap.coprod_apply, LinearMap.toSpanSingleton_apply, Submodule.coe_subtype, + QuadraticMap.prod_apply, QuadraticForm.rankOne_apply, QuadraticMap.comp_apply] + rw [QuadraticMap.map_add (⇑Q) (a • u) (w : V), QuadraticMap.map_smul, + QuadraticMap.polar_smul_left, hpolar, smul_zero, add_zero, smul_eq_mul] + ring + +/-- **`GPR Exc. 11.37`, Remark (1)**, assembled — *except* for the parity clause "`dim V` is odd" in +case (a), which is not proved here (see the module docstring). + +For a non-degenerate `Q` on a finite-dimensional space over a field, exactly one of: + +(b) `Q` is regular; or +(a) the radical of the polar form is a line, `char F = 2`, and `Q ≅ ⟨α⟩ ⊥ Q₀` for some `α ≠ 0` + and some regular `Q₀` on a complement of that line. + +`GPR` states case (a) with "`dim V` is odd" in place of the clause "the polar radical is a line". +The two are equivalent given the parity theorem for alternating forms; the version here uses the +polar-radical clause, which is what actually drives the proof and what makes the dichotomy +exclusive. -/ +theorem QuadraticForm.isGPRRegular_xor_charTwo_rankOne_decomposition (Q : QuadraticForm F V) + (hnd : QuadraticMap.Nondegenerate (Q := Q)) : + Xor Q.IsGPRRegular + (Module.finrank F (LinearMap.ker (QuadraticMap.polarBilin Q)) = 1 ∧ ringChar F = 2 ∧ + ∃ (W : Submodule F V) (α : F), α ≠ 0 ∧ + QuadraticForm.IsGPRRegular (Q.comp W.subtype) ∧ + Nonempty (QuadraticMap.IsometryEquiv + (QuadraticMap.prod (QuadraticForm.rankOne α) (Q.comp W.subtype)) Q)) := by + rcases Q.isGPRRegular_xor_finrank_ker_polarBilin_eq_one hnd with + ⟨hreg, hne⟩ | ⟨hone, hnreg⟩ + · exact Or.inl ⟨hreg, fun h ↦ hne h.1⟩ + · refine Or.inr ⟨⟨hone, Q.ringChar_eq_two_of_finrank_ker_polarBilin_eq_one hnd.1 hone, + Q.exists_isometryEquiv_rankOne_prod hnd.1 hone⟩, hnreg⟩ + +end Remark diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/OrthogonalComplement.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/OrthogonalComplement.lean new file mode 100644 index 0000000000..c2fc18cdc2 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/OrthogonalComplement.lean @@ -0,0 +1,296 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import Mathlib.LinearAlgebra.BilinearForm.Orthogonal +public import Mathlib.LinearAlgebra.TensorProduct.Prod +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus + +/-! +# Splitting off a regular submodule + +Let `(M, q)` be a quadratic form over a commutative ring and `N ⊆ M` a submodule on which the +restriction of `q` is **regular** — its polar form is a bijection `N ≃ N*`. Then `N` splits off +orthogonally: + + `M = N ⊕ Nᗮ` and `q = q|_N ⊥ q|_{Nᗮ}`, + +where `Nᗮ` is the orthogonal complement of `N` for the polar form of `q` (mathlib's +`LinearMap.BilinForm.orthogonal`). + +## Why regularity, and not less + +Regularity is used twice and both times essentially. *Surjectivity* of `N → N*` produces the +projection: the functional `n ↦ q(x, n)` on `N` is realized by an actual element of `N`, and +subtracting it lands `x` in `Nᗮ`. *Injectivity* gives `N ∩ Nᗮ = 0`. Neither follows from +non-singularity of `q` on `M`, and over a field of characteristic 2 the difference is not cosmetic: +the polar form of a non-singular form of odd rank has a kernel, so its span is a submodule that +does not split off. + +Nothing here needs `M` to be projective, finitely generated, or `2` to be invertible; those enter +only in `QuadraticForm.IsGPRNonsingular.comp_polarOrthogonal_subtype`, where non-singularity of +the complement is deduced by base change. + +## Main definitions + +* `QuadraticForm.polarProj` : the projection `M →ₗ[R] N` attached to a regular restriction. +* `QuadraticForm.polarOrthogonal` : `Nᗮ`, a readable spelling of mathlib's + `LinearMap.BilinForm.orthogonal` applied to the polar form. +* `QuadraticForm.orthogonalDecomposition` : the linear equivalence `N × Nᗮ ≃ₗ[R] M` given by + addition. + +## Main results + +* `QuadraticForm.orthogonalDecompositionIsometryEquiv` : the orthogonal splitting packaged as an + isometry equivalence. + +* `QuadraticForm.comp_orthogonalDecomposition` : `q` pulls back to `q|_N ⊥ q|_{Nᗮ}`. +* `QuadraticForm.nontrivial_baseChange_polarOrthogonal` : the complement is nonzero over every + field where `N` is strictly smaller than `M`. This is how the full-support hypothesis of the + representation lemma is met in practice. +* `QuadraticForm.IsGPRNonsingular.comp_polarOrthogonal_subtype` : the complement of a regular + submodule in a non-singular form is non-singular. This is what feeds the representation lemma + (`GPR 11.26`). +* `QuadraticForm.eq_top_of_isGPRRegular_of_rankAtStalk_eq` : a regular submodule of full rank is + everything — the complement has rank zero, hence vanishes. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.11, 19.16. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, C.8. +-/ + +@[expose] public section + +universe u v t + +open QuadraticMap (polar) + +open scoped TensorProduct + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + {Q : QuadraticForm R M} {N : Submodule R M} + +variable (Q N) in +/-- `Nᗮ`, the orthogonal complement of `N` for the polar form of `Q`. + +This is mathlib's `LinearMap.BilinForm.orthogonal` applied to `QuadraticMap.polarBilin Q`; the +abbreviation exists only so that statements about it are readable, and is reducible, so mathlib's +`LinearMap.BilinForm.mem_orthogonal_iff` applies unchanged. -/ +abbrev polarOrthogonal : Submodule R M := + LinearMap.BilinForm.orthogonal (QuadraticMap.polarBilin Q) N + +theorem mem_polarOrthogonal_iff {m : M} : + m ∈ Q.polarOrthogonal N ↔ ∀ n ∈ N, polar Q n m = 0 := + Iff.rfl + +section Regular + +variable (hreg : QuadraticForm.IsGPRRegular (Q.comp N.subtype)) +include hreg + +/-- **The orthogonal projection onto a regular submodule.** + +`x` is sent to the unique element of `N` representing the functional `n ↦ q(x, n)` through the +polar form of `q|_N`. Uniqueness — hence linearity — is exactly regularity of the restriction. -/ +noncomputable def polarProj : M →ₗ[R] N := + (LinearEquiv.ofBijective + (QuadraticMap.polarBilin (Q.comp N.subtype)) hreg).symm.toLinearMap ∘ₗ + N.subtype.dualMap ∘ₗ Q.polarBilin + +/-- The defining property of the projection: it does not change the polar form against `N`. -/ +theorem polar_polarProj (x : M) (n : N) : + polar Q (polarProj hreg x : M) (n : M) = polar Q x (n : M) := by + have h : (QuadraticMap.polarBilin (Q.comp N.subtype)) (polarProj hreg x) = + N.subtype.dualMap (Q.polarBilin x) := + (LinearEquiv.ofBijective (QuadraticMap.polarBilin (Q.comp N.subtype)) hreg).apply_symm_apply _ + exact congrFun (congrArg DFunLike.coe h) n + +/-- Every `x` decomposes as its projection plus a vector orthogonal to `N`. -/ +theorem sub_polarProj_mem_polarOrthogonal (x : M) : + x - (polarProj hreg x : M) ∈ Q.polarOrthogonal N := by + refine (mem_polarOrthogonal_iff).mpr fun n hn ↦ ?_ + rw [QuadraticMap.polar_sub_right, QuadraticMap.polar_comm Q n x, + QuadraticMap.polar_comm Q n (polarProj hreg x : M), + polar_polarProj hreg x ⟨n, hn⟩, sub_self] + +/-- The projection is the identity on `N`, by injectivity of the restricted polar form. -/ +theorem polarProj_coe (a : N) : polarProj hreg (a : M) = a := by + refine hreg.1 (LinearMap.ext fun n ↦ ?_) + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polarBilin_apply_apply] + exact polar_polarProj hreg (a : M) n + +/-- The projection kills the orthogonal complement. -/ +theorem polarProj_eq_zero {b : M} (hb : b ∈ Q.polarOrthogonal N) : polarProj hreg b = 0 := by + refine hreg.1 (LinearMap.ext fun n ↦ ?_) + rw [QuadraticMap.polarBilin_apply_apply, map_zero, LinearMap.zero_apply] + change polar Q (polarProj hreg b : M) (n : M) = 0 + rw [polar_polarProj hreg b n, QuadraticMap.polar_comm] + exact (mem_polarOrthogonal_iff).mp hb n n.2 + +/-- **`M = N ⊕ Nᗮ`.** Addition is a linear equivalence `N × Nᗮ ≃ₗ[R] M` when the restriction of +`q` to `N` is regular. -/ +noncomputable def orthogonalDecomposition : (N × (Q.polarOrthogonal N)) ≃ₗ[R] M := + LinearEquiv.ofBijective (N.subtype.coprod (Q.polarOrthogonal N).subtype) <| by + constructor + · intro p q hpq + have h : (p.1 : M) + (p.2 : M) = (q.1 : M) + (q.2 : M) := hpq + have hz : (p.1 : M) - (q.1 : M) = (q.2 : M) - (p.2 : M) := by + linear_combination (norm := module) h + have hmem : (p.1 : M) - (q.1 : M) ∈ Q.polarOrthogonal N := by + rw [hz] + exact sub_mem (q.2).2 (p.2).2 + have h1 : p.1 = q.1 := by + have hp := polarProj_eq_zero hreg hmem + rwa [map_sub, polarProj_coe, polarProj_coe, sub_eq_zero] at hp + refine Prod.ext h1 (Subtype.ext ?_) + rw [h1] at h + exact add_left_cancel h + · intro x + refine ⟨(polarProj hreg x, + ⟨x - (polarProj hreg x : M), sub_polarProj_mem_polarOrthogonal hreg x⟩), ?_⟩ + change (polarProj hreg x : M) + (x - (polarProj hreg x : M)) = x + abel + +@[simp] theorem orthogonalDecomposition_apply (p : N × (Q.polarOrthogonal N)) : + orthogonalDecomposition hreg p = (p.1 : M) + (p.2 : M) := rfl + +/-- **The orthogonal splitting of the form**: `q = q|_N ⊥ q|_{Nᗮ}`. + +The cross term vanishes by the definition of `Nᗮ`, which is the whole point. -/ +theorem comp_orthogonalDecomposition : + Q.comp (orthogonalDecomposition hreg).toLinearMap = + QuadraticMap.prod (Q.comp N.subtype) (Q.comp (Q.polarOrthogonal N).subtype) := by + refine QuadraticMap.ext fun p ↦ ?_ + have hcross : polar Q (p.1 : M) (p.2 : M) = 0 := + (mem_polarOrthogonal_iff).mp (p.2).2 (p.1 : M) (p.1).2 + have hadd := QuadraticMap.map_add Q (p.1 : M) (p.2 : M) + rw [hcross, add_zero] at hadd + rw [QuadraticMap.comp_apply, LinearEquiv.coe_coe, orthogonalDecomposition_apply, hadd, + QuadraticMap.prod_apply, QuadraticMap.comp_apply, QuadraticMap.comp_apply, + Submodule.subtype_apply, Submodule.subtype_apply] + +/-- The orthogonal decomposition packaged as an isometry between the orthogonal sum of the two +restricted forms and the ambient form. -/ +noncomputable def orthogonalDecompositionIsometryEquiv : + ((Q.comp N.subtype).prod + (Q.comp (Q.polarOrthogonal N).subtype)).IsometryEquiv Q where + toLinearEquiv := orthogonalDecomposition hreg + map_app' p := by + have h := congrFun (congrArg DFunLike.coe (comp_orthogonalDecomposition hreg)) p + exact h + +/-- A regular submodule of a finitely generated module is finitely generated: it is a direct +summand, being the image of the projection. -/ +theorem finite_of_comp_isGPRRegular [Module.Finite R M] : Module.Finite R N := + Module.Finite.of_surjective (polarProj hreg) fun a ↦ ⟨(a : M), polarProj_coe hreg a⟩ + +/-- A regular submodule of a projective module is projective. -/ +theorem projective_of_comp_isGPRRegular [Module.Projective R M] : Module.Projective R N := + Module.Projective.of_split N.subtype (polarProj hreg) (LinearMap.ext (polarProj_coe hreg)) + +/-- The complement of a regular submodule is finitely generated when the ambient module is. -/ +theorem finite_polarOrthogonal [Module.Finite R M] : + Module.Finite R (Q.polarOrthogonal N) := by + have : Module.Finite R (N × (Q.polarOrthogonal N)) := + Module.Finite.equiv (orthogonalDecomposition hreg).symm + exact Module.Finite.of_surjective (LinearMap.snd R N (Q.polarOrthogonal N)) + fun b ↦ ⟨(0, b), rfl⟩ + +/-- The complement of a regular submodule is projective when the ambient module is. -/ +theorem projective_polarOrthogonal [Module.Projective R M] : + Module.Projective R (Q.polarOrthogonal N) := by + have : Module.Projective R (N × (Q.polarOrthogonal N)) := + Module.Projective.of_equiv (orthogonalDecomposition hreg).symm + exact Module.Projective.of_split (LinearMap.inr R N (Q.polarOrthogonal N)) + (LinearMap.snd R N (Q.polarOrthogonal N)) (LinearMap.ext fun _ ↦ rfl) + +end Regular + +/-- **The complement of a regular submodule in a non-singular form is non-singular.** + +Base change the orthogonal splitting `q ≅ q|_N ⊥ q|_{Nᗮ}` to a field and read off the right +summand (`GN (C.8.3)`, `QuadraticForm.IsGPRNonsingular.of_prod_right`). This is the hypothesis the +representation lemma `GPR 11.26` consumes. -/ +theorem IsGPRNonsingular.comp_polarOrthogonal_subtype [Module.Finite R M] [Module.Projective R M] + {Q : QuadraticForm R M} {N : Submodule R M} + (hreg : QuadraticForm.IsGPRRegular (Q.comp N.subtype)) + (hQ : QuadraticForm.IsGPRNonsingular.{u, v, t} Q) : + haveI := finite_polarOrthogonal hreg + haveI := projective_polarOrthogonal hreg + QuadraticForm.IsGPRNonsingular.{u, v, t} (Q.comp (Q.polarOrthogonal N).subtype) := by + have := finite_polarOrthogonal hreg + have := projective_polarOrthogonal hreg + have := finite_of_comp_isGPRRegular hreg + have := projective_of_comp_isGPRRegular hreg + have h := hQ.comp_linearEquiv (orthogonalDecomposition hreg) + rw [comp_orthogonalDecomposition hreg] at h + exact h.of_prod_right + +/-- **The complement is visible in the rank.** Over a field `F ∈ R`-alg in which `N` is strictly +smaller than `M`, the base change of the complement is nonzero. + +Base change is exact on the splitting `M = N ⊕ Nᗮ`, so the three ranks add up; a vanishing +complement would force the two ranks to agree. This is what supplies `Module.HasFullSupport` for +the representation lemma `GPR 11.26`. -/ +theorem nontrivial_baseChange_polarOrthogonal [Module.Finite R M] + {Q : QuadraticForm R M} {N : Submodule R M} + (hreg : QuadraticForm.IsGPRRegular (Q.comp N.subtype)) (F : Type t) [Field F] [Algebra R F] + (hlt : Module.finrank F (F ⊗[R] N) < Module.finrank F (F ⊗[R] M)) : + Nontrivial (F ⊗[R] (Q.polarOrthogonal N)) := by + have := finite_polarOrthogonal hreg + have := finite_of_comp_isGPRRegular hreg + rw [← not_subsingleton_iff_nontrivial] + intro hsub + have e : (F ⊗[R] M) ≃ₗ[F] (F ⊗[R] N) × (F ⊗[R] (Q.polarOrthogonal N)) := + ((orthogonalDecomposition hreg).baseChange R F _ M).symm.trans + (TensorProduct.prodRight R F F N (Q.polarOrthogonal N)) + have hrk : Module.finrank F (F ⊗[R] M) = + Module.finrank F (F ⊗[R] N) + Module.finrank F (F ⊗[R] (Q.polarOrthogonal N)) := by + rw [e.finrank_eq, Module.finrank_prod] + have hzero : Module.finrank F (F ⊗[R] (Q.polarOrthogonal N)) = 0 := + Module.finrank_eq_zero_of_subsingleton F (F ⊗[R] (Q.polarOrthogonal N)) + omega + +/-- **A regular submodule of full rank is everything.** If the restriction of `Q` to `N` is regular +and `N` has the same constant rank as `M` at every prime, the orthogonal complement has rank zero, +hence is trivial, hence `N = ⊤`. + +This is the criterion that turns a doubling that has run out of room into a surjection; the +subalgebra form of it is `ConicAlgebra.mem_of_isGPRRegular_of_rankAtStalk_eq`. -/ +theorem eq_top_of_isGPRRegular_of_rankAtStalk_eq [Module.Finite R M] [Module.Projective R M] + {Q : QuadraticForm R M} {N : Submodule R M} + (hreg : QuadraticForm.IsGPRRegular (Q.comp N.subtype)) {r : ℕ} + (hM : Module.rankAtStalk (R := R) M = fun _ ↦ r) + (hN : Module.rankAtStalk (R := R) N = fun _ ↦ r) : N = ⊤ := by + have := finite_of_comp_isGPRRegular hreg + have := projective_of_comp_isGPRRegular hreg + have := finite_polarOrthogonal hreg + have := projective_polarOrthogonal hreg + have hzero : Module.rankAtStalk (R := R) (Q.polarOrthogonal N) = 0 := by + have hsum := Module.rankAtStalk_eq_of_equiv (orthogonalDecomposition hreg) + rw [Module.rankAtStalk_prod, hM, hN] at hsum + funext p + have := congrFun hsum p + simp only [Pi.add_apply, Pi.zero_apply] at this ⊢ + omega + have : Subsingleton (Q.polarOrthogonal N) := + (Module.rankAtStalk_eq_zero_iff_subsingleton (R := R)).mp hzero + refine Submodule.eq_top_iff'.mpr fun x ↦ ?_ + have hx : x - (polarProj hreg x : M) = 0 := by + have := Subsingleton.elim + (⟨x - (polarProj hreg x : M), sub_polarProj_mem_polarOrthogonal hreg x⟩ : + Q.polarOrthogonal N) 0 + exact congrArg Subtype.val this + have hxe : x = ((polarProj hreg x : N) : M) := by rw [← sub_eq_zero]; exact hx + rw [hxe] + exact (polarProj hreg x).2 + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneCancellation.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneCancellation.lean new file mode 100644 index 0000000000..000848585c --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneCancellation.lean @@ -0,0 +1,159 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.HyperbolicPair +public import TauCeti.LinearAlgebra.QuadraticForm.Isometry + +/-! +# Cancelling a hyperbolic plane + +The step of Witt cancellation that turns a statement about *isometries of a hyperbolic pair* into +a statement about *cancellation*: if every hyperbolic pair of `H ⊥ q₂` is the image of the standard +one under a self-isometry, then `H ⊥ q₁ ≅ H ⊥ q₂` implies `q₁ ≅ q₂`. + +This is the second half of `Dias II.6.4` (`Baeza III (4.3)`), specialized to a hyperbolic plane and +written with mathlib's `QuadraticMap.prod` in place of an internal orthogonal decomposition. The +transitivity hypothesis it consumes is `Dias II.6.2`, whose general case is what needs the LG axiom; +its unit case is `QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit`. + +## Main results + +* `QuadraticForm.isHyperbolicPair_plane_prod` : `((1,0), 0)` and `((0,1), 0)` form the standard + hyperbolic pair of `plane ⊥ q`. +* `QuadraticForm.isometryEquivOfFixesPlane` : an isometry `plane ⊥ q₁ ≅ plane ⊥ q₂` fixing both + members of the standard hyperbolic pair restricts to an isometry `q₁ ≅ q₂`. The mechanism is + that a vector is in the second summand *exactly* when it is orthogonal to the pair, which is a + two-line computation for the plane and needs no regularity of `q₁` or `q₂`. +* `QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod` : cancellation of a plane, given + transitivity on hyperbolic pairs. + +## References + +* I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de Campinas, + 1988, II.6.2 and II.6.4. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Math. **655**, Springer 1978, + III, (4.2) and (4.3). +-/ + +@[expose] public section + +universe u v w + +namespace QuadraticForm + +open _root_.QuadraticMap (polar polar_prod polar_zero_left polar_zero_right + IsHyperbolicPair) + +variable {R : Type u} [CommRing R] {M₁ : Type v} [AddCommGroup M₁] [Module R M₁] +variable {M₂ : Type w} [AddCommGroup M₂] [Module R M₂] + +/-- The standard hyperbolic pair of `plane ⊥ q`. -/ +theorem isHyperbolicPair_plane_prod (Q : QuadraticForm R M₁) : + IsHyperbolicPair ((plane R).prod Q) ((1, 0), 0) ((0, 1), 0) where + apply_left := by simp + apply_right := by simp + polar_eq_one := by + rw [polar_prod, polar_plane] + simp + +/-- A vector of `plane ⊥ q` orthogonal to both members of the standard hyperbolic pair lies in the +second summand. This is the whole content of "the orthogonal complement of the plane is `q`", and +it needs nothing of `q`. -/ +theorem fst_eq_zero_of_polar_eq_zero {Q : QuadraticForm R M₁} {x : (R × R) × M₁} + (h₁ : polar ((plane R).prod Q) x ((1, 0), 0) = 0) + (h₂ : polar ((plane R).prod Q) x ((0, 1), 0) = 0) : x.1 = 0 := by + rw [polar_prod, polar_plane, polar_zero_right] at h₁ h₂ + simp only [mul_zero, mul_one, zero_add, add_zero] at h₁ h₂ + exact Prod.ext h₂ h₁ + +section FixesPlane + +variable {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} +variable (τ : ((plane R).prod Q₁).IsometryEquiv ((plane R).prod Q₂)) +variable (hu : τ ((1, 0), 0) = ((1, 0), 0)) (hv : τ ((0, 1), 0) = ((0, 1), 0)) + +include hu hv in +/-- An isometry fixing the standard hyperbolic pair maps the second summand into the second +summand. -/ +theorem fst_map_inr_eq_zero (m : M₁) : (τ (0, m)).1 = 0 := by + refine fst_eq_zero_of_polar_eq_zero (Q := Q₂) ?_ ?_ + · rw [← hu, τ.polar_apply, polar_prod, polar_zero_left, polar_zero_right, add_zero] + · rw [← hv, τ.polar_apply, polar_prod, polar_zero_left, polar_zero_right, add_zero] + +/-- The restriction of `τ` to the second summand, as a linear map. -/ +def restrictPlane : M₁ →ₗ[R] M₂ := + (LinearMap.snd R (R × R) M₂).comp ((τ : _ ≃ₗ[R] _).toLinearMap.comp (LinearMap.inr R (R × R) M₁)) + +@[simp] theorem restrictPlane_apply (m : M₁) : restrictPlane τ m = (τ (0, m)).2 := rfl + +include hu hv in +theorem map_inr (m : M₁) : τ (0, m) = (0, restrictPlane τ m) := + Prod.ext (fst_map_inr_eq_zero τ hu hv m) rfl + +include hu hv in +theorem apply_restrictPlane (m : M₁) : Q₂ (restrictPlane τ m) = Q₁ m := by + have h := τ.map_app ((0, m) : (R × R) × M₁) + rw [map_inr τ hu hv] at h + simpa using h + +include hu in +theorem symm_fixes_left : τ.symm ((1, 0), 0) = ((1, 0), 0) := by rw [← hu, τ.symm_apply_apply] + +include hv in +theorem symm_fixes_right : τ.symm ((0, 1), 0) = ((0, 1), 0) := by rw [← hv, τ.symm_apply_apply] + +include hu hv in +theorem restrictPlane_symm_restrictPlane (m : M₁) : + restrictPlane τ.symm (restrictPlane τ m) = m := by + have h2 := congrArg τ.symm (map_inr τ hu hv m) + rw [τ.symm_apply_apply, + map_inr τ.symm (symm_fixes_left τ hu) (symm_fixes_right τ hv)] at h2 + exact congrArg Prod.snd h2.symm + +include hu hv in +theorem restrictPlane_restrictPlane_symm (n : M₂) : + restrictPlane τ (restrictPlane τ.symm n) = n := by + have h2 := congrArg τ + (map_inr τ.symm (symm_fixes_left τ hu) (symm_fixes_right τ hv) n) + rw [τ.apply_symm_apply, map_inr τ hu hv] at h2 + exact congrArg Prod.snd h2.symm + +include hu hv in +/-- **An isometry `plane ⊥ q₁ ≅ plane ⊥ q₂` fixing the standard hyperbolic pair cancels the +plane.** -/ +noncomputable def isometryEquivOfFixesPlane : Q₁.IsometryEquiv Q₂ where + __ := LinearEquiv.ofBijective (restrictPlane τ) + (Function.bijective_iff_has_inverse.2 + ⟨restrictPlane τ.symm, restrictPlane_symm_restrictPlane τ hu hv, + restrictPlane_restrictPlane_symm τ hu hv⟩) + map_app' := apply_restrictPlane τ hu hv + +end FixesPlane + +/-- **Cancellation of a hyperbolic plane**, given transitivity on hyperbolic pairs. + +The hypothesis is `Dias II.6.2` for `plane ⊥ q₂`: every hyperbolic pair is the image of the +standard one under a self-isometry. Given it, `plane ⊥ q₁ ≅ plane ⊥ q₂` implies `q₁ ≅ q₂`, by +correcting the given isometry so that it fixes the standard pair and then restricting +(`QuadraticForm.isometryEquivOfFixesPlane`). -/ +theorem isometryEquiv_of_isometryEquiv_plane_prod {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} + (htrans : ∀ i j : (R × R) × M₂, IsHyperbolicPair ((plane R).prod Q₂) i j → + ∃ σ : ((plane R).prod Q₂).IsometryEquiv ((plane R).prod Q₂), + σ ((1, 0), 0) = i ∧ σ ((0, 1), 0) = j) + (h : Nonempty (((plane R).prod Q₁).IsometryEquiv ((plane R).prod Q₂))) : + Nonempty (Q₁.IsometryEquiv Q₂) := by + obtain ⟨e⟩ := h + obtain ⟨σ, hσu, hσv⟩ := + htrans (e ((1, 0), 0)) (e ((0, 1), 0)) ((isHyperbolicPair_plane_prod Q₁).map e) + refine ⟨isometryEquivOfFixesPlane (e.trans σ.symm) ?_ ?_⟩ + · change σ.symm (e ((1, 0), 0)) = _ + rw [← hσu, σ.symm_apply_apply] + · change σ.symm (e ((0, 1), 0)) = _ + rw [← hσv, σ.symm_apply_apply] + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneSplitting.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneSplitting.lean new file mode 100644 index 0000000000..f134a3e419 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneSplitting.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Hyperbolic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.HyperbolicPair +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.OrthogonalComplement + +/-! +# A hyperbolic pair splits off a hyperbolic plane + +If `(u, v)` is a hyperbolic pair of `(M, q)` — `q u = q v = 0` and `q(u, v) = 1` — then the +submodule `R u ⊕ R v` they span is free of rank two, the restriction of `q` to it is the +hyperbolic plane `(a, b) ↦ ab`, and that restriction is **regular**. So the plane splits off +orthogonally: + + `q ≅ ⟨plane⟩ ⊥ q|_{(Ru ⊕ Rv)ᗮ}`. + +Nothing here needs `M` finitely generated or projective, `q` regular, or `2` invertible. The +regularity that the orthogonal splitting of `QuadraticForm/OrthogonalComplement.lean` consumes is +regularity of the *restricted* form, and that is supplied by the pair itself: the plane is +hyperbolic, and hyperbolic forms on finitely generated projective — here free of rank two — +modules are regular. + +This is the missing half of `GPR 11.17`: `QuadraticForm/Isotropic.lean` turns an isotropic vector +into a hyperbolic pair (`isGPRIsotropic_iff_exists_isHyperbolicPair`), and this file turns the pair +into a splitting. + +## Main definitions + +* `QuadraticMap.IsHyperbolicPair.planeEmbedding` : the map `(a, b) ↦ a u + b v`. +* `QuadraticMap.IsHyperbolicPair.planeSubmodule` : its range, `R u ⊕ R v`. + +## Main results + +* `QuadraticMap.IsHyperbolicPair.isGPRRegular_comp_planeSubmodule_subtype` : the restriction of + `q` to `R u ⊕ R v` is regular. +* `QuadraticMap.IsHyperbolicPair.isometryEquivPlaneProd` : **`q ≅ plane ⊥ q|_{(Ru ⊕ Rv)ᗮ}`**. +* `QuadraticForm.isGPRRegular_plane` : the hyperbolic plane is regular over any commutative ring. + +## Implementation notes + +The embedding is injective because the pair recovers coordinates: `q(a u + b v, v) = a` and +`q(a u + b v, u) = b`, using `q(u, u) = 2 q u = 0` and `q(v, v) = 0`. This is why no hypothesis on +`M` is needed — the splitting is entirely local to the plane. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.11, 11.17. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Math. **655**, Springer 1978, + I, (3.3). +-/ + +@[expose] public section + +universe u v + +open QuadraticMap (polar) + +namespace QuadraticForm + +variable (R : Type u) [CommRing R] + +/-- **The hyperbolic plane is regular** over any commutative ring: `(a, b) ↦ ab` is the pairing of +`R` against `R`, so `QuadraticForm.isGPRRegular_of_basis_pairing` applies to the one-element basis +of `R`. No hypothesis on `2`. -/ +theorem isGPRRegular_plane : QuadraticForm.IsGPRRegular (plane R) := + isGPRRegular_of_basis_pairing (Module.Basis.singleton Unit R) fun x ↦ by simp + +/-- The hyperbolic plane is non-singular. -/ +theorem isGPRNonsingular_plane : QuadraticForm.IsGPRNonsingular.{u, u, v} (plane R) := + isGPRNonsingular_of_basis_pairing (Module.Basis.singleton Unit R) fun x ↦ by simp + +end QuadraticForm + +namespace QuadraticMap.IsHyperbolicPair + +open QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + {Q : QuadraticForm R M} {u v : M} + +variable (u v) in +/-- The map `R × R → M`, `(a, b) ↦ a u + b v`, whose image is the plane spanned by a hyperbolic +pair. Defined for any two vectors; it is the hypothesis `IsHyperbolicPair` that makes it injective +and an isometry from `QuadraticForm.plane`. -/ +def planeEmbedding : (R × R) →ₗ[R] M := + (LinearMap.toSpanSingleton R M u).comp (LinearMap.fst R R R) + + (LinearMap.toSpanSingleton R M v).comp (LinearMap.snd R R R) + +@[simp] theorem planeEmbedding_apply (x : R × R) : + planeEmbedding u v x = x.1 • u + x.2 • v := rfl + +variable (h : Q.IsHyperbolicPair u v) +include h + +/-- The embedding carries the hyperbolic plane to `Q`. -/ +theorem apply_planeEmbedding (x : R × R) : + Q (planeEmbedding u v x) = QuadraticForm.plane R x := by + have hadd := QuadraticMap.map_add Q (x.1 • u) (x.2 • v) + rw [QuadraticMap.map_smul, QuadraticMap.map_smul, QuadraticMap.polar_smul_left, + QuadraticMap.polar_smul_right, h.apply_left, h.apply_right, h.polar_eq_one] at hadd + rw [planeEmbedding_apply, hadd, QuadraticForm.plane_apply] + ring + +/-- Pairing `a u + b v` with `v` recovers `a`. -/ +theorem polar_planeEmbedding_right (x : R × R) : polar Q (planeEmbedding u v x) v = x.1 := by + rw [planeEmbedding_apply, QuadraticMap.polar_add_left, QuadraticMap.polar_smul_left, + QuadraticMap.polar_smul_left, h.polar_eq_one, h.polar_self_right] + ring + +/-- Pairing `a u + b v` with `u` recovers `b`. -/ +theorem polar_planeEmbedding_left (x : R × R) : polar Q (planeEmbedding u v x) u = x.2 := by + rw [planeEmbedding_apply, QuadraticMap.polar_add_left, QuadraticMap.polar_smul_left, + QuadraticMap.polar_smul_left, h.polar_self_left, QuadraticMap.polar_comm _ v u, + h.polar_eq_one] + ring + +theorem injective_planeEmbedding : Function.Injective (planeEmbedding (R := R) u v) := by + intro x y hxy + refine Prod.ext ?_ ?_ + · rw [← h.polar_planeEmbedding_right x, ← h.polar_planeEmbedding_right y, hxy] + · rw [← h.polar_planeEmbedding_left x, ← h.polar_planeEmbedding_left y, hxy] + +variable (u v) in +/-- The submodule `R u ⊕ R v` spanned by a hyperbolic pair, presented as the range of +`QuadraticMap.IsHyperbolicPair.planeEmbedding`. -/ +def planeSubmodule : Submodule R M := LinearMap.range (planeEmbedding (R := R) u v) + +/-- The plane of a hyperbolic pair, as a module, is `R × R`. -/ +noncomputable def planeEquiv : (R × R) ≃ₗ[R] planeSubmodule (R := R) u v := + LinearEquiv.ofInjective _ h.injective_planeEmbedding + +@[simp] theorem planeEquiv_coe (x : R × R) : + ((h.planeEquiv x : planeSubmodule (R := R) u v) : M) = x.1 • u + x.2 • v := rfl + +/-- The restriction of `Q` to the plane of a hyperbolic pair *is* the hyperbolic plane, read +through `QuadraticMap.IsHyperbolicPair.planeEquiv`. -/ +theorem comp_planeEquiv : + (Q.comp (planeSubmodule (R := R) u v).subtype).comp h.planeEquiv.toLinearMap = + QuadraticForm.plane R := by + refine QuadraticMap.ext fun x ↦ ?_ + rw [QuadraticMap.comp_apply, QuadraticMap.comp_apply, LinearEquiv.coe_coe, + Submodule.subtype_apply, planeEquiv_coe] + exact h.apply_planeEmbedding x + +/-- The hyperbolic plane, as a quadratic module, *is* the plane of the pair inside `(M, Q)`. -/ +noncomputable def planeIsometryEquiv : + (QuadraticForm.plane R).IsometryEquiv (Q.comp (planeSubmodule (R := R) u v).subtype) where + toLinearEquiv := h.planeEquiv + map_app' x := h.apply_planeEmbedding x + +/-- **The restriction of `Q` to the plane of a hyperbolic pair is regular.** This is what lets the +plane split off orthogonally, and it holds over any commutative ring with no hypothesis on `2`. -/ +theorem isGPRRegular_comp_planeSubmodule_subtype : + QuadraticForm.IsGPRRegular (Q.comp (planeSubmodule (R := R) u v).subtype) := by + rw [← QuadraticForm.isGPRRegular_comp_linearEquiv_iff h.planeEquiv, h.comp_planeEquiv] + exact QuadraticForm.isGPRRegular_plane R + +/-- **A hyperbolic pair splits off a hyperbolic plane**: `Q ≅ plane ⊥ Q|_{(Ru ⊕ Rv)ᗮ}`. + +The orthogonal complement is taken for the polar form of `Q` +(`QuadraticForm.polarOrthogonal`). -/ +noncomputable def isometryEquivPlaneProd : + ((QuadraticForm.plane R).prod + (Q.comp (Q.polarOrthogonal (planeSubmodule (R := R) u v)).subtype)).IsometryEquiv Q := + (QuadraticMap.IsometryEquiv.prod h.planeIsometryEquiv + (QuadraticMap.IsometryEquiv.refl _)).trans + (QuadraticForm.orthogonalDecompositionIsometryEquiv + h.isGPRRegular_comp_planeSubmodule_subtype) + +end QuadraticMap.IsHyperbolicPair diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneTransitivity.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneTransitivity.lean new file mode 100644 index 0000000000..7a12afede0 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/PlaneTransitivity.lean @@ -0,0 +1,524 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.Module.RankDecomposition +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Isotropic +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneCancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Representation + +/-! +# `Dias II.6.1`–`II.6.2`: transitivity on hyperbolic pairs + +Not the Witt *extension* theorem — nothing here extends an isometry between submodules to the whole +module. What is proved is the single statement Witt cancellation needs: **the isometry group of +`plane ⊥ q` acts transitively on hyperbolic pairs**. `Dias II.6.1` is the step of it that uses the +LG axiom, and the only one in the whole chain that does. + +Work in `plane ⊥ q₀` on `(R × R) × M₀`, with standard hyperbolic pair `u = ((1,0), 0)`, +`v = ((0,1), 0)`. A vector is `i = ((α, β), m)`, and applying the Siegel–Eichler transvection +`E(u, (0, y))` to it gives + + `E(u, (0, y)) i = ((α - b(y, m) - β * q₀ y, β), m + β • y)`, + +so the `u`-coefficient changes from `α` to `α - b(y, m) - β·q₀(y)`. `Dias II.6.1` says that over an +LG ring one can choose `y` making that a **unit**, after which +`QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit` finishes the job. + +## The residue-field core + +Over a field, with `q₀` non-singular, `α β + q₀ m = 0` (isotropy of `i`) and `α ≠ 0`, `β ≠ 0` or +`q₀(m, ·) ≠ 0` (a consequence of unimodularity of `i`), the value `α - b(y, m) - β q₀ y` is +nonzero for a suitable `y`: + +* `α ≠ 0` — take `y = 0`; +* `α = 0` and `m ≠ 0` — then `q₀ m = 0`, so `m` is a nonzero isotropic vector and extends to a + hyperbolic pair `(m, y)` (`exists_isHyperbolicPair_of_radical_eq_bot`); the value is `-1`; +* `α = 0` and `m = 0` — then `β ≠ 0` (the third disjunct is vacuous when `m = 0`), and any `y` + with `q₀ y ≠ 0` + (`QuadraticForm.exists_apply_ne_zero_of_radical_eq_bot`) gives the value `-β q₀ y`. + +The last case needs `M₀ ⊗ κ(𝔪) ≠ 0` — Baeza's rank hypothesis in `Baeza III (2.3)`, Dias's +`V₀ ≠ 0`. Both sources assume it globally. Here it is needed only at those maximal ideals where +`α` is not *already* a unit, since where it is, `y = 0` works and the residue-field core is never +called. That is what lets the hypothesis be dispensed with entirely. + +## The locus where `M₀` vanishes + +Where `M₀ ⊗ κ(𝔪) = 0` the form `plane ⊥ q₀` reduces to the plane at `𝔪`, and there the hyperbolic +pair `(u, v)` and the pair `(β • v, β⁻¹ • u)` are exchanged by the **switch**, which is not a +product of transvections and dilations — it has the opposite Dickson invariant. No amount of +Eichler theory reaches it. + +The locus is clopen: it is cut out by `Module.rankIdempotent R M₀ 0` +(`Module/RankDecomposition.lean`), which annihilates `M₀` and reduces to `1` on the locus. Rather +than splitting `R` into a product of rings, `QuadraticForm.switchIdem` performs the switch on the +locus and the identity off it — one isometry, defined over `R`. Applying it first makes the +`u`-coefficient a unit at exactly the maximal ideals where `M₀` dies, so `Dias II.6.1` can be run +with no hypothesis on the support of `M₀` at all. + +## Main results + +* `QuadraticForm.exists_ne_zero_sub_polar_sub_smul` : the residue-field core, above. +* `QuadraticForm.exists_isUnit_sub_polar_sub_smul` : **`Dias II.6.1`**, the LG step. +* `QuadraticForm.switchIdem` : the partial switch. +* `QuadraticForm.exists_isometryEquiv_of_isHyperbolicPair` : **`Dias II.6.2`** — the isometry group + of `plane ⊥ q` is transitive on hyperbolic pairs. +* `QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing` : cancellation of one + hyperbolic plane. `QuadraticForm/WittCancellation.lean` passes from this to `GN 6.5`. + +## References + +* I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de Campinas, + 1988, II.6.1, II.6.2. +* R. Baeza, *Quadratic Forms over Semilocal Rings*, Lecture Notes in Math. **655**, Springer 1978, + III, (2.3). +-/ + +@[expose] public section + +universe u v v₁ + +namespace QuadraticForm + +open _root_.QuadraticMap (polar polar_comm polar_zero_left polar_zero_right polar_comp_apply + IsHyperbolicPair) + +/-- **The residue-field core of `Dias II.6.1`.** Let `q` be a quadratic form with vanishing radical +on a nonzero vector space over a field, let `a * b + q w = 0`, and suppose one of `a`, `b`, +`q(w, ·)` is nonzero. Then some `y` makes `a - q(y, w) - b * q y` nonzero. + +This is the value taken by the `u`-coefficient of `E(u, (0, y)) i` for `i = ((a, b), w)`; the three +cases are those listed in the module docstring. Non-singularity of `q` enters twice: to extend an +isotropic vector to a hyperbolic pair, and to guarantee that `q` is not identically zero. -/ +theorem exists_ne_zero_sub_polar_sub_smul {F : Type u} [Field F] {W : Type v} [AddCommGroup W] + [Module F W] [Nontrivial W] {q : QuadraticForm F W} (hq : q.radical = ⊥) {a b : F} {w : W} + (hiso : a * b + q w = 0) (hnz : a ≠ 0 ∨ b ≠ 0 ∨ ∃ z : W, polar q w z ≠ 0) : + ∃ y : W, a - polar q y w - b * q y ≠ 0 := by + by_cases ha : a ≠ 0 + · exact ⟨0, by simpa using ha⟩ + push Not at ha + subst ha + have hqw : q w = 0 := by linear_combination hiso + by_cases hw : w = 0 + · subst hw + have hb : b ≠ 0 := by + rcases hnz with h | h | ⟨z, hz⟩ + · exact absurd rfl h + · exact h + · exact absurd (QuadraticMap.polar_zero_left q z) hz + obtain ⟨y, hy⟩ := q.exists_apply_ne_zero_of_radical_eq_bot hq + refine ⟨y, ?_⟩ + simpa using mul_ne_zero hb hy + · obtain ⟨y, hy⟩ := exists_isHyperbolicPair_of_radical_eq_bot hq hw hqw + refine ⟨y, ?_⟩ + rw [polar_comm, hy.polar_eq_one, hy.apply_right] + simp + +/-! ### The polynomial of `Dias II.6.1` + +The function `y ↦ α - b(y, m) - β * q y` is an inhomogeneous quadratic polynomial function. On a +free module it is computed by an explicit `MvPolynomial`, in the same way `GPR 11.8` +(`QuadraticForm.toMvPolynomial`) computes `q` itself: a constant term, a linear term from the polar +form, and `-β` times the polynomial of `q`. -/ + +section Polynomial + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] +variable [Module.Finite R M] [Module.Projective R M] {n : ℕ} + +/-- The polar form evaluated on a finite linear combination. -/ +theorem polar_sum_smul_left {S : Type*} [CommRing S] {P : Type*} [AddCommGroup P] [Module S P] + {ι : Type*} [Fintype ι] (Q : QuadraticForm S P) (f : ι → S) (g : ι → P) (w : P) : + polar Q (∑ i, f i • g i) w = ∑ i, f i * polar Q (g i) w := by + simp only [← QuadraticMap.polarBilin_apply_apply] + rw [map_sum] + simp [LinearMap.sum_apply, smul_eq_mul] + +variable (α β : R) (q : QuadraticForm R M) (m : M) (bm : Module.Basis (Fin n) R M) + +/-- The polynomial computing `y ↦ α - b(y, m) - β * q y` in the basis `bm`. -/ +noncomputable def eichlerMvPolynomial : MvPolynomial (Fin n) R := + MvPolynomial.C α - (∑ i, MvPolynomial.C (polar q (bm i) m) * MvPolynomial.X i) - + MvPolynomial.C β * QuadraticForm.toMvPolynomial q bm + +variable {α β q m bm} + +/-- The defining property of `eichlerMvPolynomial`, over `R` itself. -/ +theorem aeval_eichlerMvPolynomial_self (t : Fin n → R) : + MvPolynomial.aeval t (eichlerMvPolynomial α β q m bm) = + α - polar q (∑ i, t i • bm i) m - β * q (∑ i, t i • bm i) := by + rw [eichlerMvPolynomial, map_sub, map_sub, map_mul, map_sum, + QuadraticForm.aeval_toMvPolynomial_self, polar_sum_smul_left] + simp only [MvPolynomial.aeval_C, MvPolynomial.aeval_X, map_mul, Algebra.algebraMap_self_apply] + rw [Finset.sum_congr rfl fun i (_ : i ∈ Finset.univ) ↦ mul_comm (polar q (bm i) m) (t i)] + +/-- The polar form of a base-changed form on a pair of pure tensors. -/ +theorem polar_baseChangeOfProjective_tmul (S : Type*) [CommRing S] [Algebra R S] + (Q : QuadraticForm R M) (x y : M) : + polar (Q.baseChangeOfProjective S) ((1 : S) ⊗ₜ[R] x) ((1 : S) ⊗ₜ[R] y) = + algebraMap R S (polar Q x y) := by + have h := QuadraticForm.polarBilin_baseChangeOfProjective (A := S) Q + have h2 := DFunLike.congr_fun (DFunLike.congr_fun h ((1 : S) ⊗ₜ[R] x)) ((1 : S) ⊗ₜ[R] y) + simpa [Algebra.smul_def] using h2 + +/-- The defining property of `eichlerMvPolynomial` after base change: `GPR 11.8` for the +inhomogeneous polynomial. -/ +theorem aeval_eichlerMvPolynomial (S : Type*) [CommRing S] [Algebra R S] (s : Fin n → S) : + MvPolynomial.aeval s (eichlerMvPolynomial α β q m bm) = + algebraMap R S α - + polar (q.baseChangeOfProjective S) (∑ i, s i • ((1 : S) ⊗ₜ[R] bm i)) + ((1 : S) ⊗ₜ[R] m) - + algebraMap R S β * + (q.baseChangeOfProjective S) (∑ i, s i • ((1 : S) ⊗ₜ[R] bm i)) := by + rw [eichlerMvPolynomial, map_sub, map_sub, map_mul, map_sum, + QuadraticForm.aeval_toMvPolynomial, polar_sum_smul_left] + simp only [MvPolynomial.aeval_C, MvPolynomial.aeval_X, map_mul, + polar_baseChangeOfProjective_tmul S q _ m] + rw [Finset.sum_congr rfl fun i (_ : i ∈ Finset.univ) ↦ + mul_comm (algebraMap R S (polar q (bm i) m)) (s i)] + +end Polynomial + + +/-! ### `Dias II.6.1` over an LG ring -/ + +section LG + +open scoped TensorProduct + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-- **`Dias II.6.1`.** Over an LG ring, for `q` non-singular on a finitely generated projective +module, and `α β m` with `α β + q m = 0` whose reductions never vanish simultaneously, some `y` +makes `α - q(y, m) - β * q y` a **unit**. + +Applied to `i = ((α, β), m)` in `plane ⊥ q`, this says the Siegel–Eichler transvection `E(u, (0,y))` +can be chosen to make the `u`-coefficient of `i` a unit — the hypothesis of +`QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit`. + +The LG axiom is applied to `QuadraticForm.eichlerMvPolynomial` written in the standard basis of a +presentation `Rⁿ ↠ M`; as in `QuadraticForm/Representation.lean`, pulling back along the +presentation is what removes any need for `M` to be free. + +`hM` is what replaces Baeza's rank hypothesis and Dias's `V₀ ≠ 0`: `M` need only be nonzero at +those residue fields where `α` itself is not already a unit. Where it is, `y = 0` works and the +residue-field core is not called at all. Full support (`Module.HasFullSupport`) implies `hM`, but +is strictly stronger — it fails for `M = 0`, which the cancellation theorem has to cover. -/ +theorem exists_isUnit_sub_polar_sub_smul (hLG : IsLGRing R) [Module.Finite R M] + [Module.Projective R M] {q : QuadraticForm R M} (hq : q.IsGPRNonsingular.{u, v, u}) + {α β : R} {m : M} (hiso : α * β + q m = 0) + (hnz : ∀ 𝔪 : Ideal R, + 𝔪.IsMaximal → α ∉ 𝔪 ∨ β ∉ 𝔪 ∨ ∃ n : M, polar q m n ∉ 𝔪) + (hM : ∀ 𝔪 : Ideal R, + 𝔪.IsMaximal → α ∉ 𝔪 ∨ Nontrivial ((R ⧸ 𝔪) ⊗[R] M)) : + ∃ y : M, IsUnit (α - polar q y m - β * q y) := by + obtain ⟨n, π, hπ⟩ := Module.Finite.exists_fin' R M + obtain ⟨m', rfl⟩ := hπ m + set bm : Module.Basis (Fin n) R (Fin n → R) := Pi.basisFun R (Fin n) with hbm + set q' : QuadraticForm R (Fin n → R) := q.comp π with hq' + have hrep : (eichlerMvPolynomial α β q' m' bm).RepresentsUnit R := by + refine (hLG n _).mpr fun 𝔪 _ ↦ ?_ + let : Field (R ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + -- where `α` is already a unit, `y = 0` does the job and `M` is not needed at all + rcases hM 𝔪 ‹_› with hα | hnt + · refine ⟨0, ?_⟩ + rw [QuadraticForm.aeval_eichlerMvPolynomial] + simp only [Pi.zero_apply, zero_smul, Finset.sum_const_zero, polar_zero_left, map_zero, + mul_zero, sub_zero] + rw [Ideal.Quotient.algebraMap_eq] + exact isUnit_iff_ne_zero.mpr fun hc ↦ hα (Ideal.Quotient.eq_zero_iff_mem.mp hc) + have := hnt + -- the residue-field witness + have hisoF : algebraMap R (R ⧸ 𝔪) α * algebraMap R (R ⧸ 𝔪) β + + (q.baseChangeOfProjective (R ⧸ 𝔪)) ((1 : R ⧸ 𝔪) ⊗ₜ[R] π m') = 0 := by + rw [QuadraticForm.baseChangeOfProjective_tmul, mul_one, Algebra.smul_def, mul_one, + ← map_mul, ← map_add, hiso, map_zero] + have hnzF : algebraMap R (R ⧸ 𝔪) α ≠ 0 ∨ algebraMap R (R ⧸ 𝔪) β ≠ 0 ∨ + ∃ z : (R ⧸ 𝔪) ⊗[R] M, + polar (q.baseChangeOfProjective (R ⧸ 𝔪)) + ((1 : R ⧸ 𝔪) ⊗ₜ[R] π m') z ≠ 0 := by + have hmk : ∀ r : R, algebraMap R (R ⧸ 𝔪) r = 0 ↔ r ∈ 𝔪 := fun r ↦ + Ideal.Quotient.eq_zero_iff_mem + rcases hnz 𝔪 ‹_› with h | h | ⟨n, hn⟩ + · exact Or.inl fun hc ↦ h ((hmk α).mp hc) + · exact Or.inr (Or.inl fun hc ↦ h ((hmk β).mp hc)) + · refine Or.inr (Or.inr ⟨(1 : R ⧸ 𝔪) ⊗ₜ[R] n, ?_⟩) + rw [QuadraticForm.polar_baseChangeOfProjective_tmul] + exact fun hc ↦ hn ((hmk _).mp hc) + obtain ⟨yF, hyF⟩ := + QuadraticForm.exists_ne_zero_sub_polar_sub_smul (hq (R ⧸ 𝔪)) hisoF hnzF + obtain ⟨x, rfl⟩ := LinearMap.baseChange_surjective (R ⧸ 𝔪) hπ yF + set b' := Algebra.TensorProduct.basis (R ⧸ 𝔪) bm with hb' + refine ⟨fun i ↦ b'.repr x i, ?_⟩ + have hx : ∑ i, b'.repr x i • ((1 : R ⧸ 𝔪) ⊗ₜ[R] bm i) = x := by + simpa [hb', Algebra.TensorProduct.basis_apply] using b'.sum_repr x + rw [QuadraticForm.aeval_eichlerMvPolynomial, hx, hq', + QuadraticForm.baseChangeOfProjective_comp, polar_comp_apply, QuadraticMap.comp_apply, + LinearMap.baseChange_tmul] + exact hyF.isUnit + obtain ⟨t, ht⟩ := hrep + rw [QuadraticForm.aeval_eichlerMvPolynomial_self] at ht + have hsum : ∑ i, t i • bm i = t := by + simpa [hbm] using (Pi.basisFun R (Fin n)).sum_repr t + rw [hsum, hq', polar_comp_apply, QuadraticMap.comp_apply] at ht + exact ⟨π t, ht⟩ + +end LG + + +/-! ### `Dias II.6.2` and cancellation of a plane -/ + +section Cancellation + +open scoped TensorProduct + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-! #### The partial switch + +The switch `(x, y) ↦ (y, x)` of the plane is an isometry that no product of transvections and +dilations can equal — it has the opposite Dickson invariant. An idempotent `ε` lets it be applied +on the clopen piece `D(ε)` of `Spec R` and not on the complement, still as a single global +isometry: `(x, y) ↦ (εy + (1-ε)x, εx + (1-ε)y)`. This is the one move outside the Eichler group +that the argument needs, and it is exactly what handles the locus where `M` vanishes. -/ + +/-- The **partial switch** of the plane: the switch on `D(ε)`, the identity on `D(1 - ε)`. -/ +def switchIdemPlaneMap (ε : R) : (R × R) →ₗ[R] (R × R) := + LinearMap.prod (ε • LinearMap.snd R R R + (1 - ε) • LinearMap.fst R R R) + (ε • LinearMap.fst R R R + (1 - ε) • LinearMap.snd R R R) + +@[simp] theorem switchIdemPlaneMap_apply (ε : R) (x : R × R) : + switchIdemPlaneMap ε x = (ε * x.2 + (1 - ε) * x.1, ε * x.1 + (1 - ε) * x.2) := rfl + +/-- The partial switch of `plane ⊥ q`, acting on the plane and fixing `M`. -/ +def switchIdemMap (ε : R) (M : Type v) [AddCommGroup M] [Module R M] : + ((R × R) × M) →ₗ[R] ((R × R) × M) := + (switchIdemPlaneMap ε).prodMap LinearMap.id + +@[simp] theorem switchIdemMap_apply (ε : R) (x : (R × R) × M) : + switchIdemMap ε M x = + ((ε * x.1.2 + (1 - ε) * x.1.1, ε * x.1.1 + (1 - ε) * x.1.2), x.2) := rfl + +/-- The partial switch is an involution, because `ε` is idempotent. -/ +theorem switchIdemMap_switchIdemMap {ε : R} (hε : IsIdempotentElem ε) (x : (R × R) × M) : + switchIdemMap ε M (switchIdemMap ε M x) = x := by + have hεε : ε * ε = ε := hε.eq + refine Prod.ext (Prod.ext ?_ ?_) rfl <;> simp only [switchIdemMap_apply] + · linear_combination (2 * (x.1.1 - x.1.2)) * hεε + · linear_combination (2 * (x.1.2 - x.1.1)) * hεε + +/-- The partial switch preserves `plane ⊥ q`: on the plane the product `x * y` is `ε` times the +switched product plus `1 - ε` times the original, and `ε(1 - ε) = 0`. -/ +theorem apply_switchIdemMap {ε : R} (hε : IsIdempotentElem ε) (q : QuadraticForm R M) + (x : (R × R) × M) : ((plane R).prod q) (switchIdemMap ε M x) = ((plane R).prod q) x := by + have hεε : ε * ε = ε := hε.eq + simp only [switchIdemMap_apply, QuadraticMap.prod_apply, plane_apply] + linear_combination (-(x.1.1 - x.1.2) ^ 2) * hεε + +/-- The **partial switch** as a self-isometry of `plane ⊥ q`. -/ +noncomputable def switchIdem {ε : R} (hε : IsIdempotentElem ε) (q : QuadraticForm R M) : + ((plane R).prod q).IsometryEquiv ((plane R).prod q) where + __ := LinearEquiv.ofBijective (switchIdemMap ε M) + (Function.bijective_iff_has_inverse.2 + ⟨switchIdemMap ε M, switchIdemMap_switchIdemMap hε, switchIdemMap_switchIdemMap hε⟩) + map_app' := apply_switchIdemMap hε q + +@[simp] theorem switchIdem_apply {ε : R} (hε : IsIdempotentElem ε) (q : QuadraticForm R M) + (x : (R × R) × M) : + switchIdem hε q x = ((ε * x.1.2 + (1 - ε) * x.1.1, ε * x.1.1 + (1 - ε) * x.1.2), x.2) := rfl + +theorem switchIdem_switchIdem {ε : R} (hε : IsIdempotentElem ε) (q : QuadraticForm R M) + (x : (R × R) × M) : switchIdem hε q (switchIdem hε q x) = x := + switchIdemMap_switchIdemMap hε x + +/-- **`Dias II.6.2`, the case where the `u`-coefficient is a unit where `M` vanishes.** Over an LG +ring, if `q` is non-singular on a finitely generated projective module and `α` is a unit at every +residue field where `M` dies, then the hyperbolic pair `(((α, β), m), j)` is the image of the +standard one under a self-isometry. + +The proof is `Dias II.6.1` (`exists_isUnit_sub_polar_sub_smul`) followed by the unit case +(`QuadraticMap.IsHyperbolicPair.exists_isometryEquiv_of_isUnit`): the transvection `E(u, (0, y))` +moves the given pair to one whose `u`-coefficient is a unit, and the unit case moves the standard +pair to *that*; composing with `E(u, (0, y))⁻¹` finishes. + +`exists_isometryEquiv_of_isHyperbolicPair` removes the hypothesis `hM` by a partial switch. -/ +theorem exists_isometryEquiv_of_isHyperbolicPair_of_notMem (hLG : IsLGRing R) [Module.Finite R M] + [Module.Projective R M] {q : QuadraticForm R M} (hq : q.IsGPRNonsingular.{u, v, u}) + (α β : R) (m : M) (j : (R × R) × M) + (hij : IsHyperbolicPair ((plane R).prod q) ((α, β), m) j) + (hM : ∀ 𝔪 : Ideal R, + 𝔪.IsMaximal → α ∉ 𝔪 ∨ Nontrivial ((R ⧸ 𝔪) ⊗[R] M)) : + ∃ σ : ((plane R).prod q).IsometryEquiv ((plane R).prod q), + σ ((1, 0), 0) = ((α, β), m) ∧ σ ((0, 1), 0) = j := by + set Q : QuadraticForm R ((R × R) × M) := (plane R).prod q with hQ + have huv : IsHyperbolicPair Q ((1, 0), 0) ((0, 1), 0) := isHyperbolicPair_plane_prod q + -- the coefficient of `i` is isotropic data + have hiso : α * β + q m = 0 := by + have := hij.apply_left + rwa [hQ, QuadraticMap.prod_apply, plane_apply] at this + -- unimodularity of `i`, read off from `q(i, j) = 1` + have hnz : ∀ 𝔪 : Ideal R, + 𝔪.IsMaximal → α ∉ 𝔪 ∨ β ∉ 𝔪 ∨ ∃ n : M, polar q m n ∉ 𝔪 := by + intro 𝔪 h𝔪 + by_cases hα : α ∈ 𝔪 + · by_cases hβ : β ∈ 𝔪 + · refine Or.inr (Or.inr ⟨j.2, fun hc ↦ h𝔪.ne_top ?_⟩) + have hone := hij.polar_eq_one + rw [hQ, QuadraticMap.polar_prod, polar_plane] at hone + refine Ideal.eq_top_of_isUnit_mem 𝔪 ?_ isUnit_one + rw [← hone] + exact Ideal.add_mem _ + (Ideal.add_mem _ (Ideal.mul_mem_right _ _ hα) (Ideal.mul_mem_right _ _ hβ)) hc + · exact Or.inr (Or.inl hβ) + · exact Or.inl hα + obtain ⟨y, hy⟩ := QuadraticForm.exists_isUnit_sub_polar_sub_smul hLG hq hiso hnz hM + obtain ⟨a, ha⟩ := hy + -- the transvection `E(u, (0, y))` + have hzu : polar Q (((1 : R), (0 : R)), (0 : M)) ((0, 0), y) = 0 := by + rw [hQ, QuadraticMap.polar_prod, polar_plane]; simp + set E := QuadraticMap.eichler huv.apply_left hzu with hE + have hEi : + E ((α, β), m) = + ((0, 0), m + β • y) + (a : R) • ((1, 0), 0) + β • ((0, 1), 0) := by + have hp₁ : polar Q ((1, 0), 0) ((α, β), m) = β := by + rw [hQ, QuadraticMap.polar_prod, polar_plane]; simp + have hp₂ : polar Q ((0, 0), y) ((α, β), m) = polar q y m := by + rw [hQ, QuadraticMap.polar_prod, polar_plane]; simp + have hp₃ : Q ((0, 0), y) = q y := by rw [hQ, QuadraticMap.prod_apply, plane_apply]; simp + rw [hE, QuadraticMap.eichler_apply, hp₁, hp₂, hp₃] + refine Prod.ext (Prod.ext ?_ ?_) ?_ <;> simp + linear_combination -ha + obtain ⟨σ', hσ'u, hσ'v⟩ := + (huv.exists_isometryEquiv_of_isUnit (hij.map E) (a := a) (b := β) + (z := ((0, 0), m + β • y)) + (by rw [hQ, QuadraticMap.polar_prod, polar_plane]; simp) + (by rw [hQ, QuadraticMap.polar_prod, polar_plane]; simp) + (by rw [← hEi])) + refine ⟨σ'.trans E.symm, ?_, ?_⟩ + · change E.symm (σ' ((1, 0), 0)) = _ + rw [hσ'u, E.symm_apply_apply] + · change E.symm (σ' ((0, 1), 0)) = _ + rw [hσ'v, E.symm_apply_apply] + +/-- **`Dias II.6.2`.** Over an LG ring, if `q` is non-singular on a finitely generated projective +module, then every hyperbolic pair of `plane ⊥ q` is the image of the standard hyperbolic pair +under a self-isometry. **No hypothesis on the support of `M`.** + +Where `M ⊗ κ(𝔪)` vanishes the plane is everything, and there the pair `(u, v)` reaches the pair +`(β • v, β⁻¹ • u)` only through the switch — not a product of transvections and dilations. The +partial switch `switchIdem` supplies exactly that, on exactly that locus: with +`ε₀ = Module.rankIdempotent R M 0` and `i = ((α, β), m)`, `j = ((γ, δ), n)`, the element + + `ε := ε₀ * (β * γ)` + +is idempotent, because `ε₀` annihilates `M` and hence kills `q m`, `q n` and `q(m, n)`, leaving +`α β = 0`, `γ δ = 0`, `α δ + β γ = 1` — the relations that make `β γ` idempotent on the vanishing +locus. Applying `switchIdem ε` first turns the `u`-coefficient into `ε β + (1 - ε) α`, which is a +unit at every maximal ideal where `M` dies: there either `β γ` or `α δ` is `1`. That is the +hypothesis `exists_isometryEquiv_of_isHyperbolicPair_of_notMem` needs. -/ +theorem exists_isometryEquiv_of_isHyperbolicPair (hLG : IsLGRing R) [Module.Finite R M] + [Module.Projective R M] {q : QuadraticForm R M} (hq : q.IsGPRNonsingular.{u, v, u}) + (i j : (R × R) × M) (hij : IsHyperbolicPair ((plane R).prod q) i j) : + ∃ σ : ((plane R).prod q).IsometryEquiv ((plane R).prod q), + σ ((1, 0), 0) = i ∧ σ ((0, 1), 0) = j := by + obtain ⟨⟨α, β⟩, m⟩ := i + obtain ⟨⟨γ, δ⟩, n⟩ := j + -- the three identities defining a hyperbolic pair, in coordinates + have hi : α * β + q m = 0 := by + have h := hij.apply_left; rwa [QuadraticMap.prod_apply, plane_apply] at h + have hj : γ * δ + q n = 0 := by + have h := hij.apply_right; rwa [QuadraticMap.prod_apply, plane_apply] at h + have hone : α * δ + β * γ + polar q m n = 1 := by + have h := hij.polar_eq_one; rwa [QuadraticMap.polar_prod, polar_plane] at h + -- the rank-zero idempotent annihilates `M`, hence kills every value of `q` and of its polar + set e := Module.rankIdempotent R M 0 with he + have hee : e * e = e := (Module.isIdempotentElem_rankIdempotent R M 0).eq + have hesmul : ∀ x : M, e • x = 0 := Module.rankIdempotent_zero_smul R M + have heq : ∀ x : M, e * q x = 0 := fun x ↦ by + have h := q.map_smul e x + rw [hesmul x, QuadraticMap.map_zero, hee] at h + exact h.symm + have hepolar : ∀ x y : M, e * polar q x y = 0 := fun x y ↦ by + have h := QuadraticMap.polar_smul_left (Q := q) e x y + rw [hesmul x, polar_zero_left, smul_eq_mul] at h + exact h.symm + -- the idempotent cutting out the locus where the switch is needed + set ε := e * (β * γ) with hεdef + have hε : IsIdempotentElem ε := by + change ε * ε = ε + rw [hεdef] + linear_combination (β * γ) ^ 2 * hee + (e * β * γ) * hone - (β * γ) * hepolar m n - + (e * γ * δ) * hi + (e * q m) * hj - (q n) * heq m + set S := switchIdem hε q with hS + -- after the partial switch the `u`-coefficient is a unit wherever `M` dies + have hM : ∀ 𝔪 : Ideal R, 𝔪.IsMaximal → + ε * β + (1 - ε) * α ∉ 𝔪 ∨ Nontrivial ((R ⧸ 𝔪) ⊗[R] M) := by + intro 𝔪 h𝔪 + rcases subsingleton_or_nontrivial ((R ⧸ 𝔪) ⊗[R] M) with hsub | hnt + swap + · exact Or.inr hnt + refine Or.inl ?_ + have hprime := h𝔪.isPrime + -- `M` dies at `𝔪`, so `ε₀` is a unit there and `q(m, n) ∈ 𝔪` + have hemem : e ∉ 𝔪 := Module.notMem_rankIdempotent_zero R M 𝔪 hsub + have hp : polar q m n ∈ 𝔪 := + (hprime.mem_or_mem (hepolar m n ▸ 𝔪.zero_mem)).resolve_left hemem + rcases hprime.mem_or_mem (show ε * (1 - ε) ∈ 𝔪 by + rw [hε.mul_one_sub_self]; exact 𝔪.zero_mem) with hεm | hεm + · -- `ε ≡ 0`: the coefficient is `α`, and `α δ = 1` at `𝔪` + have hα : α ∉ 𝔪 := by + intro hαmem + refine h𝔪.ne_top (Ideal.eq_top_iff_one _ |>.mpr ?_) + rw [← hone] + exact 𝔪.add_mem (𝔪.add_mem (Ideal.mul_mem_right _ _ hαmem) + ((hprime.mem_or_mem hεm).resolve_left hemem)) hp + intro hc + refine hα ?_ + rw [show α = ε * β + (1 - ε) * α - ε * β + ε * α by ring] + exact 𝔪.add_mem (𝔪.sub_mem hc (Ideal.mul_mem_right _ _ hεm)) + (Ideal.mul_mem_right _ _ hεm) + · -- `ε ≡ 1`: the coefficient is `β`, and `β γ = 1` at `𝔪` + have hβ : β ∉ 𝔪 := by + intro hβmem + refine h𝔪.ne_top (Ideal.eq_top_iff_one _ |>.mpr ?_) + have hεmem : ε ∈ 𝔪 := + hεdef ▸ Ideal.mul_mem_left _ e (Ideal.mul_mem_right _ _ hβmem) + simpa using 𝔪.add_mem hεmem hεm + intro hc + refine hβ ?_ + rw [show β = ε * β + (1 - ε) * α + (1 - ε) * β - (1 - ε) * α by ring] + exact 𝔪.sub_mem (𝔪.add_mem hc (Ideal.mul_mem_right _ _ hεm)) + (Ideal.mul_mem_right _ _ hεm) + obtain ⟨σ', hσ'u, hσ'v⟩ := exists_isometryEquiv_of_isHyperbolicPair_of_notMem hLG hq + (ε * β + (1 - ε) * α) (ε * α + (1 - ε) * β) m (S ((γ, δ), n)) (hij.map S) hM + have hSi : S ((α, β), m) = ((ε * β + (1 - ε) * α, ε * α + (1 - ε) * β), m) := rfl + refine ⟨σ'.trans S, ?_, ?_⟩ + · change S (σ' ((1, 0), 0)) = _ + rw [hσ'u, ← hSi, hS, switchIdem_switchIdem] + · change S (σ' ((0, 1), 0)) = _ + rw [hσ'v, hS, switchIdem_switchIdem] + +/-- **Cancellation of a hyperbolic plane over an LG ring.** For `q₂` non-singular on a finitely +generated projective module, `plane ⊥ q₁ ≅ plane ⊥ q₂` implies `q₁ ≅ q₂`. + +This is `Dias II.6.4` for one plane: `Dias II.6.2` supplies the transitivity that +`QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod` consumes. Note `q₁` carries no +hypotheses at all, and `q₂` only non-singularity — in particular `M` may vanish, or vanish on +part of `Spec R`. -/ +theorem isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing (hLG : IsLGRing R) + {M₁ : Type v₁} [AddCommGroup M₁] [Module R M₁] [Module.Finite R M] + [Module.Projective R M] + {q₁ : QuadraticForm R M₁} {q₂ : QuadraticForm R M} + (hq₂ : q₂.IsGPRNonsingular.{u, v, u}) + (h : Nonempty (((plane R).prod q₁).IsometryEquiv ((plane R).prod q₂))) : + Nonempty (q₁.IsometryEquiv q₂) := + QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod + (fun i j hij ↦ exists_isometryEquiv_of_isHyperbolicPair hLG hq₂ i j hij) h + +end Cancellation + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Polynomial.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Polynomial.lean new file mode 100644 index 0000000000..91395c2a4b --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Polynomial.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective +public import Mathlib.Algebra.MvPolynomial.Eval +public import Mathlib.RingTheory.TensorProduct.Free + +/-! +# A quadratic form on a free module as a polynomial (`GPR 11.8`) + +If `M` is free with basis `bm : Basis (Fin n) R M`, a quadratic form `q : M → R` is a homogeneous +quadratic polynomial in `n` variables, and evaluating that polynomial over any `R`-algebra `S` +computes `q` base-changed to `S`. This is what lets the LG axiom — which speaks about +`MvPolynomial (Fin n) R` — say anything about quadratic forms. + +## Main definitions + +* `QuadraticForm.toMvPolynomial q bm` : `∑ i, ∑ j, C (B (bm i) (bm j)) * X i * X j`, where `B` is + the bilinear representative `QuadraticMap.bilinRepr q` used to define + `QuadraticForm.baseChangeOfProjective`. + +## Main results + +* `QuadraticForm.aeval_toMvPolynomial_self` : + `aeval t (toMvPolynomial q bm) = q (∑ i, t i • bm i)`. +* `QuadraticForm.aeval_toMvPolynomial` : the same after base change, + `aeval s (toMvPolynomial q bm) = (q.baseChangeOfProjective S) (∑ i, s i • (1 ⊗ₜ bm i))`. +* `QuadraticForm.totalDegree_toMvPolynomial_le` : the polynomial has total degree at most two. + +## Implementation notes + +The polynomial is built from `QuadraticMap.bilinRepr q` rather than from `QuadraticMap.toBilin` +(mathlib's triangular representative) purely so that the base-change statement is immediate: +`QuadraticForm.baseChangeOfProjective` is *defined* as the diagonal of +`LinearMap.BilinForm.baseChange` applied to `bilinRepr`, so both sides of +`aeval_toMvPolynomial` expand to the same double sum without needing +`baseChangeOfProjective_eq_of_toQuadraticMap_eq`. The polynomial is not canonical — a different +bilinear representative gives a different polynomial — but its evaluations are, which is all the +LG axiom cares about. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.8. +-/ + +@[expose] public section + +universe u v w + +open scoped TensorProduct + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + [Module.Finite R M] [Module.Projective R M] {n : ℕ} + +variable (q : QuadraticForm R M) (bm : Module.Basis (Fin n) R M) + +/-- The quadratic polynomial of `q` in the basis `bm` (`GPR 11.8`), built from the bilinear +representative that `QuadraticForm.baseChangeOfProjective` uses. -/ +noncomputable def toMvPolynomial : MvPolynomial (Fin n) R := + ∑ i, ∑ j, MvPolynomial.C (QuadraticMap.bilinRepr q (bm i) (bm j)) * + MvPolynomial.X i * MvPolynomial.X j + +/-- The polynomial of a quadratic form in a basis is quadratic: its total degree is at most two. +Each summand `C (B (bm i) (bm j)) * X i * X j` is a constant times two variables. -/ +theorem totalDegree_toMvPolynomial_le : + (QuadraticForm.toMvPolynomial q bm).totalDegree ≤ 2 := by + rcases subsingleton_or_nontrivial R with hR | hR + · let : Subsingleton (MvPolynomial (Fin n) R) := inferInstance + rw [Subsingleton.elim (QuadraticForm.toMvPolynomial q bm) 0, MvPolynomial.totalDegree_zero] + exact Nat.zero_le 2 + have hterm : ∀ i j : Fin n, (MvPolynomial.C (QuadraticMap.bilinRepr q (bm i) (bm j)) * + MvPolynomial.X i * MvPolynomial.X j : MvPolynomial (Fin n) R).totalDegree ≤ 2 := by + intro i j + have h₁ := MvPolynomial.totalDegree_mul + (MvPolynomial.C (QuadraticMap.bilinRepr q (bm i) (bm j)) * + (MvPolynomial.X i : MvPolynomial (Fin n) R)) (MvPolynomial.X j) + have h₂ := MvPolynomial.totalDegree_mul + (MvPolynomial.C (QuadraticMap.bilinRepr q (bm i) (bm j))) + (MvPolynomial.X i : MvPolynomial (Fin n) R) + rw [MvPolynomial.totalDegree_C] at h₂ + rw [MvPolynomial.totalDegree_X] at h₁ h₂ + omega + refine le_trans (MvPolynomial.totalDegree_finsetSum _ _) (Finset.sup_le fun i _ ↦ ?_) + exact le_trans (MvPolynomial.totalDegree_finsetSum _ _) (Finset.sup_le fun j _ ↦ hterm i j) + +variable {q bm} + +/-- Evaluating `toMvPolynomial` over an `R`-algebra `S` gives a double sum in the Gram matrix of +the bilinear representative. -/ +theorem aeval_toMvPolynomial_eq_sum {S : Type w} [CommRing S] [Algebra R S] (s : Fin n → S) : + MvPolynomial.aeval s (QuadraticForm.toMvPolynomial q bm) = + ∑ i, ∑ j, algebraMap R S (QuadraticMap.bilinRepr q (bm i) (bm j)) * s i * s j := by + simp only [toMvPolynomial, map_sum, map_mul, MvPolynomial.aeval_C, MvPolynomial.aeval_X] + +/-- A bilinear form evaluated on a pair of finite sums is the double sum of its values. -/ +private theorem bilin_sum_sum {S : Type w} [CommRing S] {P : Type*} [AddCommGroup P] [Module S P] + (T : LinearMap.BilinForm S P) (f g : Fin n → P) : + T (∑ i, f i) (∑ j, g j) = ∑ i, ∑ j, T (f i) (g j) := by + simp only [map_sum, LinearMap.sum_apply] + exact Finset.sum_comm + +/-- **`GPR 11.8`, over `R` itself.** -/ +theorem aeval_toMvPolynomial_self (t : Fin n → R) : + MvPolynomial.aeval t (QuadraticForm.toMvPolynomial q bm) = q (∑ i, t i • bm i) := by + rw [aeval_toMvPolynomial_eq_sum, ← QuadraticMap.bilinRepr_apply_self q, + bilin_sum_sum (QuadraticMap.bilinRepr q)] + refine Finset.sum_congr rfl fun i _ ↦ Finset.sum_congr rfl fun j _ ↦ ?_ + simp only [map_smul, LinearMap.smul_apply, smul_eq_mul, Algebra.algebraMap_self_apply] + ring + +/-- **`GPR 11.8`.** The polynomial of `q` in a basis computes `q` after every base change: its +value at `s : Fin n → S` is `q_S` evaluated at the corresponding point of `S ⊗[R] M`. -/ +theorem aeval_toMvPolynomial {S : Type w} [CommRing S] [Algebra R S] (s : Fin n → S) : + MvPolynomial.aeval s (QuadraticForm.toMvPolynomial q bm) = + (q.baseChangeOfProjective S) (∑ i, s i • ((1 : S) ⊗ₜ[R] bm i)) := by + rw [aeval_toMvPolynomial_eq_sum, QuadraticForm.baseChangeOfProjective, + LinearMap.BilinMap.toQuadraticMap_apply, + bilin_sum_sum (LinearMap.BilinForm.baseChange S (QuadraticMap.bilinRepr q))] + refine Finset.sum_congr rfl fun i _ ↦ Finset.sum_congr rfl fun j _ ↦ ?_ + simp only [map_smul, LinearMap.smul_apply, LinearMap.BilinForm.baseChange_tmul, mul_one, + smul_eq_mul, Algebra.smul_def] + ring + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Real.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Real.lean new file mode 100644 index 0000000000..86d71e0790 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Real.lean @@ -0,0 +1,147 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.Real +public import TauCeti.LinearAlgebra.QuadraticForm.Real + +/-! +# Anisotropic real quadratic forms are definite, and determined by their dimension and sign + +The existence half of Sylvester's law of inertia — mathlib's +`QuadraticForm.equivalent_one_zero_neg_one_weighted_sum_squared` — writes a real quadratic form as +a weighted sum of squares with weights `-1`, `0`, `1`. Anisotropy +forbids the weight `0`, and forbids `-1` and `1` from occurring together — a weight `0` gives a null +basis vector, and opposite weights give a null sum of two basis vectors. So an anisotropic real form +is `± (x₁² + ⋯ + xₙ²)`, and the sign is decided by any single value. + +Consequently two anisotropic real quadratic forms of the same dimension taking a positive value are +isometric. This is the classification input the real case of the composition-algebra classification +needs; the composition norm takes the value `1` at the identity element. TauCeti has the general +classification of real quadratic forms by signature +(`QuadraticForm.equivalent_iff_finrank_eq_and_sigPos_eq_and_sigNeg_eq`) and the definiteness +criterion used here (`QuadraticForm.anisotropic_iff_posDef_or_negDef`); this file records only the +corollary in the form the classification consumes. + +## Main results + +* `QuadraticForm.equivalent_sumSquares_of_anisotropic` : an anisotropic real form with a positive + value is equivalent to the sum of `finrank` squares. +* `QuadraticForm.posDef_of_anisotropic` : such a form is positive definite. +* `QuadraticForm.equivalent_of_anisotropic_of_finrank_eq` : two anisotropic real forms of equal + dimension, each taking a positive value, are equivalent. + +## References + +* Sylvester, *A demonstration of the theorem that every homogeneous quadratic polynomial is + reducible by real orthogonal substitutions to the form of a sum of positive and negative + squares*, Philosophical Magazine **4** (1852), 138–142. +-/ + +@[expose] public section + +universe v w + +open QuadraticMap + +namespace QuadraticForm + +variable {M : Type v} [AddCommGroup M] [Module ℝ M] [FiniteDimensional ℝ M] + {N : Type w} [AddCommGroup N] [Module ℝ N] [FiniteDimensional ℝ N] + +omit [FiniteDimensional ℝ M] [FiniteDimensional ℝ N] in +/-- Anisotropy transports backwards along an isometry. -/ +private theorem anisotropic_of_isometryEquiv {Q : QuadraticForm ℝ M} {P : QuadraticForm ℝ N} + (e : Q.IsometryEquiv P) (h : Q.Anisotropic) : P.Anisotropic := fun x hx ↦ by + have hQ : Q (e.symm x) = 0 := by + rw [← e.map_app (e.symm x), e.apply_symm_apply]; exact hx + rw [← e.apply_symm_apply x, h _ hQ, map_zero] + +/-- **An anisotropic real quadratic form taking a positive value is a sum of squares.** By +Sylvester's law it is a weighted sum of squares with weights in `{-1, 0, 1}`; a zero weight would +make a basis vector null, and a `-1` alongside a `1` would make the sum of the two corresponding +basis vectors null. A positive value forces the common weight to be `1`. -/ +theorem equivalent_sumSquares_of_anisotropic (Q : QuadraticForm ℝ M) (hani : Q.Anisotropic) + {v : M} (hv : 0 < Q v) : + Q.Equivalent (weightedSumSquares ℝ (1 : Fin (Module.finrank ℝ M) → ℝ)) := by + classical + obtain ⟨w, hw, ⟨e⟩⟩ := Q.equivalent_one_zero_neg_one_weighted_sum_squared + have hani' : (weightedSumSquares ℝ w).Anisotropic := anisotropic_of_isometryEquiv e hani + -- The value of the weighted sum of squares at a single basis vector is the weight. + have hsingle : ∀ i, weightedSumSquares ℝ w (Pi.single i (1 : ℝ)) = w i := by + intro i + rw [weightedSumSquares_apply] + rw [Finset.sum_eq_single_of_mem i (Finset.mem_univ i)] + · simp + · intro j _ hj + simp [hj] + -- The value at the sum of two distinct basis vectors is the sum of the two weights. + have hpair : ∀ i j, i ≠ j → + weightedSumSquares ℝ w (Pi.single i (1 : ℝ) + Pi.single j (1 : ℝ)) = w i + w j := by + intro i j hij + rw [weightedSumSquares_apply, + ← Finset.sum_subset (Finset.subset_univ ({i, j} : Finset (Fin (Module.finrank ℝ M)))) + (fun k _ hk ↦ by + have hki : k ≠ i := fun h ↦ hk (by simp [h]) + have hkj : k ≠ j := fun h ↦ hk (by simp [h]) + simp [hki, hkj]), + Finset.sum_pair hij] + simp [hij, Ne.symm hij] + -- Some weight is positive, since the form takes a positive value. + have hpos : ∃ j, w j = 1 := by + by_contra hcon + have hcon' : ∀ j, w j ≠ 1 := fun j hj ↦ hcon ⟨j, hj⟩ + have hle : weightedSumSquares ℝ w (e v) ≤ 0 := by + rw [weightedSumSquares_apply] + refine Finset.sum_nonpos fun j _ ↦ ?_ + have : w j ≤ 0 := by rcases hw j with h | h | h <;> simp_all + simpa using mul_nonpos_of_nonpos_of_nonneg this (mul_self_nonneg _) + rw [e.map_app v] at hle + exact absurd hv (not_lt.mpr hle) + -- Every weight is `1`: none is `0`, and none is `-1`. + have hone : ∀ i, w i = 1 := by + intro i + rcases hw i with h | h | h + · exfalso + obtain ⟨j, hj⟩ := hpos + have hij : i ≠ j := fun hij ↦ by rw [hij, hj] at h; norm_num at h + have hnull := hani' _ ((hpair i j hij).trans (by rw [h, hj]; ring)) + simpa [hij] using congrFun hnull i + · exfalso + have hnull := hani' _ ((hsingle i).trans h) + simpa using congrFun hnull i + · exact h + have hw1 : w = 1 := funext hone + subst hw1 + exact ⟨e⟩ + +omit [FiniteDimensional ℝ M] in +/-- An anisotropic real quadratic form taking a positive value is positive definite: by TauCeti's +`QuadraticForm.anisotropic_iff_posDef_or_negDef` it is positive or negative definite, and the +positive value rules out the second. -/ +theorem posDef_of_anisotropic (Q : QuadraticForm ℝ M) (hani : Q.Anisotropic) {v : M} + (hv : 0 < Q v) : Q.PosDef := by + refine ((QuadraticForm.anisotropic_iff_posDef_or_negDef Q).mp hani).resolve_right fun hneg ↦ ?_ + have hv0 : v ≠ 0 := fun h ↦ by simp [h] at hv + have := hneg v hv0 + simp only [neg_apply, Left.neg_pos_iff] at this + exact absurd hv (not_lt.mpr this.le) + +/-- **Anisotropic real quadratic forms are classified by their dimension and sign.** Two +anisotropic real forms of the same dimension, each taking a positive value, are isometric. The sign +hypothesis cannot be dropped: `x²` and `-x²` are anisotropic of the same dimension but not +isometric. -/ +theorem equivalent_of_anisotropic_of_finrank_eq {Q : QuadraticForm ℝ M} {P : QuadraticForm ℝ N} + (hQ : Q.Anisotropic) (hP : P.Anisotropic) {v : M} (hv : 0 < Q v) {u : N} (hu : 0 < P u) + (hdim : Module.finrank ℝ M = Module.finrank ℝ N) : Q.Equivalent P := by + have hmid : (weightedSumSquares ℝ (1 : Fin (Module.finrank ℝ M) → ℝ)).Equivalent + (weightedSumSquares ℝ (1 : Fin (Module.finrank ℝ N) → ℝ)) := by + rw [hdim] + exact ⟨QuadraticMap.IsometryEquiv.refl _⟩ + exact ((Q.equivalent_sumSquares_of_anisotropic hQ hv).trans hmid).trans + (P.equivalent_sumSquares_of_anisotropic hP hu).symm + +end QuadraticForm diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean new file mode 100644 index 0000000000..79484280ee --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean @@ -0,0 +1,1204 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import Mathlib.LinearAlgebra.QuadraticForm.Basic +public import Mathlib.LinearAlgebra.QuadraticForm.Prod +public import Mathlib.LinearAlgebra.QuadraticForm.Radical +public import Mathlib.LinearAlgebra.Dual.BaseChange +public import Mathlib.LinearAlgebra.Dual.Lemmas +public import Mathlib.LinearAlgebra.PerfectPairing.Basic +public import Mathlib.LinearAlgebra.FiniteDimensional.Lemmas +public import Mathlib.RingTheory.Finiteness.Prod +public import Mathlib.RingTheory.Flat.Stability +public import Mathlib.RingTheory.Ideal.Nonunits +public import Mathlib.RingTheory.Ideal.Quotient.Operations +public import Mathlib.RingTheory.LocalProperties.Exactness +public import Mathlib.RingTheory.LocalRing.Module +public import Mathlib.RingTheory.Localization.AtPrime.Basic +public import Mathlib.RingTheory.Localization.BaseChange +public import Mathlib.RingTheory.Spectrum.Prime.FreeLocus +public import Mathlib.RingTheory.TensorProduct.Free +public import Mathlib.LinearAlgebra.TensorProduct.Prod +public import Mathlib.LinearAlgebra.TensorProduct.Tower +public import Mathlib.LinearAlgebra.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.BaseChangeProjective +public import TauCeti.LinearAlgebra.Dual.BaseChange +public import TauCeti.LinearAlgebra.Dual.Rank +public import TauCeti.LinearAlgebra.QuadraticForm.Radical + +/-! +# Regularity of quadratic forms: the radical, `IsGPRNondegenerate`, `IsGPRRegular`, +# `IsGPRNonsingular`, `IsEKMNondegenerate` + +There is no agreement in the literature on the right words (nonsingular, regular, non-degenerate, +etc.) for regularity conditions on quadratic forms, and worse, the *same* word means different +things in different sources. To keep this straight, every regularity predicate in this file is +named after the source whose convention it follows. + +`GPR 11.11` distinguishes four notions: **weakly regular** (the polar form is injective — mathlib's +`polarBilin.Nondegenerate`/`SeparatingLeft`, overview §6(b)), **non-degenerate** +(`radical Q = ⊥`, `GN C.8(d)`), **non-singular** (the radical vanishes after every field base +change, `GN C.8(e)`), and **regular** (the polar form is an isomorphism onto the dual, not just +injective). + +⚠ **Over a general ring these do not form a linear ladder.** Since `radical Q` lies in the kernel +of the polar form, regular ⇒ weakly regular ⇒ non-degenerate; and regular ⇒ non-singular for `M` +finitely generated projective (`GN (C.8.1)`). Nothing else holds in general. `x²` over `𝔽₂` is +non-degenerate (indeed non-singular) but not weakly regular, its polar form being zero; `x²` over +`𝔽₂[ε]/(ε²)` is non-singular but has `ε` in its radical; and `2x²` over `ℤ` is weakly regular but +not non-singular, since it vanishes modulo `2`. Over any field non-singular ⇒ non-degenerate (the +converse fails for `x² + t y²` over `𝔽₂(t)`, which acquires a radical vector over `𝔽₂(√t)`), and +for finite-dimensional forms over a field of characteristic not `2` all four notions agree. + +`EKM` independently has its own two-rung ladder built from the same radical, calling its rungs +"regular" and "non-degenerate" — words that collide with, but do not mean the same thing as, GPR's +"regular" and "non-degenerate". + +## Main definitions + +* `QuadraticForm.IsGPRNondegenerate` : `QuadraticMap.radical Q = ⊥`, GPR's own "non-degenerate" + rung. The radical is **mathlib's** `QuadraticMap.radical`, the submodule of vectors on which + both `Q` and its polar form vanish (`GN C.8(d)`, `EKM` II §7). It lies in the kernel of the polar + form, so `radical Q = ⊥` is *weaker* than mathlib's + `LinearMap.BilinForm.Nondegenerate`/`SeparatingLeft` (injectivity of the polar form); `x²` over + `𝔽₂` separates them. `IsGPRNondegenerate` is *not* the same as mathlib's + `QuadraticMap.Nondegenerate`, which also bounds the rank of the polar radical and over a field + is the `IsGPRNonsingular` condition (`QuadraticForm/NonsingularOverFields.lean`), nor the same as + `EKM`'s "non-degenerate" (see `QuadraticForm.IsEKMNondegenerate` below). +* `QuadraticForm.IsGPRRegular` : `polarBilin Q` is a *bijection* onto `Module.Dual R M`, not merely + injective (`SeparatingLeft`/weakly regular only asks injectivity). Equivalently, `polarBilin Q` + is a mathlib perfect pairing (`QuadraticForm.isGPRRegular_iff_isPerfPair`). +* `QuadraticForm.IsGPRNonsingular` : `radical (Q.baseChangeOfProjective F) = ⊥` for every field `F` + with `[Algebra R F]` (`GN C.8(e)`). GPR calls this property **non-singular**; readers may know + the same condition as **non-degenerate**, **ordinary**, or **semiregular**, especially over + fields (`GPR Exc. 11.37`, Remark (2)). +* `QuadraticForm.IsEKMNondegenerate` : for `Q` over a *field* `F`, + `radical (Q.baseChangeOfProjective K) = ⊥` for every field `K` with `[Algebra F K]` + (`EKM Definition 7.17`, condition (1) of `Lemma + 7.16`). Literally the same universal statement as `IsGPRNonsingular` specialized to `R` already a + field — see `QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular` below. + +## Main results + +* `QuadraticForm.IsGPRRegular.isGPRNondegenerate` : regularity implies that the radical vanishes. +* `QuadraticForm.radical_eq_bot_iff_injective_polarBilin` : when `2 ∈ Rˣ`, `Q.radical = ⊥` + agrees exactly with mathlib's weakly-regular/`Nondegenerate` (`GN (C.8.2)`, non-base-changed + half). This is what makes `IsGPRNondegenerate` collapse onto mathlib's `Nondegenerate` once `2` + is invertible, and it needs no base change at all: it is a fact about `Q` over `R` itself. +* `QuadraticForm.IsGPRRegular.isGPRNonsingular` : `Q` regular implies `Q` non-singular for `M` + finitely generated projective (`GN (C.8.1)`), via + `QuadraticForm.IsGPRRegular.injective_polarBilin_baseChangeOfProjective` — regularity survives + base change as injectivity of the polar form. +* `Module.Dual.bijective_of_forall_residue_field_injective` : a map from a finite **free** + module to its dual that is injective after base change to every residue field is bijective — + the determinant heart of `GN (C.8.2)`'s converse. +* `QuadraticForm.isGPRRegular_of_forall_baseChangeOfProjective_isGPRRegular` : regularity after + every field base change implies regularity over the base ring, for a finite projective module. +* `QuadraticForm.IsGPRNonsingular.bijective_baseChange_of_isLocalRing` : the same statement for + `M` finite projective, after base change to an arbitrary *local* `R`-algebra, where `M` becomes + free. +* `QuadraticForm.IsGPRNonsingular.isGPRRegular`, `QuadraticForm.isGPRRegular_iff_isGPRNonsingular` : + `GN (C.8.2)`'s converse (non-singular implies regular when `2 ∈ Rˣ`) and the resulting + equivalence. +* `QuadraticMap.radical_prod_eq_bot`, + `QuadraticMap.radical_eq_bot_left_of_radical_prod_eq_bot` : how the radical of an orthogonal sum + `QuadraticMap.prod` relates to those of its summands, over an arbitrary base ring. +* `QuadraticForm.baseChangeOfProjective_prod` : base change of an orthogonal sum is the orthogonal + sum of the base changes, along the canonical `A ⊗[R] (M₁ × M₂) ≃ (A ⊗ M₁) × (A ⊗ M₂)`. +* `QuadraticForm.IsGPRNonsingular.of_prod_left`, `.of_prod_right`, + `QuadraticForm.IsGPRRegular.prod_isGPRNonsingular` : **`GN (C.8.3)`**, the two implications + relating non-singularity to orthogonal sums. The asymmetry is essential — the second needs `q₁` + *regular*, not merely non-singular. +* `QuadraticForm.isGPRNonsingular_rankOne`, `QuadraticForm.isGPRRegular_rankOne_iff` : the + rank-one form `⟨u⟩ : r ↦ u * r ^ 2` is non-singular for `u` a unit, but regular only when + `2 * u` is one — so `IsGPRNonsingular` is strictly weaker than `IsGPRRegular`, and the + `2 ∈ Rˣ` hypothesis above is sharp. `QuadraticForm.not_isGPRRegular_rankOne_one_int` is the + concrete witness over `ℤ`. +* `QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular` : over a field `R`, `IsEKMNondegenerate` + and `IsGPRNonsingular` are the same predicate. +* `QuadraticForm.isGPRRegular_prod_iff` : an orthogonal sum is regular exactly when both summands + are. +* `QuadraticForm.IsGPRRegular.smul_of_isUnit`, `QuadraticForm.isUnit_of_isGPRRegular_smul` : + rescaling by a unit preserves regularity, and on a module with a unimodular element a regular + rescaling `c • q` forces `c` to be a unit. +* `QuadraticMap.injOn_ker_polarBilin`, `QuadraticMap.two_smul_eq_zero_of_mem_ker_polarBilin` : for + `Q` with vanishing radical, `Q` is injective on the kernel of its polar form, and `2` kills that + kernel (the assertion `2 C⊥ = 0` of `GPR 19.3`). + +All results in this file are complete; there are no `sorry`s. + +## Implementation notes + +`IsGPRNonsingular` is stated for `M` finitely generated projective over `R`, matching GN's own +definition of a "quadratic form" (finite projectivity of the module is part of the data, not a +separate hypothesis). It routes through `QuadraticForm.baseChangeOfProjective` +(`QuadraticForm/BaseChangeProjective.lean`), *not* mathlib's `QuadraticForm.baseChange`: the latter +requires `[Invertible (2 : R)]` (built from the halved `QuadraticMap.associated`) and is therefore +inapplicable to exactly the characteristic-2 example (`GPR 19.4`, Layer 8) this development exists +to support — the trap overview §6(a) is about. + +**What is used, and from where.** `GPR 9.15`, that duals of finitely generated projective modules +commute with base change, is TauCeti's `TauCeti.Module.Dual.baseChangeEvaluationEquiv`, which +identifies `A ⊗[R] (Module.Dual R M)` with `Module.Dual A (A ⊗[R] M)`; its rank consequence is +`TauCeti.Module.rankAtStalk_dual`. + +Consequently, `GN (C.8.1)` (`Q` regular implies `Q` non-singular) is proved for every finitely +generated projective `M`, with no freeness hypothesis. + +The other piece the free case needed was a compatibility fact between mathlib's +`LinearMap.BilinForm.baseChange` (built via `tensorDistrib`) and the composite of ordinary linear +base change with the dual-comparison map above; that is +`LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange`, proved directly by checking both sides on +pure tensors. + +**The converse half of `GN (C.8.2)`, and why it needed care.** Non-singular implies regular is +the classical local-global argument, in three steps, none of them deep: + +1. Over a ring where the module is *free*, `polarBilin Q` is a square matrix, and a matrix is + invertible iff its determinant is a unit iff that determinant lies in no maximal ideal — so + injectivity after base change to each residue field (which is what non-singularity supplies) + forces invertibility. That is `Module.Dual.bijective_of_forall_residue_field_injective`. +2. Over a *local* ring `S`, a finite projective `M` becomes free (finite + flat over a local + ring), so step 1 applies to `S ⊗[R] M`. That is + `QuadraticForm.IsGPRNonsingular.bijective_baseChange_of_isLocalRing`. +3. A linear map that is bijective after base change to `Localization.AtPrime 𝔪` for every maximal + `𝔪` is bijective. That is `LinearMap.bijective_of_forall_baseChange_atPrime_bijective`. + +Mathematically that is the whole proof, and every step was easy. What made it hard in Lean was +naming residue fields concretely, and the fix in both places was to keep them abstract: + +* Step 1's hypothesis is phrased as "for every field `F` with `[Algebra S F]` whose structure map + has kernel `𝔪`", *not* as "for `S ⧸ 𝔪`". Since `IsGPRNonsingular` accepts any field carrying an + `R`-algebra structure, and a residue field of `S` carries one via `R → S → F`, step 2 can feed + it such an `F` with no residue-field identification at all — no + `IsLocalization.AtPrime.equivQuotMaximalIdeal`, no `IsLocalRing.eq_maximalIdeal`. Had the + hypothesis kept the concrete `S ⧸ 𝔪`, step 2 would have to elaborate + `Localization.AtPrime 𝔪 ⧸ 𝔫`, a quotient of a localization, whose `CommSemiring` instance + diverges against the ring structure underlying `Ideal.Quotient.field 𝔫`; an earlier attempt + along those lines ran for eight hours without terminating. +* Step 2 is likewise stated for an arbitrary local `R`-algebra `S`, with the localization + supplied only in the one-line corollary `bijective_baseChange_atPrime`. With `S` a variable, + `SMul R S` can only be `Algebra.toSMul`, so the `IsScalarTower R S F` the proof builds for a + residue field typechecks on the nose; at the concrete localization it would have to be + reconciled with `OreLocalization.instSMulOfIsScalarTower`. + +One further instance subtlety, recorded because it is easy to hit again: inside step 1 the +residue field structure on `S ⧸ 𝔪` must be introduced with `letI`, not `haveI`. `hinj` +synthesizes `Field F` first and then wants an `Algebra S F` over *that* semiring structure; an +opaque `haveI` prevents `Field.toSemiring` from unfolding to the quotient's own `CommRing`, and +`Algebra S (S ⧸ 𝔪)` then fails to synthesize outright. + +**Sharpness of `2 ∈ Rˣ`.** That hypothesis in `GN (C.8.2)` is not an artifact of the proof: +`QuadraticForm.rankOne`, the form `⟨u⟩ : r ↦ u * r ^ 2` on `R` itself, is non-singular for every +unit `u` (`isGPRNonsingular_rankOne`) but regular exactly when `2 * u` — equivalently `2` — is a +unit (`isGPRRegular_rankOne_iff`, `isGPRRegular_rankOne_iff_isUnit_two`). Over `ℤ` with `u = 1` +this separates the two predicates outright. See the section at the end of this file. + +**Comparison with `EKM`.** `GN C.9` identifies non-singularity over a field with EKM's notion of +non-degeneracy. Traced +to source: `GN` cites `EKM Definition 7.17`, which in turn rests on `EKM Lemma 7.16`. Unlike `GPR` +and `GN`, `EKM` only ever works with quadratic forms over a *field*, never over a general +commutative ring — so its terminology only competes with `GPR`'s once `R` is specialized to a +field, and any Lean statement relating the two must carry that hypothesis explicitly rather than +silently inheriting it. For a quadratic form `ϕ` over a field `F` with polar form `b_ϕ`, `EKM` +write `rad ϕ := {v ∈ rad b_ϕ : ϕ(v) = 0}` — precisely mathlib's `QuadraticMap.radical` — and call +`ϕ` **regular** if `rad ϕ = 0`. + +⚠ **This is a third name for our `IsGPRNondegenerate`, not for `IsGPRRegular`.** `EKM`'s "regular" +means `rad ϕ = 0`, matching `QuadraticForm.IsGPRNondegenerate`, *not* the bijective-polar-form +`QuadraticForm.IsGPRRegular` above — a second, independent collision on top of the +"non-degenerate" one already noted, both worth getting right before formalizing `EKM`'s statements +here. + +`EKM Lemma 7.16` shows TFAE: (1) `ϕ_K` is `EKM`-regular for every field extension `K/F`; +(2) `ϕ_K` is `EKM`-regular for some algebraically closed `K ⊇ F`; (3) `ϕ` is `EKM`-regular and +`dim (rad b_ϕ) ≤ 1`. `Definition 7.17` calls `ϕ` **non-degenerate** when these hold; this is +`QuadraticForm.IsEKMNondegenerate` below, defined via condition (1) since it is the one that reads +verbatim as a base-change statement. When `R` is already a field, condition (1) is literally +`IsGPRNonsingular Q` (`Algebra R F` for `F` a field is automatically a field extension of `R`, +field homomorphisms being injective) — the two quantify over exactly the same class of base +changes — which is `QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular` below. That equality of +predicates is immediate from the definitions. `EKM Lemma 7.16` itself (that conditions (1)–(3) +agree) is proved in `QuadraticForm/NonsingularOverFields.lean`, by `EKM`'s own elementary +argument rather than by `GN`'s `C.9`, whose proof cites an external étale-cover argument `GN` +does not reprove and which overview §8 asks us not to import wholesale. That file also proves +`GPR Exercise 11.37` and most of its Remark (1). + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Cambridge + University Press, New Mathematical Monographs vol. 48, 2024. 11.11, 19.3, 19.4. +* [GPR 42] Calmès, Fasel, *Groupes classiques*, Panoramas & Synthèses **46** (2015), + 1–133. +* [GPR 53] Conrad, *Reductive group schemes*, in *Autour des schémas en groupes*, vol. I, + Panoramas & Synthèses **42/43** (2014), 93–444. +* [GPR 60] Deligne, Katz, *Groupes de Monodromie en Géométrie Algébrique: Séminaire de + Géométrie Algébrique du Bois-Marie 1967–1969 (SGA 7 II)*, vol. 340, Springer, 2006. +* [GPR 157] Knus, *Quadratic and Hermitian Forms over Rings*, vol. 294, Springer-Verlag, 1991. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Appendix C + (`C.8`, `C.9`). +* [EKM] Elman, Karpenko, Merkurjev, *The Algebraic and Geometric Theory of Quadratic Forms*, + AMS Colloquium Publications vol. 56, 2008. §7.A, Lemma 7.16, Definition 7.17. +-/ + +@[expose] public section + +universe u v w s t₁ t₂ t₃ + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + {N : Type w} [AddCommGroup N] [Module R N] + +/-- `Q` is **non-degenerate** in GPR's sense (`GPR 11.11`, overview §6(b)): +`QuadraticMap.radical Q = ⊥`. This is a genuinely different, *weaker* notion than mathlib's +`polarBilin.Nondegenerate` (GPR's "weakly regular"), which asks the polar form itself to be +injective: the radical lies in the kernel of the polar form, so an injective polar form forces +`radical Q = ⊥`, but not conversely — `x²` over `𝔽₂` has zero polar form and zero radical. + +The radical itself is mathlib's `QuadraticMap.radical` — the submodule of vectors on which both +`Q` and its polar form vanish (`GN C.8(d)`, `EKM` Chapter II §7). Constraining `Q` itself, not +just the polar form, is what makes it smaller than the kernel of the polar form, which is all that +mathlib's bilinear-form nondegeneracy predicates see — see overview §6(b). + +**Terminology.** Named for its source, `GPR`, since `EKM` uses "non-degenerate" for a different, +stronger condition — see `QuadraticForm.IsEKMNondegenerate` below. Note in particular that this +is *not* mathlib's `QuadraticMap.Nondegenerate`, which additionally bounds the rank of the polar +radical and over a field is the `IsGPRNonsingular` condition; see +`QuadraticForm/NonsingularOverFields.lean`. -/ +def QuadraticForm.IsGPRNondegenerate (Q : QuadraticForm R M) : Prop := + Q.radical = ⊥ + +/-- `Q` is **regular**: its polar form is a *bijection* `M ≃ Module.Dual R M`, not merely +injective. The strongest of `GPR 11.11`'s notions: it implies the other three (non-singularity +for `M` finitely generated projective). + +**Terminology.** Named for its source, `GPR`, since `EKM` uses "regular" for the weaker condition +`radical Q = ⊥` — see `QuadraticForm.IsEKMNondegenerate` below. -/ +def QuadraticForm.IsGPRRegular (Q : QuadraticForm R M) : Prop := + Function.Bijective (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M) + +/-- **`GPR`'s regularity is mathlib's perfect pairing**: `Q` is regular exactly when its polar form +is a `LinearMap.IsPerfPair`. The polar form is symmetric, so bijectivity in one argument already +gives it in the other. This opens mathlib's perfect-pairing API to regular forms. -/ +theorem QuadraticForm.isGPRRegular_iff_isPerfPair {Q : QuadraticForm R M} : + Q.IsGPRRegular ↔ (QuadraticMap.polarBilin Q).IsPerfPair := by + have hflip : (QuadraticMap.polarBilin Q).flip = QuadraticMap.polarBilin Q := + LinearMap.ext₂ fun x y ↦ QuadraticMap.polar_comm Q y x + refine ⟨fun h ↦ ⟨h, by rw [hflip]; exact h⟩, fun h ↦ h.1⟩ + +/-- A regular quadratic form is non-degenerate in `GPR`'s sense: its radical lies in the kernel +of the polar map, and that kernel vanishes because the polar map is injective. -/ +theorem QuadraticForm.IsGPRRegular.isGPRNondegenerate {Q : QuadraticForm R M} + (h : Q.IsGPRRegular) : Q.IsGPRNondegenerate := by + rw [QuadraticForm.IsGPRNondegenerate] + exact le_antisymm + (QuadraticMap.radical_le_ker_polarBilin.trans_eq (LinearMap.ker_eq_bot.mpr h.1)) bot_le + +/-- `Q` is **non-singular** (`GN C.8(e)`): its radical vanishes after base change to every field +extension of `R`. Uses `QuadraticForm.baseChangeOfProjective` +(`QuadraticForm/BaseChangeProjective.lean`), which needs no hypothesis on `2`. + +**Terminology.** Named for its source, `GPR`. GPR's Remark (2) following Exercise 11.37 notes that +this condition is called **non-degenerate** in `[GPR 53, §6.1 and Exercise 1.6.10]`, **ordinary** +in `[GPR 60, §XII.1]`, and **semiregular** in `[GPR 157, §IV.3]` or `[GPR 42, §2.6]`. Thus, +over a field, a reader may have met GPR's "non-singular" quadratic forms under any of those names. +Here +**non-degenerate** in that literature-synonym sense must not be confused with either +`QuadraticForm.IsGPRNondegenerate` above (the `radical Q = ⊥` rung over the base ring) or mathlib's +`LinearMap.BilinForm.Nondegenerate` (GPR's "weakly regular": an injective polar form). When `R` is +already a field, this condition coincides with `EKM`'s own "non-degenerate" — +`QuadraticForm.IsEKMNondegenerate` below. -/ +def QuadraticForm.IsGPRNonsingular [Module.Finite R M] [Module.Projective R M] + (Q : QuadraticForm R M) : Prop := + ∀ (F : Type*) [Field F] [Algebra R F], (Q.baseChangeOfProjective F).radical = ⊥ + +/-- When `2` is invertible, `radical Q = ⊥` (GPR's non-degenerate) agrees exactly with +mathlib's `polarBilin.Nondegenerate`/`SeparatingLeft` (GPR's weakly regular) — +`GN (C.8.2)`'s non-base-changed half. No base change is involved: +`2 • Q m = polar Q m m` lets `Q m = 0` be recovered from the polar form vanishing, so the +extra `Q m = 0` clause in the radical becomes redundant. That last step is mathlib's +`QuadraticMap.radical_eq_ker_polarBilin`. -/ +theorem QuadraticForm.radical_eq_bot_iff_injective_polarBilin [Invertible (2 : R)] + (Q : QuadraticForm R M) : + Q.radical = ⊥ ↔ Function.Injective (QuadraticMap.polarBilin Q) := by + rw [QuadraticMap.radical_eq_ker_polarBilin, LinearMap.ker_eq_bot] + +open scoped TensorProduct + +namespace Module.Dual + +/-- If a linear map from a finite free module into its own dual is injective after base change +to every residue field of the base ring, it is bijective. Used for the base-changed half of +`GN (C.8.2)` (`QuadraticForm.IsGPRNonsingular.isGPRRegular` below), applied after localizing at +each maximal ideal. + +The matrix of the map, computed in a chosen basis and its dual basis, has determinant that cannot +lie in any maximal ideal: its image in each residue field is the determinant of a matrix +representing an injective — hence, by a dimension count, bijective — map, so is nonzero. Hence the +determinant is a unit, and a unit-determinant map is bijective. + +**The residue field is kept abstract**, presented as any field `F` with `[Algebra S F]` whose +structure map has kernel `𝔪`, rather than as the concrete `S ⧸ 𝔪`. Only the kernel condition is +used (to see that a determinant lying in `𝔪` dies in `F`), and the proof instantiates `F` at +`S ⧸ 𝔪` internally — where `S` is still an abstract ring, so nothing expensive is formed. The +payoff is at the call site: `QuadraticForm.IsGPRNonsingular.bijective_baseChange_atPrime` below +instantiates `S` at `Localization.AtPrime 𝔪`, and the concrete form of this hypothesis would +force Lean to elaborate `Localization.AtPrime 𝔪 ⧸ 𝔫` — a quotient of a localization, whose +`CommSemiring` instance search diverges against the one under `Ideal.Quotient.field 𝔫`. With `F` +abstract that term never appears, and `IsGPRNonsingular` — which accepts *any* field carrying an +`R`-algebra structure, in particular `F` via `R → S → F` — applies directly, with no residue-field +identification needed at all. `F` shares `S`'s universe because the internal instantiation at +`S ⧸ 𝔪` lives there. -/ +theorem bijective_of_forall_residue_field_injective {S : Type s} [CommRing S] + {P : Type*} [AddCommGroup P] [Module S P] {ι : Type*} [Finite ι] + (v : Basis ι S P) {g : P →ₗ[S] Module.Dual S P} + (hinj : ∀ (𝔪 : Ideal S) [𝔪.IsMaximal] (F : Type s) [Field F] [Algebra S F], + RingHom.ker (algebraMap S F) = 𝔪 → Function.Injective (LinearMap.baseChange F g)) : + Function.Bijective g := by + -- The matrix and determinant below need `Fintype ι` and `DecidableEq ι`; neither appears in the + -- statement, so both are recovered here. + cases nonempty_fintype ι + classical + have hUnit : IsUnit (LinearMap.toMatrix v v.dualBasis g).det := by + by_contra hnot + obtain ⟨𝔪, hmax, hmem⟩ := exists_max_ideal_of_mem_nonunits (mem_nonunits_iff.mpr hnot) + have := hmax + -- `letI`, not `haveI`: `hinj` synthesizes `Field F` first and then demands an `Algebra S F` + -- built on *that* semiring structure. An opaque `haveI` blocks `Field.toSemiring` from + -- unfolding to the quotient's own `CommRing`, and `Algebra S (S ⧸ 𝔪)` then fails to + -- synthesize. + let : Field (S ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + set A : Matrix ι ι S := LinearMap.toMatrix v v.dualBasis g with hA + set B : Matrix ι ι (S ⧸ 𝔪) := A.map (algebraMap S (S ⧸ 𝔪)) with hB + have hBdet : B.det = 0 := by + rw [hB, ← RingHom.mapMatrix_apply, ← RingHom.map_det, Ideal.Quotient.algebraMap_eq, + Ideal.Quotient.eq_zero_iff_mem] + exact hmem + obtain ⟨y, hy, hBy⟩ := Matrix.exists_mulVec_eq_zero_iff.mpr hBdet + set b1 := Algebra.TensorProduct.basis (S ⧸ 𝔪) v with hb1 + set b2 := Algebra.TensorProduct.basis (S ⧸ 𝔪) v.dualBasis with hb2 + have hBeq : B = LinearMap.toMatrix b1 b2 (LinearMap.baseChange (S ⧸ 𝔪) g) := by + rw [hB, hA, LinearMap.toMatrix_baseChange] + set x : (S ⧸ 𝔪) ⊗[S] P := b1.equivFun.symm y with hx + have hrepr : ⇑(b1.repr x) = y := by + rw [hx, ← Basis.equivFun_apply, LinearEquiv.apply_symm_apply] + have hxne : x ≠ 0 := by + intro h + apply hy + have : ⇑(b1.repr x) = ⇑(b1.repr (0 : (S ⧸ 𝔪) ⊗[S] P)) := by rw [h] + rw [hrepr, map_zero] at this + simpa using this + have hz : B.toLin b1 b2 x = 0 := by + rw [Matrix.toLin_apply_eq_zero_iff] + intro j + have hj := congrFun hBy j + rwa [hrepr] + rw [hBeq, Matrix.toLin_toMatrix] at hz + have hker : RingHom.ker (algebraMap S (S ⧸ 𝔪)) = 𝔪 := by + rw [Ideal.Quotient.algebraMap_eq]; exact Ideal.mk_ker + apply hxne + apply hinj 𝔪 (S ⧸ 𝔪) hker + rw [map_zero] + exact hz + exact (LinearEquiv.ofIsUnitDet (v := v) (v' := v.dualBasis) hUnit).bijective + +end Module.Dual + +/-- A linear map between two `R`-modules is bijective if it becomes bijective after base change +to the localization at every maximal ideal of `R`. Bridges `bijective_of_localized_maximal` +(stated for the concrete `LocalizedModule` localization) to base change along +`Localization.AtPrime`, via the natural equivalence `LocalizedModule.equivTensorProduct`. -/ +theorem LinearMap.bijective_of_forall_baseChange_atPrime_bijective {R : Type*} [CommRing R] + {M N : Type*} [AddCommGroup M] [Module R M] [AddCommGroup N] [Module R N] (f : M →ₗ[R] N) + (h : ∀ (𝔪 : Ideal R) [𝔪.IsMaximal], + Function.Bijective (LinearMap.baseChange (Localization.AtPrime 𝔪) f)) : + Function.Bijective f := by + apply bijective_of_localized_maximal f + intro 𝔪 hmax + have hsq : (LocalizedModule.equivTensorProduct 𝔪.primeCompl N) ∘ + (LocalizedModule.map 𝔪.primeCompl f) = + (LinearMap.baseChange (Localization.AtPrime 𝔪) f) ∘ + (LocalizedModule.equivTensorProduct 𝔪.primeCompl M) := by + ext m + induction m using LocalizedModule.induction_on with + | _ x s => + simp [LocalizedModule.map_mk, LocalizedModule.equivTensorProduct_apply_mk, + LinearMap.baseChange_tmul] + have hbij : Function.Bijective (LinearMap.baseChange (Localization.AtPrime 𝔪) f) := h 𝔪 + have hcomp : Function.Bijective ((LocalizedModule.equivTensorProduct 𝔪.primeCompl N) ∘ + (LocalizedModule.map 𝔪.primeCompl f)) := by + rw [hsq] + exact hbij.comp (LocalizedModule.equivTensorProduct 𝔪.primeCompl M).bijective + exact (Function.Bijective.of_comp_iff' + (LocalizedModule.equivTensorProduct 𝔪.primeCompl N).bijective _).mp hcomp + +/-- The base change of a bilinear form (`LinearMap.BilinForm.baseChange`, built via +`tensorDistrib`) agrees with base-changing it as a linear map into the dual and then applying the +dual-base-change equivalence from `GPR 9.15`. Checked directly on pure tensors. -/ +theorem LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange [Module.Projective R M] + [Module.Finite R M] (A : Type*) [CommRing A] [Algebra R A] (B : LinearMap.BilinForm R M) : + LinearMap.BilinForm.baseChange A B = + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := A)).toLinearMap ∘ₗ + LinearMap.baseChange A B := by + ext a m + simp only [TensorProduct.AlgebraTensorModule.curry_apply, TensorProduct.curry_apply, + LinearMap.coe_restrictScalars, LinearMap.BilinForm.baseChange_tmul, mul_one, + LinearMap.restrictScalars_comp, LinearMap.coe_comp, LinearEquiv.coe_coe, Function.comp_apply, + LinearMap.baseChange_tmul] + have hkey := TauCeti.Module.Dual.baseChangeEvaluation_tmul (R := R) (A := A) 1 1 (B a) m + simp only [one_mul] at hkey + rw [TauCeti.Module.Dual.baseChangeEvaluationEquiv_apply, hkey, + Algebra.algebraMap_eq_smul_one] + +/-- A quadratic form on a finite projective module is regular if it becomes regular after base +change to every field over the base ring. + +This is the local-global principle for the polar map. After localizing at a maximal ideal, the +module becomes finite free. The polar map is then bijective by Nakayama's lemma because its base +change to every residue field is injective; the latter is the assumed regularity after the +corresponding composite field extension of `R`. -/ +theorem QuadraticForm.isGPRRegular_of_forall_baseChangeOfProjective_isGPRRegular + [Module.Projective R M] [Module.Finite R M] (Q : QuadraticForm R M) + (h : ∀ (F : Type u) [Field F] [Algebra R F], + (Q.baseChangeOfProjective F).IsGPRRegular) : Q.IsGPRRegular := by + apply LinearMap.bijective_of_forall_baseChange_atPrime_bijective + intro 𝔪 _ + let S := Localization.AtPrime 𝔪 + let : Module.Flat R M := Module.Flat.of_projective + let : Module.Finite S (S ⊗[R] M) := Module.Finite.base_change R S M + let : Module.Free S (S ⊗[R] M) := Module.free_of_flat_of_isLocalRing + let v : Module.Basis (Module.Free.ChooseBasisIndex S (S ⊗[R] M)) S (S ⊗[R] M) := + Module.Free.chooseBasis S (S ⊗[R] M) + let f : M →ₗ[R] Module.Dual R M := QuadraticMap.polarBilin Q + let g : (S ⊗[R] M) →ₗ[S] Module.Dual S (S ⊗[R] M) := + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := S)).toLinearMap ∘ₗ + LinearMap.baseChange S f + have hgbij : Function.Bijective g := by + apply Module.Dual.bijective_of_forall_residue_field_injective v (g := g) + intro 𝔫 _ F _ _ _ + let : Algebra R F := ((algebraMap S F).comp (algebraMap R S)).toAlgebra + have : IsScalarTower R S F := IsScalarTower.of_algebraMap_eq' rfl + have hdirect : Function.Injective (LinearMap.baseChange F f) := by + have hpolar := (h F).injective + rw [QuadraticForm.polarBilin_baseChangeOfProjective, + LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange] at hpolar + simp only [LinearMap.coe_comp] at hpolar + simpa only [f] using hpolar.of_comp + have hiter : Function.Injective + (LinearMap.baseChange F (LinearMap.baseChange S f)) := by + rw [LinearMap.baseChange_baseChange f] + exact (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F + (Module.Dual R M)).symm.injective.comp + (hdirect.comp (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F M).injective) + simp only [g, LinearMap.baseChange_comp] + have hE : Function.Injective (LinearMap.baseChange F + (TauCeti.Module.Dual.baseChangeEvaluationEquiv + (R := R) (M := M) (A := S)).toLinearMap) := by + rw [← LinearEquiv.coe_baseChange] + exact LinearEquiv.injective _ + exact hE.comp hiter + exact (Function.Bijective.of_comp_iff' + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := S)).bijective + (LinearMap.baseChange S f)).mp hgbij + +/-- **Regularity is stable under base change.** Base-changing the bijection +`polarBilin Q : M ≃ Module.Dual R M` as a plain linear map keeps it injective, and composing with +the always-bijective dual-comparison map of `GPR 9.15` +(`LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange`) identifies the result with the polar +form of the base-changed quadratic form. -/ +theorem QuadraticForm.IsGPRRegular.injective_polarBilin_baseChangeOfProjective + [Module.Projective R M] [Module.Finite R M] {Q : QuadraticForm R M} (hReg : Q.IsGPRRegular) + (A : Type*) [CommRing A] [Algebra R A] : + Function.Injective (QuadraticMap.polarBilin (Q.baseChangeOfProjective A)) := by + have hinj1 : Function.Injective (LinearMap.baseChange A (QuadraticMap.polarBilin Q)) := + ((LinearEquiv.ofBijective (QuadraticMap.polarBilin Q) hReg).baseChange + R A M (Module.Dual R M)).injective + have hinj2 : Function.Injective + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := A)).toLinearMap := + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := A)).injective + intro x y hxy + refine hinj2.comp hinj1 ?_ + rw [QuadraticForm.polarBilin_baseChangeOfProjective, + LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange] at hxy + simpa using hxy + +/-- **`GN (C.8.1)`.** `Q` regular implies `Q` non-singular: over every field the polar form of the +base change stays injective (`IsGPRRegular.injective_polarBilin_baseChangeOfProjective`), which is +exactly what a vanishing radical needs. -/ +theorem QuadraticForm.IsGPRRegular.isGPRNonsingular [Module.Projective R M] [Module.Finite R M] + {Q : QuadraticForm R M} (hReg : Q.IsGPRRegular) : Q.IsGPRNonsingular := fun F _ _ ↦ + ((Q.baseChangeOfProjective F).radical.eq_bot_iff).mpr fun _ hx ↦ + (injective_iff_map_eq_zero _).mp + (hReg.injective_polarBilin_baseChangeOfProjective F) _ hx.2 + +/-- **Non-singularity is stable under base change.** This is the whole point of quantifying over +every field in `R`-alg rather than asking for `radical Q = ⊥` over `R` itself: a field over `S` is +a field over `R`, and `QuadraticForm.baseChangeOfProjectiveIsometryEquiv` identifies the iterated +base change `(Q_S)_F` with the direct one `Q_F`, whose radical vanishes by hypothesis. + +The `Algebra R F` and `IsScalarTower R S F` instances are built inside the proof from +`Algebra R S` and `Algebra S F`; they are not available to instance search, and the whole +statement would be false-by-elaboration if `F` carried an unrelated `R`-algebra structure. -/ +theorem QuadraticForm.IsGPRNonsingular.baseChangeOfProjective [Module.Finite R M] + [Module.Projective R M] {Q : QuadraticForm R M} (hNS : Q.IsGPRNonsingular.{u, v, w}) + (S : Type s) [CommRing S] [Algebra R S] : + (Q.baseChangeOfProjective S).IsGPRNonsingular.{s, max v s, w} := by + intro F _ _ + let : Algebra R F := ((algebraMap S F).comp (algebraMap R S)).toAlgebra + have : IsScalarTower R S F := IsScalarTower.of_algebraMap_eq fun _ ↦ rfl + have he := (QuadraticForm.baseChangeOfProjectiveIsometryEquiv S F Q).map_radical + rw [hNS F, Submodule.map_eq_bot_iff] at he + exact he + +/-- If `Q` is non-singular, `polarBilin Q` stays injective after base change to any field `F` +with `Invertible (2 : F)`. The field-level half of the translation between `IsGPRNonsingular` and +injectivity of `polarBilin`, isolated at the top level (rather than nested inside +`QuadraticForm.IsGPRNonsingular.isGPRRegular`'s proof) to keep its elaboration cheap. -/ +theorem QuadraticForm.IsGPRNonsingular.injective_baseChange [Module.Finite R M] + [Module.Projective R M] {Q : QuadraticForm R M} (hNS : Q.IsGPRNonsingular.{u, v, u}) + {F : Type u} [Field F] [Algebra R F] [Invertible (2 : F)] : + Function.Injective + (LinearMap.baseChange F (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M)) := by + have hrad : (Q.baseChangeOfProjective F).radical = ⊥ := hNS F + have hpolarinj : Function.Injective (QuadraticMap.polarBilin (Q.baseChangeOfProjective F)) := + (QuadraticForm.radical_eq_bot_iff_injective_polarBilin _).mp hrad + rw [QuadraticForm.polarBilin_baseChangeOfProjective, + LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange] at hpolarinj + simp only [LinearMap.coe_comp] at hpolarinj + exact hpolarinj.of_comp + +/-- Iterating `injective_baseChange` through an intermediate ring `S`: if `Q` is non-singular, +`polarBilin Q` base-changed to `S` and then to a further `S`-algebra field `F` stays injective. +`LinearMap.baseChange_baseChange` identifies the iterated base change with the direct one to `F` +(an `R`-algebra via `R → S → F`), where `injective_baseChange` applies. + +`F` is kept fully generic (a bare `{F : Type u} [Field F] [Algebra S F] [IsScalarTower R S F]`), +rather than fixed to a concrete `S ⧸ 𝔫`: baking a concrete quotient into the statement fixes +*some* `CommSemiring F` instance for `LinearMap.baseChange` the moment the statement is +elaborated, and separately deriving `[Field F]` from `[𝔫.IsMaximal]` inside the proof gives a +second, propositionally-but-not-definitionally-equal instance — reconciling the two costs an +expensive `isDefEq` on every use of `Q.baseChangeOfProjective F`. Keeping `F` abstract sidesteps +the diamond; callers instantiate it (e.g. at `S ⧸ 𝔫`) themselves. -/ +theorem QuadraticForm.IsGPRNonsingular.injective_baseChange_baseChange [Module.Finite R M] + [Module.Projective R M] {Q : QuadraticForm R M} + (hNS : Q.IsGPRNonsingular.{u, v, u}) {S : Type u} [CommRing S] [Algebra R S] + {F : Type u} [Field F] [Algebra S F] [Algebra R F] [IsScalarTower R S F] + [Invertible (2 : F)] : + Function.Injective (LinearMap.baseChange F + (LinearMap.baseChange S (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M))) := by + set f : M →ₗ[R] Module.Dual R M := QuadraticMap.polarBilin Q with hf + have hFinj : Function.Injective (LinearMap.baseChange F f) := by + have hrad : (Q.baseChangeOfProjective F).radical = ⊥ := hNS F + have hpolarinj : Function.Injective (QuadraticMap.polarBilin (Q.baseChangeOfProjective F)) := + (QuadraticForm.radical_eq_bot_iff_injective_polarBilin _).mp hrad + rw [QuadraticForm.polarBilin_baseChangeOfProjective, + LinearMap.BilinForm.baseChange_eq_comp_dualBaseChange] at hpolarinj + simp only [LinearMap.coe_comp] at hpolarinj + exact hpolarinj.of_comp + have hbc : LinearMap.baseChange F (LinearMap.baseChange S f) = + (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F (Module.Dual R M)).symm ∘ₗ + LinearMap.baseChange F f ∘ₗ + (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F M) := + LinearMap.baseChange_baseChange f + rw [hbc] + exact (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F + (Module.Dual R M)).symm.injective.comp + (hFinj.comp (TensorProduct.AlgebraTensorModule.cancelBaseChange R S F F M).injective) + +/-- Over *any* local `R`-algebra `S`, `polarBilin Q` becomes bijective after base change: a finite +projective `M` is free after base change to a local ring (`M` projective ⇒ flat, +`Module.Flat.of_projective`; finite flat over a local ring is free, +`Module.free_of_flat_of_isLocalRing`), so +`Module.Dual.bijective_of_forall_residue_field_injective` applies to the resulting free module, +with `injective_baseChange_baseChange` supplying its hypothesis at each residue field. + +`S` is deliberately kept abstract rather than fixed to `Localization.AtPrime 𝔪` (that is +`bijective_baseChange_atPrime` below, an immediate corollary). With `S` a variable, `SMul R S` +can only be `Algebra.toSMul`, so the `IsScalarTower R S F` this proof must build for a residue +field `F` typechecks on the nose. At the concrete localization it would instead have to reconcile +`Algebra.toSMul` with `OreLocalization.instSMulOfIsScalarTower` — the same class of instance +diamond that made the earlier, localization-first version of this proof intractable. -/ +theorem QuadraticForm.IsGPRNonsingular.bijective_baseChange_of_isLocalRing [Module.Finite R M] + [Module.Projective R M] [Invertible (2 : R)] {Q : QuadraticForm R M} + (hNS : Q.IsGPRNonsingular.{u, v, u}) (S : Type u) [CommRing S] [Algebra R S] + [IsLocalRing S] : + Function.Bijective (LinearMap.baseChange S + (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M)) := by + set f : M →ₗ[R] Module.Dual R M := QuadraticMap.polarBilin Q with hf + have : Module.Flat R M := Module.Flat.of_projective + have : Module.Finite S (S ⊗[R] M) := Module.Finite.base_change R S M + have : Module.Free S (S ⊗[R] M) := Module.free_of_flat_of_isLocalRing + set v : Module.Basis (Module.Free.ChooseBasisIndex S (S ⊗[R] M)) S (S ⊗[R] M) := + Module.Free.chooseBasis S (S ⊗[R] M) with hv + set g : (S ⊗[R] M) →ₗ[S] Module.Dual S (S ⊗[R] M) := + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := S)).toLinearMap ∘ₗ + LinearMap.baseChange S f with hg + suffices hgbij : Function.Bijective g by + exact (Function.Bijective.of_comp_iff' + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := S)).bijective + (LinearMap.baseChange S f)).mp hgbij + apply Module.Dual.bijective_of_forall_residue_field_injective v (g := g) + -- `F` is an arbitrary residue field of `S`. Neither `𝔫` nor the kernel condition is used: all + -- that matters is that `F` is a field with an `R`-algebra structure, which it acquires from + -- `R → S → F`, since that is the only thing `hNS` asks of a base change. + intro 𝔫 _ F _ _ _ + let : Algebra R F := ((algebraMap S F).comp (algebraMap R S)).toAlgebra + have : IsScalarTower R S F := IsScalarTower.of_algebraMap_eq' rfl + have : Invertible (2 : F) := + (Invertible.map (algebraMap R F) (2 : R)).copy 2 (map_ofNat (algebraMap R F) 2).symm + have hE : Function.Injective (LinearMap.baseChange F + (TauCeti.Module.Dual.baseChangeEvaluationEquiv (R := R) (M := M) (A := S)).toLinearMap) := by + rw [← LinearEquiv.coe_baseChange] + exact LinearEquiv.injective _ + rw [hg, LinearMap.baseChange_comp] + simp only [LinearMap.coe_comp] + exact hE.comp hNS.injective_baseChange_baseChange + +/-- For a fixed maximal ideal `𝔪`, `polarBilin Q` becomes bijective after base change to +`Localization.AtPrime 𝔪`. Immediate from `bijective_baseChange_of_isLocalRing`, since a +localization at a prime is local. -/ +theorem QuadraticForm.IsGPRNonsingular.bijective_baseChange_atPrime [Module.Finite R M] + [Module.Projective R M] [Invertible (2 : R)] {Q : QuadraticForm R M} + (hNS : Q.IsGPRNonsingular.{u, v, u}) (𝔪 : Ideal R) [𝔪.IsMaximal] : + Function.Bijective (LinearMap.baseChange (Localization.AtPrime 𝔪) + (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M)) := + hNS.bijective_baseChange_of_isLocalRing (Localization.AtPrime 𝔪) + +/-- **`GN (C.8.2)`, converse direction.** `Q` non-singular implies `Q` regular, when `2 ∈ Rˣ`: +bundle `bijective_baseChange_atPrime` over every maximal ideal via +`LinearMap.bijective_of_forall_baseChange_atPrime_bijective`. -/ +theorem QuadraticForm.IsGPRNonsingular.isGPRRegular [Module.Finite R M] [Module.Projective R M] + [Invertible (2 : R)] {Q : QuadraticForm R M} (hNS : Q.IsGPRNonsingular.{u, v, u}) : + Q.IsGPRRegular := + LinearMap.bijective_of_forall_baseChange_atPrime_bijective (QuadraticMap.polarBilin Q) + (fun 𝔪 _ ↦ hNS.bijective_baseChange_atPrime 𝔪) + +/-- `GN (C.8.2)`, in full: for `M` finitely generated projective and `2 ∈ Rˣ`, `Q` is regular iff +`Q` is non-singular. Combines `QuadraticForm.IsGPRRegular.isGPRNonsingular` (no hypothesis on `2` +needed) with `QuadraticForm.IsGPRNonsingular.isGPRRegular` (the converse, needing `2 ∈ Rˣ`). -/ +theorem QuadraticForm.isGPRRegular_iff_isGPRNonsingular [Module.Finite R M] + [Module.Projective R M] [Invertible (2 : R)] (Q : QuadraticForm R M) : + Q.IsGPRRegular ↔ Q.IsGPRNonsingular.{u, v, u} := + ⟨QuadraticForm.IsGPRRegular.isGPRNonsingular, QuadraticForm.IsGPRNonsingular.isGPRRegular⟩ + +/-! ### The rank-one form `⟨u⟩`, and the sharpness of `2 ∈ Rˣ` + +`GN (C.8.1)` says regular implies non-singular unconditionally; `GN (C.8.2)` says the converse +holds when `2 ∈ Rˣ`. The rank-one form `⟨u⟩ : r ↦ u * r ^ 2` shows that hypothesis cannot be +dropped: for `u` a unit, `⟨u⟩` is non-singular over any commutative ring but regular exactly when +`2` is a unit. `R = ℤ`, `u = 1` is the concrete separating example. + +The two directions use genuinely different features of the definitions. Non-singularity needs only +the `Q m = 0` clause of `QuadraticMap.radical` — the clause that makes the radical smaller than the +kernel of the polar form, which is all that mathlib's `LinearMap.BilinForm.Nondegenerate` sees — +together with the absence of zero divisors in a field. Regularity, by contrast, is entirely about +the polar form `x ↦ 2 * u * x`, which is where the `2` enters. +-/ + +/-- The **rank-one form** `⟨u⟩ : r ↦ u * r ^ 2` on `R` itself. + +This is mathlib's `QuadraticMap.sq` scaled by `u`, not a new construction; the abbreviation exists +only so that `GPR`'s `⟨u⟩` has a name here. -/ +def QuadraticForm.rankOne (u : R) : QuadraticForm R R := u • QuadraticMap.sq + +@[simp] +theorem QuadraticForm.rankOne_apply (u r : R) : QuadraticForm.rankOne u r = u * r ^ 2 := by + simp [QuadraticForm.rankOne, QuadraticMap.sq, pow_two] + +/-- The polar form of `⟨u⟩` is `(x, y) ↦ 2 * u * x * y`: the factor `2` that `GN (C.8.2)` must +invert is visible here, and is the whole content of the example. -/ +@[simp] +theorem QuadraticForm.polar_rankOne (u x y : R) : + QuadraticMap.polar (QuadraticForm.rankOne u) x y = 2 * u * (x * y) := by + simp only [QuadraticMap.polar, QuadraticForm.rankOne_apply] + ring + +/-- The same computation for `polarBilin`. Not a `simp` lemma: `simp` already reaches this via +`QuadraticMap.polarBilin_apply_apply` and `QuadraticForm.polar_rankOne`. -/ +theorem QuadraticForm.polarBilin_rankOne_apply_apply (u x y : R) : + QuadraticMap.polarBilin (QuadraticForm.rankOne u) x y = 2 * u * (x * y) := + (QuadraticMap.polarBilin_apply_apply _ _ _).trans (QuadraticForm.polar_rankOne u x y) + +/-- `⟨u⟩` is regular exactly when `2 * u` is a unit. Under `Module.Dual R R ≅ R` the polar form is +multiplication by `2 * u`; surjectivity forces `2 * u * x = 1` for some `x`, and conversely an +inverse `w` of `2 * u` builds both the injectivity witness and the preimage `w * f 1` of an +arbitrary functional `f`. -/ +theorem QuadraticForm.isGPRRegular_rankOne_iff (u : R) : + (QuadraticForm.rankOne u).IsGPRRegular ↔ IsUnit (2 * u) := by + constructor + · intro h + obtain ⟨x, hx⟩ := h.surjective (LinearMap.id : Module.Dual R R) + have h1 : 2 * u * (x * 1) = 1 := by + simpa only [QuadraticForm.polarBilin_rankOne_apply_apply, LinearMap.id_coe, id_eq] + using DFunLike.congr_fun hx (1 : R) + exact IsUnit.of_mul_eq_one x (by rw [← h1]; ring) + · intro hu + obtain ⟨w, hw⟩ := hu.exists_right_inv + constructor + · rw [injective_iff_map_eq_zero] + intro x hx + have h1 : 2 * u * (x * 1) = 0 := by + simpa only [QuadraticForm.polarBilin_rankOne_apply_apply, LinearMap.zero_apply] + using DFunLike.congr_fun hx (1 : R) + calc x = 2 * u * w * x := by rw [hw, one_mul] + _ = w * (2 * u * (x * 1)) := by ring + _ = 0 := by rw [h1, mul_zero] + · intro f + refine ⟨w * f 1, LinearMap.ext fun y ↦ ?_⟩ + have hfy : f y = y * f 1 := by + conv_lhs => rw [← mul_one y, ← smul_eq_mul, map_smul] + rw [smul_eq_mul] + rw [QuadraticForm.polarBilin_rankOne_apply_apply, hfy] + calc 2 * u * (w * f 1 * y) = 2 * u * w * (y * f 1) := by ring + _ = y * f 1 := by rw [hw, one_mul] + +/-- For `u` a unit, `⟨u⟩` is regular exactly when `2 ∈ Rˣ`. -/ +theorem QuadraticForm.isGPRRegular_rankOne_iff_isUnit_two {u : R} (hu : IsUnit u) : + (QuadraticForm.rankOne u).IsGPRRegular ↔ IsUnit (2 : R) := by + rw [QuadraticForm.isGPRRegular_rankOne_iff, (Commute.all (2 : R) u).isUnit_mul_iff] + exact and_iff_left hu + +/-- For `u` a unit, `⟨u⟩` is non-singular over *every* base ring, with no hypothesis on `2`. + +Every element of `F ⊗[R] R` is `a ⊗ₜ 1`, on which the base-changed form takes the value +`u • (a * a)`. The image of `u` in `F` is a unit, so `u • (a * a) = 0` forces `a * a = 0`, hence +`a = 0` since a field has no zero divisors. Only the `Q m = 0` half of `QuadraticMap.radical` is +used; +the polar form never enters, which is exactly why no assumption on `2` is needed. -/ +theorem QuadraticForm.isGPRNonsingular_rankOne {u : R} (hu : IsUnit u) : + (QuadraticForm.rankOne u).IsGPRNonsingular := by + intro F _ _ + refine (((QuadraticForm.rankOne u).baseChangeOfProjective F).radical.eq_bot_iff).mpr + fun x hx ↦ ?_ + obtain ⟨a, rfl⟩ : ∃ a : F, x = a ⊗ₜ[R] (1 : R) := + ⟨TensorProduct.rid R F x, by + conv_lhs => rw [← (TensorProduct.rid R F).symm_apply_apply x] + rw [TensorProduct.rid_symm_apply]⟩ + have hQ := hx.1 + rw [QuadraticForm.baseChangeOfProjective_tmul, QuadraticForm.rankOne_apply, one_pow, mul_one, + Algebra.smul_def] at hQ + have ha : a = 0 := + mul_self_eq_zero.mp ((hu.map (algebraMap R F)).mul_right_eq_zero.mp hQ) + rw [ha, TensorProduct.zero_tmul] + +/-- **The separating example, half one.** Over `ℤ`, the form `⟨1⟩ : r ↦ r ^ 2` is non-singular. +Paired with `QuadraticForm.not_isGPRRegular_rankOne_one_int`, this shows `IsGPRNonsingular` is +strictly weaker than `IsGPRRegular` over a general commutative ring. -/ +theorem QuadraticForm.isGPRNonsingular_rankOne_one_int : + (QuadraticForm.rankOne (1 : ℤ)).IsGPRNonsingular := + QuadraticForm.isGPRNonsingular_rankOne isUnit_one + +/-- **The separating example, half two.** Over `ℤ`, the form `⟨1⟩ : r ↦ r ^ 2` is *not* regular, +since `2` is not a unit in `ℤ`. So the hypothesis `[Invertible (2 : R)]` in +`QuadraticForm.isGPRRegular_iff_isGPRNonsingular` is not removable. -/ +theorem QuadraticForm.not_isGPRRegular_rankOne_one_int : + ¬ (QuadraticForm.rankOne (1 : ℤ)).IsGPRRegular := by + rw [QuadraticForm.isGPRRegular_rankOne_iff] + simp [Int.isUnit_iff] + +/-! ### Rescaling by a unit + +Multiplying a quadratic form by a unit changes neither its radical nor any of the rungs of the +ladder. This is the `⟨-μ⟩ q` of the Cayley–Dickson norm `q ⊥ ⟨-μ⟩ q`, where `μ` is a unit exactly +in the theorems that need the double to be a composition algebra. -/ + +/-- Rescaling by a unit preserves non-singularity, since it does so after every base change: the +image of a unit under `algebraMap` is a unit. -/ +theorem QuadraticForm.IsGPRNonsingular.smul_of_isUnit [Module.Finite R M] [Module.Projective R M] + {c : R} (hc : IsUnit c) {Q : QuadraticForm R M} (h : Q.IsGPRNonsingular.{u, v, w}) : + QuadraticForm.IsGPRNonsingular.{u, v, w} (c • Q) := by + intro F _ _ + rw [QuadraticForm.baseChangeOfProjective_smul, + QuadraticMap.radical_smul (hc.map (algebraMap R F))] + exact h F + +/-! ### `GN (C.8.3)`: orthogonal sums + +`GN C.8(f)` records how the ladder behaves under the orthogonal sum `q₁ ⊥ q₂` — mathlib's +`QuadraticMap.prod`. Regularity is symmetric (`q₁ ⊥ q₂` is regular iff both are), but +non-singularity is not, and `(C.8.3)` is exactly the pair of implications that do hold: + + `q₁ ⊥ q₂` non-singular ⇒ `q₁` and `q₂` non-singular, + `q₁` **regular** and `q₂` non-singular ⇒ `q₁ ⊥ q₂` non-singular. + +The asymmetry is real, and visible in the radical: `rad (q₁ ⊥ q₂)` contains `rad q₁ × rad q₂` but +can be strictly larger, because `q₁ m₁ + q₂ m₂ = 0` does not force `q₁ m₁ = 0 = q₂ m₂`. Regularity +of `q₁` is what kills the first coordinate outright and lets the second-coordinate equation +collapse. -/ + +section OrthogonalSum + +variable {M₁ : Type*} [AddCommGroup M₁] [Module R M₁] + {M₂ : Type*} [AddCommGroup M₂] [Module R M₂] + +/-- `(x, 0)` lies in the radical of `Q₁ ⊥ Q₂` when `x` lies in the radical of `Q₁`. -/ +theorem QuadraticMap.inl_mem_radical_prod {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + {x : M₁} (hx : x ∈ Q₁.radical) : (x, (0 : M₂)) ∈ (Q₁.prod Q₂).radical := by + refine ⟨by simp [QuadraticMap.prod_apply, hx.1], LinearMap.ext fun y ↦ ?_⟩ + have h1 : QuadraticMap.polar Q₁ x y.1 = 0 := by + have h := DFunLike.congr_fun hx.2 y.1 + rwa [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] at h + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_prod, h1, + QuadraticMap.polar_zero_left, add_zero, LinearMap.zero_apply] + +/-- `(0, x)` lies in the radical of `Q₁ ⊥ Q₂` when `x` lies in the radical of `Q₂`. -/ +theorem QuadraticMap.inr_mem_radical_prod + {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + {x : M₂} (hx : x ∈ Q₂.radical) : ((0 : M₁), x) ∈ (Q₁.prod Q₂).radical := by + refine ⟨by simp [QuadraticMap.prod_apply, hx.1], LinearMap.ext fun y ↦ ?_⟩ + have h1 : QuadraticMap.polar Q₂ x y.2 = 0 := by + have h := DFunLike.congr_fun hx.2 y.2 + rwa [QuadraticMap.polarBilin_apply_apply, LinearMap.zero_apply] at h + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_prod, h1, + QuadraticMap.polar_zero_left, zero_add, LinearMap.zero_apply] + +/-- A vanishing radical passes to the left summand. -/ +theorem QuadraticMap.radical_eq_bot_left_of_radical_prod_eq_bot {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} (h : (Q₁.prod Q₂).radical = ⊥) : Q₁.radical = ⊥ := by + refine (Q₁.radical).eq_bot_iff.mpr fun x hx ↦ ?_ + have hmem := QuadraticMap.inl_mem_radical_prod (Q₂ := Q₂) hx + rw [h, Submodule.mem_bot, Prod.mk_eq_zero] at hmem + exact hmem.1 + +/-- A vanishing radical passes to the right summand. -/ +theorem QuadraticMap.radical_eq_bot_right_of_radical_prod_eq_bot {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} (h : (Q₁.prod Q₂).radical = ⊥) : Q₂.radical = ⊥ := by + refine (Q₂.radical).eq_bot_iff.mpr fun x hx ↦ ?_ + have hmem := QuadraticMap.inr_mem_radical_prod (Q₁ := Q₁) hx + rw [h, Submodule.mem_bot, Prod.mk_eq_zero] at hmem + exact hmem.2 + +/-- The ring-level heart of `GN (C.8.3)`: an *injective* polar form on the left summand plus a +vanishing radical on the right gives a vanishing radical on the sum. + +Injectivity on the left is what breaks the symmetry. It forces the first coordinate of a radical +vector to vanish, after which `Q₁ 0 + Q₂ x₂ = 0` really does say `Q₂ x₂ = 0`. -/ +theorem QuadraticMap.radical_prod_eq_bot {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + (h₁ : Function.Injective (QuadraticMap.polarBilin Q₁)) (h₂ : Q₂.radical = ⊥) : + (Q₁.prod Q₂).radical = ⊥ := by + refine ((Q₁.prod Q₂).radical).eq_bot_iff.mpr fun x hx ↦ ?_ + have hp1 : QuadraticMap.polarBilin Q₁ x.1 = 0 := LinearMap.ext fun y₁ ↦ by + have h := DFunLike.congr_fun hx.2 (y₁, (0 : M₂)) + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_prod, LinearMap.zero_apply, + QuadraticMap.polar_zero_right, add_zero] at h + rw [QuadraticMap.polarBilin_apply_apply, h, LinearMap.zero_apply] + have hx1 : x.1 = 0 := (injective_iff_map_eq_zero _).mp h₁ _ hp1 + have hp2 : QuadraticMap.polarBilin Q₂ x.2 = 0 := LinearMap.ext fun y₂ ↦ by + have h := DFunLike.congr_fun hx.2 ((0 : M₁), y₂) + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_prod, LinearMap.zero_apply, + QuadraticMap.polar_zero_right, zero_add] at h + rw [QuadraticMap.polarBilin_apply_apply, h, LinearMap.zero_apply] + have hQ2 : Q₂ x.2 = 0 := by + have h := hx.1 + rwa [QuadraticMap.prod_apply, hx1, QuadraticMap.map_zero, zero_add] at h + have hmem : x.2 ∈ Q₂.radical := ⟨hQ2, hp2⟩ + rw [h₂, Submodule.mem_bot] at hmem + exact Prod.ext hx1 hmem + +/-- The polar form of a precomposition is the precomposed polar form: the pointwise form of +mathlib's `QuadraticMap.polarBilin_comp`. -/ +theorem QuadraticMap.polar_comp_apply {M' : Type*} [AddCommGroup M'] [Module R M'] + (Q : QuadraticMap R M N) (f : M' →ₗ[R] M) (x y : M') : + QuadraticMap.polar (Q.comp f) x y = QuadraticMap.polar Q (f x) (f y) := by + simpa using LinearMap.congr_fun₂ (Q.polarBilin_comp f) x y + +/-- Radical membership transports along a linear equivalence: mathlib's +`QuadraticMap.IsometryEquiv.map_radical` for the isometry `Q ≅ Q ∘ e`. -/ +theorem QuadraticMap.mem_radical_comp_linearEquiv {M' : Type*} [AddCommGroup M'] [Module R M'] + (Q : QuadraticMap R M N) (e : M' ≃ₗ[R] M) {x : M'} : + x ∈ (Q.comp e.toLinearMap).radical ↔ e x ∈ Q.radical := by + rw [← (Q.isometryEquivOfCompLinearEquiv e).map_radical] + exact Submodule.mem_map_equiv (e := (Q.isometryEquivOfCompLinearEquiv e).toLinearEquiv) _ + +/-- Transporting a vanishing radical along a linear equivalence. -/ +theorem QuadraticMap.radical_comp_linearEquiv_eq_bot_iff {M' : Type*} [AddCommGroup M'] + [Module R M'] (Q : QuadraticMap R M N) (e : M' ≃ₗ[R] M) : + (Q.comp e.toLinearMap).radical = ⊥ ↔ Q.radical = ⊥ := by + rw [← (Q.isometryEquivOfCompLinearEquiv e).map_radical] + exact Submodule.map_eq_bot_iff (e := (Q.isometryEquivOfCompLinearEquiv e).toLinearEquiv) + +/-- **Base change of an orthogonal sum is the orthogonal sum of the base changes**, along the +canonical `A ⊗[R] (M₁ × M₂) ≃ (A ⊗[R] M₁) × (A ⊗[R] M₂)`. Checked on pure tensors `1 ⊗ₜ m`, +where both sides come down to `add_smul`. -/ +theorem QuadraticForm.baseChangeOfProjective_prod {A : Type*} [CommRing A] [Algebra R A] + [Module.Finite R M₁] [Module.Projective R M₁] + [Module.Finite R M₂] [Module.Projective R M₂] + (Q₁ : QuadraticForm R M₁) (Q₂ : QuadraticForm R M₂) : + QuadraticForm.baseChangeOfProjective A (Q₁.prod Q₂) = + ((Q₁.baseChangeOfProjective A).prod (Q₂.baseChangeOfProjective A)).comp + (TensorProduct.prodRight R A A M₁ M₂).toLinearMap := by + refine baseChange_ext fun m ↦ ?_ + simp only [QuadraticForm.baseChangeOfProjective_tmul, QuadraticMap.comp_apply, + LinearEquiv.coe_coe, TensorProduct.prodRight_tmul, QuadraticMap.prod_apply] + rw [add_smul] + +end OrthogonalSum + +section TransportNonsingular + +/-- **Regularity transports along a linear equivalence.** + +The polar map of `Q ∘ e` factors as `e* ∘ polarBilin Q ∘ e`, a composition of three bijections; +no finiteness, projectivity or hypothesis on `2` is involved, unlike the non-singular version +below, which has to pass through base change. -/ +theorem QuadraticForm.IsGPRRegular.comp_linearEquiv {M' : Type t₁} [AddCommGroup M'] [Module R M'] + {Q : QuadraticForm R M} (h : Q.IsGPRRegular) (e : M' ≃ₗ[R] M) : + QuadraticForm.IsGPRRegular (Q.comp e.toLinearMap) := by + have hfactor : (QuadraticMap.polarBilin (Q.comp e.toLinearMap) : + M' →ₗ[R] Module.Dual R M') = + (e.dualMap.toLinearMap ∘ₗ + (QuadraticMap.polarBilin Q : M →ₗ[R] Module.Dual R M)) ∘ₗ e.toLinearMap := by + refine LinearMap.ext fun x ↦ LinearMap.ext fun y ↦ ?_ + simp [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar, QuadraticMap.comp_apply] + rw [QuadraticForm.IsGPRRegular, hfactor] + exact (e.dualMap.bijective.comp h).comp e.bijective + +/-- Regularity is *equivalent* to regularity after precomposition with an equivalence. -/ +theorem QuadraticForm.isGPRRegular_comp_linearEquiv_iff {M' : Type t₁} [AddCommGroup M'] + [Module R M'] {Q : QuadraticForm R M} (e : M' ≃ₗ[R] M) : + QuadraticForm.IsGPRRegular (Q.comp e.toLinearMap) ↔ Q.IsGPRRegular := by + refine ⟨fun h ↦ ?_, fun h ↦ h.comp_linearEquiv e⟩ + have h2 := QuadraticForm.IsGPRRegular.comp_linearEquiv h e.symm + rwa [show (Q.comp e.toLinearMap).comp e.symm.toLinearMap = Q from + QuadraticMap.ext fun x ↦ by simp] at h2 + +/-- **Non-singularity transports along a linear equivalence.** + +Base change turns the equivalence `e : M' ≃ M` into an equivalence `F ⊗ M' ≃ F ⊗ M` +(`LinearEquiv.baseChange`), and a vanishing radical is invariant under precomposition with an +equivalence (`QuadraticMap.radical_comp_linearEquiv_eq_bot_iff`). -/ +theorem QuadraticForm.IsGPRNonsingular.comp_linearEquiv [Module.Finite R M] + [Module.Projective R M] {M' : Type t₁} [AddCommGroup M'] [Module R M'] [Module.Finite R M'] + [Module.Projective R M'] {Q : QuadraticForm R M} + (h : QuadraticForm.IsGPRNonsingular.{u, v, t₃} Q) (e : M' ≃ₗ[R] M) : + QuadraticForm.IsGPRNonsingular.{u, t₁, t₃} (Q.comp e.toLinearMap) := by + intro F _ _ + rw [QuadraticForm.baseChangeOfProjective_comp, + show LinearMap.baseChange F e.toLinearMap = (e.baseChange R F M' M).toLinearMap from rfl, + QuadraticMap.radical_comp_linearEquiv_eq_bot_iff] + exact h F + +end TransportNonsingular + +section OrthogonalSumNonsingular + +variable {M₁ : Type t₁} [AddCommGroup M₁] [Module R M₁] [Module.Finite R M₁] + [Module.Projective R M₁] + {M₂ : Type t₂} [AddCommGroup M₂] [Module R M₂] [Module.Finite R M₂] + [Module.Projective R M₂] + +/-- **`GN (C.8.3)`, first implication (left summand).** If `q₁ ⊥ q₂` is non-singular, so is `q₁`. + +Over any field, a radical vector of `(q₁)_F` gives the radical vector `(x, 0)` of `(q₁ ⊥ q₂)_F`. -/ +theorem QuadraticForm.IsGPRNonsingular.of_prod_left {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} + (h : QuadraticForm.IsGPRNonsingular.{u, max t₁ t₂, t₃} (Q₁.prod Q₂)) : + QuadraticForm.IsGPRNonsingular.{u, t₁, t₃} Q₁ := by + intro F _ _ + have hF := h F + rw [QuadraticForm.baseChangeOfProjective_prod, + QuadraticMap.radical_comp_linearEquiv_eq_bot_iff] at hF + exact QuadraticMap.radical_eq_bot_left_of_radical_prod_eq_bot hF + +/-- **`GN (C.8.3)`, first implication (right summand).** If `q₁ ⊥ q₂` is non-singular, so is +`q₂`. -/ +theorem QuadraticForm.IsGPRNonsingular.of_prod_right {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} + (h : QuadraticForm.IsGPRNonsingular.{u, max t₁ t₂, t₃} (Q₁.prod Q₂)) : + QuadraticForm.IsGPRNonsingular.{u, t₂, t₃} Q₂ := by + intro F _ _ + have hF := h F + rw [QuadraticForm.baseChangeOfProjective_prod, + QuadraticMap.radical_comp_linearEquiv_eq_bot_iff] at hF + exact QuadraticMap.radical_eq_bot_right_of_radical_prod_eq_bot hF + +/-- **`GN (C.8.3)`, second implication.** `q₁` **regular** and `q₂` non-singular imply `q₁ ⊥ q₂` +non-singular. + +Regularity of `q₁` — not merely non-singularity — is what is needed: it survives base change as +*injectivity* of the polar form (`IsGPRRegular.injective_polarBilin_baseChangeOfProjective`), and +that is exactly the hypothesis `QuadraticMap.radical_prod_eq_bot` consumes. + +The hypothesis cannot be weakened to "`q₁` non-singular". Over a field of characteristic `2` the +polar form of `⟨1⟩` vanishes identically, so `⟨1⟩` is non-singular (`isGPRNonsingular_rankOne`) +purely because `a ^ 2 = 0` forces `a = 0`; but `⟨1⟩ ⊥ ⟨1⟩` sends `(a, b)` to +`a ^ 2 + b ^ 2 = (a + b) ^ 2`, whose zero set is the line `a = b`, so the sum has a nonzero +radical. That counterexample is not formalized here. -/ +theorem QuadraticForm.IsGPRRegular.prod_isGPRNonsingular {Q₁ : QuadraticForm R M₁} + {Q₂ : QuadraticForm R M₂} (h₁ : Q₁.IsGPRRegular) + (h₂ : QuadraticForm.IsGPRNonsingular.{u, t₂, t₃} Q₂) : + QuadraticForm.IsGPRNonsingular.{u, max t₁ t₂, t₃} (Q₁.prod Q₂) := by + intro F _ _ + rw [QuadraticForm.baseChangeOfProjective_prod, QuadraticMap.radical_comp_linearEquiv_eq_bot_iff] + exact QuadraticMap.radical_prod_eq_bot + (h₁.injective_polarBilin_baseChangeOfProjective F) (h₂ F) + +end OrthogonalSumNonsingular + +/-- `Q` is **non-degenerate** in `EKM`'s sense (`EKM Definition 7.17`, condition (1) of +`Lemma 7.16`): unlike every other predicate in this file, this is only meaningful for `Q` over a +*field* `R` — `EKM` never considers quadratic forms over a general commutative ring, so there is +no ring-level analogue to state here. `Q` is `IsEKMNondegenerate` when its radical vanishes after +base change along *every* field extension `K` of `R`. + +**Terminology.** Named for its source, `EKM`, since `EKM`'s "non-degenerate" is a different, +stronger condition than `GPR`'s "non-degenerate" — see `QuadraticForm.IsGPRNondegenerate` above. +`EKM`'s own weaker condition, `radical Q = ⊥`, is what `EKM` calls "regular", and is *not* what this +predicate captures — that is `QuadraticForm.IsGPRNondegenerate`, again via the naming clash noted +there. -/ +def QuadraticForm.IsEKMNondegenerate.{w2} {F : Type u} [Field F] {V : Type v} + [AddCommGroup V] [Module F V] [Module.Finite F V] [Module.Projective F V] + (Q : QuadraticForm F V) : Prop := + QuadraticForm.IsGPRNonsingular.{u, v, w2} Q + +/-- Over a field `R`, `EKM`'s non-degenerate (`QuadraticForm.IsEKMNondegenerate`) is *literally* +the same universal statement as `GPR`'s non-singular (`QuadraticForm.IsGPRNonsingular`): both +quantify `(Q.baseChangeOfProjective K).radical = ⊥` over the same class of fields `K` with +`[Algebra R K]`. `EKM Lemma 7.16` itself — that this condition agrees with `EKM`'s other two +formulations — is `QuadraticForm.isEKMNondegenerate_iff_nondegenerate`, in +`QuadraticForm/NonsingularOverFields.lean`; this theorem only records that the definition chosen +here for `IsEKMNondegenerate` (condition (1) of the lemma) coincides on the nose with the +ring-theoretic `IsGPRNonsingular` once the ring is a field, which is `GN C.9`'s claim. -/ +theorem QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular.{w2} {F : Type u} [Field F] + {V : Type v} [AddCommGroup V] [Module F V] [Module.Finite F V] [Module.Projective F V] + (Q : QuadraticForm F V) : + QuadraticForm.IsEKMNondegenerate.{u, v, w2} Q ↔ QuadraticForm.IsGPRNonsingular.{u, v, w2} Q := + Iff.rfl + +/-! ### Regularity of orthogonal sums and of rescaled forms + +The orthogonal sum `q₁ ⊥ q₂` of `GPR 11.12` is mathlib's `QuadraticMap.prod`. -/ + +namespace QuadraticForm + +variable {R : Type*} [CommRing R] {M : Type*} [AddCommGroup M] [Module R M] + {M₁ : Type*} [AddCommGroup M₁] [Module R M₁] {M₂ : Type*} [AddCommGroup M₂] [Module R M₂] + +/-- **An orthogonal sum of regular forms is regular.** The polar map of `q₁ ⊥ q₂` sends `(x₁, x₂)` +to `(y₁, y₂) ↦ q₁(x₁, y₁) + q₂(x₂, y₂)`, so it is the product of the two polar maps followed by +the identification `M₁* × M₂* ≃ (M₁ × M₂)*`. -/ +theorem IsGPRRegular.prod {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + (h₁ : Q₁.IsGPRRegular) (h₂ : Q₂.IsGPRRegular) : IsGPRRegular (Q₁.prod Q₂) := by + refine ⟨fun x y hxy ↦ ?_, fun f ↦ ?_⟩ + · have e₁ : QuadraticMap.polarBilin Q₁ x.1 = QuadraticMap.polarBilin Q₁ y.1 := + LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hxy (z, 0) + have e₂ : QuadraticMap.polarBilin Q₂ x.2 = QuadraticMap.polarBilin Q₂ y.2 := + LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hxy (0, z) + exact Prod.ext (h₁.1 e₁) (h₂.1 e₂) + · obtain ⟨x₁, hx₁⟩ := h₁.2 (f ∘ₗ LinearMap.inl R M₁ M₂) + obtain ⟨x₂, hx₂⟩ := h₂.2 (f ∘ₗ LinearMap.inr R M₁ M₂) + refine ⟨(x₁, x₂), LinearMap.ext fun z ↦ ?_⟩ + have e₁ := LinearMap.congr_fun hx₁ z.1 + have e₂ := LinearMap.congr_fun hx₂ z.2 + simp only [QuadraticMap.polarBilin_apply_apply, LinearMap.comp_apply, LinearMap.inl_apply, + LinearMap.inr_apply] at e₁ e₂ + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar_prod, e₁, e₂, ← map_add, + Prod.mk_add_mk, add_zero, zero_add] + +/-- **The left summand of a regular orthogonal sum is regular.** A preimage of `f ∘ fst` under the +polar map of `q₁ ⊥ q₂` has first component a preimage of `f` under the polar map of `q₁`. -/ +theorem IsGPRRegular.of_prod_left {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + (h : IsGPRRegular (Q₁.prod Q₂)) : Q₁.IsGPRRegular := by + refine ⟨fun x y hxy ↦ ?_, fun f ↦ ?_⟩ + · have e : QuadraticMap.polarBilin (Q₁.prod Q₂) (x, 0) = + QuadraticMap.polarBilin (Q₁.prod Q₂) (y, 0) := + LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hxy z.1 + exact congrArg Prod.fst (h.1 e) + · obtain ⟨x, hx⟩ := h.2 (f ∘ₗ LinearMap.fst R M₁ M₂) + exact ⟨x.1, LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hx (z, 0)⟩ + +/-- **The right summand of a regular orthogonal sum is regular.** -/ +theorem IsGPRRegular.of_prod_right {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} + (h : IsGPRRegular (Q₁.prod Q₂)) : Q₂.IsGPRRegular := by + refine ⟨fun x y hxy ↦ ?_, fun f ↦ ?_⟩ + · have e : QuadraticMap.polarBilin (Q₁.prod Q₂) (0, x) = + QuadraticMap.polarBilin (Q₁.prod Q₂) (0, y) := + LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hxy z.2 + exact congrArg Prod.snd (h.1 e) + · obtain ⟨x, hx⟩ := h.2 (f ∘ₗ LinearMap.snd R M₁ M₂) + exact ⟨x.2, LinearMap.ext fun z ↦ by simpa using LinearMap.congr_fun hx (0, z)⟩ + +/-- **Regularity of an orthogonal sum** (`GN C.8(f)`): `q₁ ⊥ q₂` is regular if and only if both +`q₁` and `q₂` are. Unlike non-singularity (`GN (C.8.3)`, +`QuadraticForm.IsGPRRegular.prod_isGPRNonsingular`), regularity is symmetric in the two summands, +and needs no finiteness or projectivity. -/ +theorem isGPRRegular_prod_iff {Q₁ : QuadraticForm R M₁} {Q₂ : QuadraticForm R M₂} : + IsGPRRegular (Q₁.prod Q₂) ↔ Q₁.IsGPRRegular ∧ Q₂.IsGPRRegular := + ⟨fun h ↦ ⟨h.of_prod_left, h.of_prod_right⟩, fun h ↦ h.1.prod h.2⟩ + +/-- **A unit multiple of a regular form is regular**: the polar map of `c q` is `c` times the +polar map of `q`, and multiplication by a unit is bijective on the dual. -/ +theorem IsGPRRegular.smul_of_isUnit {c : R} (hc : IsUnit c) {Q : QuadraticForm R M} + (h : Q.IsGPRRegular) : (c • Q).IsGPRRegular := by + have hpolar (x : M) : QuadraticMap.polarBilin (c • Q) x = c • QuadraticMap.polarBilin Q x := + LinearMap.ext fun y ↦ by + simp only [QuadraticMap.polarBilin_apply_apply, LinearMap.smul_apply, smul_eq_mul, + QuadraticMap.polar, smul_apply] + ring + refine ⟨fun x y hxy ↦ h.1 ?_, fun f ↦ ?_⟩ + · rwa [hpolar, hpolar, hc.smul_left_cancel] at hxy + · obtain ⟨x, hx⟩ := h.2 ((hc.unit⁻¹ : Rˣ) • f) + refine ⟨x, ?_⟩ + rw [hpolar, hx, Units.smul_def, smul_smul, hc.mul_val_inv, one_smul] + +/-- **A regular rescaled form forces the scalar to be a unit**, as soon as the module has a +unimodular element `m`: if `f m = 1` and `x` is a preimage of `f` under the polar map of `c q`, +then `c · q(x, m) = 1`. -/ +theorem isUnit_of_isGPRRegular_smul {c : R} {Q : QuadraticForm R M} (h : (c • Q).IsGPRRegular) + {m : M} (hm : Module.IsUnimodular R m) : IsUnit c := by + obtain ⟨f, hf⟩ := Module.isUnimodular_iff.mp hm + obtain ⟨x, hx⟩ := h.2 f + refine IsUnit.of_mul_eq_one (QuadraticMap.polar Q x m) ?_ + rw [← hf, ← hx, QuadraticMap.polarBilin_apply_apply] + simp only [QuadraticMap.polar, smul_apply, smul_eq_mul] + ring + +end QuadraticForm + +/-! ### The polar radical of a quadratic map -/ + +namespace QuadraticMap + +variable {R M P : Type*} [CommRing R] [AddCommGroup M] [Module R M] [AddCommGroup P] + [Module R P] {Q : QuadraticMap R M P} + +/-- Membership in the kernel of the polar form `Q.polarBilin`: `n(z, y) = 0` for every `y`. This +kernel is `Rad(DQ)` in `GPR`'s notation, not the radical `QuadraticMap.radical Q`. -/ +theorem mem_ker_polarBilin_iff {z : M} : + z ∈ LinearMap.ker Q.polarBilin ↔ ∀ y, polar Q z y = 0 := by + simp only [LinearMap.mem_ker, LinearMap.ext_iff, polarBilin_apply_apply, LinearMap.zero_apply] + +/-- A quadratic map is additive in an argument from the kernel of its polar form. -/ +theorem map_add_of_mem_ker_polarBilin {a : M} (ha : a ∈ LinearMap.ker Q.polarBilin) (b : M) : + Q (a + b) = Q a + Q b := by + rw [QuadraticMap.map_add Q, mem_ker_polarBilin_iff.mp ha, add_zero] + +/-- If the radical of `Q` vanishes (`GPR`'s non-degeneracy), then `Q` is injective on the kernel +of its polar form. For `a, b` in that kernel with `Q a = Q b`, the difference `a - b` is in the +kernel too, and `Q (a - b) = Q a + Q b = 2 • Q a = n(a, a) = 0`, so `a - b` is in the radical. +This is the first step of `GPR 19.3`'s treatment of the polar radical. -/ +theorem injOn_ker_polarBilin (hrad : Q.radical = ⊥) : + Set.InjOn Q (LinearMap.ker Q.polarBilin) := by + intro a ha b hb hab + have hmem : a - b ∈ Q.radical := by + refine ⟨?_, LinearMap.mem_ker.mp (Submodule.sub_mem _ ha hb)⟩ + rw [sub_eq_add_neg, map_add_of_mem_ker_polarBilin ha, QuadraticMap.map_neg, ← hab, + ← two_nsmul, ← polar_self, mem_ker_polarBilin_iff.mp ha] + rwa [hrad, Submodule.mem_bot, sub_eq_zero] at hmem + +/-- **`2` kills the polar radical** of a quadratic map with vanishing radical (the assertion +`2 C⊥ = 0` of `GPR 19.3`): for `z` in the kernel of the polar form, `Q (2 • z) = 2 • n(z, z) = 0`, +so `2 • z` is in the radical. No algebra structure is involved. -/ +theorem two_smul_eq_zero_of_mem_ker_polarBilin (hrad : Q.radical = ⊥) {z : M} + (hz : z ∈ LinearMap.ker Q.polarBilin) : (2 : R) • z = 0 := by + have hmem : (2 : R) • z ∈ Q.radical := by + refine ⟨?_, LinearMap.mem_ker.mp (Submodule.smul_mem _ _ hz)⟩ + rw [QuadraticMap.map_smul, mul_smul, two_smul R (Q z), ← two_nsmul, ← polar_self, + mem_ker_polarBilin_iff.mp hz, smul_zero] + rwa [hrad, Submodule.mem_bot] at hmem + +end QuadraticMap diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Representation.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Representation.lean new file mode 100644 index 0000000000..08e051b649 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Representation.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Semilocal +public import LeanPool.CompositionAlgebrasOverRings.LGRing.Unimodular +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Polynomial +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Regularity +public import Mathlib.RingTheory.Flat.FaithfullyFlat.Basic +public import Mathlib.RingTheory.LocalRing.ResidueField.Ideal + +/-! +# The representation lemma (`GPR 11.26`, `GN Lemma C.13(a)`) + +Over an LG-ring `R`, a non-singular quadratic form `(M, q)` with `M` finitely generated projective +represents a unit — `q(M) ∩ Rˣ ≠ ∅` — if and only if `M` has **full support**. + +`GPR 11.26` states this for `q` regular; `GN C.13(a)` observes that the same proof gives the +non-singular case, which is the version formalized here (`IsGPRNonsingular`, from +`QuadraticForm/Regularity.lean`). + +## Main definitions + +* `Module.HasFullSupport R M` : `F ⊗[R] M ≠ 0` for every field `F ∈ R`-alg. This is condition (iv) + of `GPR 11.25`, the formulation the proof actually consumes. For `M` finitely generated it is + mathlib's `Module.support R M = Set.univ` (`Module.hasFullSupport_iff_support_eq_univ`). + +## Main results + +* `Module.hasFullSupport_of_isUnit_apply` : the easy direction of `GN C.13(a)`, `(ai) ⇒ (aii)`. + Needs neither the LG hypothesis nor freeness: a unit value `q m ∈ Rˣ` stays a unit in every + `F ⊗[R] M`, which is therefore nonzero. +* `QuadraticForm.exists_apply_ne_zero_of_radical_eq_bot` : over a field, a form whose radical + vanishes on a nonzero space takes a nonzero — hence invertible — value. If `q` vanished + identically its radical would be everything. +* `QuadraticForm.exists_isUnit_baseChange_of_hasFullSupport` : the **local half** of the hard + direction. For `q` non-singular and `M` of full support, `q` represents a unit over every field + `F ∈ R`-alg. This is exactly the hypothesis the LG axiom consumes. +* `QuadraticForm.exists_isUnit_apply_of_hasFullSupport` : the hard direction `(aii) ⇒ (ai)`, in + full generality, by applying the LG axiom to the polynomial of `GPR 11.8`. +* `QuadraticForm.exists_isUnit_apply_iff_hasFullSupport` : **`GPR 11.26`** / **`GN C.13(a)`**, the + two directions combined. +* `Module.exists_isUnimodular_of_hasFullSupport` : **`GN 2.6(a)`** restated for full support — a + finitely generated projective module of full support over an LG-ring contains a unimodular + element. Proved in `LGRing/Unimodular.lean`. + +## Implementation notes + +`GPR 11.8` (`QuadraticForm/Polynomial.lean`) writes a quadratic form on a *free* module as a +polynomial, and `M` is only projective, so the hard direction looks as though it needs a basis — +which is how `GPR` and `GN` proceed, reducing to the constant-rank case by the rank decomposition +(`GPR Exc. 9.31`) and then invoking constant-rank-projective ⇒ free (`GPR 11.24` = `GN 2.6(b)`). + +That route is available in this development (`Module/RankDecomposition.lean` and +`LGRing/ConstantRank.lean`), but it is not the route taken here. Choosing a presentation +`π : Rⁿ ↠ M` and pulling `q` back to `q ∘ π` on the free module `Rⁿ` is enough: the polynomial of +`GPR 11.8` then exists outright, and the residue-field hypothesis survives the pullback because +`π ⊗ k` is still surjective. So neither `GN 2.6(b)` nor the rank decomposition is needed for +`GPR 11.26`. This is the same device that proves `GN 2.6(a)` in `LGRing/Unimodular.lean`. + +The pullback is compared with base change by `QuadraticForm.baseChangeOfProjective_comp`. + +## References + +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.25, 11.26. +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, Lemma C.13(a). +-/ + +@[expose] public section + +universe u v + +open scoped TensorProduct + +/-- `M` has **full support** over `R`: base change to every field in `R`-alg is nonzero. This is +condition (iv) of `GPR 11.25`; `GPR` and `GN` also call a finitely generated projective module +with this property *faithfully projective*. -/ +def Module.HasFullSupport (R : Type u) [CommRing R] (M : Type v) [AddCommGroup M] [Module R M] : + Prop := + ∀ (F : Type u) [Field F] [Algebra R F], Nontrivial (F ⊗[R] M) + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + +/-- **Full support is mathlib's `Module.support R M = Set.univ`**, for `M` finitely generated. + +`F ⊗[R] M ≠ 0` at the residue field `κ(𝔭)` of every prime is membership of `𝔭` in the support +(`Module.mem_support_iff_nontrivial_residueField_tensorProduct`, which is where finite generation +is used). Conversely, a field `F ∈ R`-alg receives `κ(𝔭)` for `𝔭 = ker (R → F)`, and +`F ⊗[R] M = F ⊗[κ(𝔭)] (κ(𝔭) ⊗[R] M)` is nonzero because `F` is faithfully flat over the field +`κ(𝔭)`. -/ +theorem Module.hasFullSupport_iff_support_eq_univ [Module.Finite R M] : + Module.HasFullSupport R M ↔ Module.support R M = Set.univ := by + refine ⟨fun h ↦ Set.eq_univ_of_forall fun p ↦ + (Module.mem_support_iff_nontrivial_residueField_tensorProduct p).mpr + (h p.asIdeal.ResidueField), fun h F _ _ ↦ ?_⟩ + let p : PrimeSpectrum R := ⟨RingHom.ker (algebraMap R F), RingHom.ker_isPrime _⟩ + have : p.asIdeal.IsPrime := p.2 + have : Nontrivial (p.asIdeal.ResidueField ⊗[R] M) := + (Module.mem_support_iff_nontrivial_residueField_tensorProduct p).mp (h ▸ Set.mem_univ p) + let f : p.asIdeal.ResidueField →+* F := + Ideal.ResidueField.lift p.asIdeal (algebraMap R F) le_rfl fun r hr ↦ + isUnit_iff_ne_zero.mpr fun h0 ↦ hr (RingHom.mem_ker.mpr h0) + let : Algebra p.asIdeal.ResidueField F := f.toAlgebra + have : IsScalarTower R p.asIdeal.ResidueField F := + IsScalarTower.of_algebraMap_eq fun r ↦ + (Ideal.ResidueField.lift_algebraMap p.asIdeal (algebraMap R F) _ _ r).symm + exact (TensorProduct.AlgebraTensorModule.cancelBaseChange R p.asIdeal.ResidueField F F + M).symm.toEquiv.nontrivial + +/-- Full support gives the residue-field condition — condition (iv) of `GPR 11.25` implies +condition (iii). This is the form the LG axiom consumes, since `IsLGRing` quantifies over residue +fields. + +The converse also holds for `M` finitely generated projective (`GPR 11.25`), but needs the rank +function on projective modules: a field `F ∈ R`-alg has `ker (algebraMap R F)` prime, and one must +know that the rank at that prime agrees with the rank at a maximal ideal containing it. That is +not proved here. -/ +theorem Module.HasFullSupport.nontrivial_quotient_tensor (h : Module.HasFullSupport R M) + (𝔪 : Ideal R) [𝔪.IsMaximal] : Nontrivial ((R ⧸ 𝔪) ⊗[R] M) := by + let : Field (R ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + exact h (R ⧸ 𝔪) + +/-- **`GN 2.6(a)`**, in terms of full support: over an LG-ring, a finitely generated projective +module of full support contains a unimodular element. This is `IsLGRing.exists_isUnimodular` +(`LGRing/Unimodular.lean`) fed through `HasFullSupport.nontrivial_quotient_tensor`. -/ +theorem Module.exists_isUnimodular_of_hasFullSupport [Module.Finite R M] [Module.Projective R M] + (hLG : IsLGRing R) (hM : Module.HasFullSupport R M) : ∃ m : M, Module.IsUnimodular R m := + hLG.exists_isUnimodular fun 𝔪 h𝔪 ↦ haveI := h𝔪; hM.nontrivial_quotient_tensor 𝔪 + +/-- **`GN C.13(a)`, `(ai) ⇒ (aii)`.** If `q` takes an invertible value then `M` has full support. + +No LG hypothesis and no freeness: the value `q m ∈ Rˣ` maps to a unit of `F`, so +`q_F (1 ⊗ m) ≠ 0`, so `1 ⊗ m ≠ 0`. -/ +theorem Module.hasFullSupport_of_isUnit_apply [Module.Finite R M] [Module.Projective R M] + (q : QuadraticForm R M) {m : M} (hm : IsUnit (q m)) : Module.HasFullSupport R M := by + intro F _ _ + rw [← not_subsingleton_iff_nontrivial] + intro hsub + have hzero : (1 : F) ⊗ₜ[R] m = 0 := Subsingleton.elim _ _ + have hval : (q.baseChangeOfProjective F) ((1 : F) ⊗ₜ[R] m) = algebraMap R F (q m) := by + rw [QuadraticForm.baseChangeOfProjective_tmul, mul_one, Algebra.smul_def, mul_one] + rw [hzero, map_zero] at hval + exact (hm.map (algebraMap R F)).ne_zero hval.symm + +/-- Over a field, a quadratic form with vanishing radical on a nonzero space takes a nonzero +value. If it vanished identically, its polar form would too, so its radical would be all of `V`, +contradicting `radical = ⊥` on a nontrivial space. -/ +theorem QuadraticForm.exists_apply_ne_zero_of_radical_eq_bot {F : Type*} [Field F] {V : Type*} + [AddCommGroup V] [Module F V] [Nontrivial V] (q : QuadraticForm F V) + (h : q.radical = ⊥) : ∃ v : V, q v ≠ 0 := by + by_contra hcon + simp only [not_exists, not_not] at hcon + have htop : q.radical = ⊤ := by + refine eq_top_iff.mpr fun v _ ↦ ⟨hcon v, LinearMap.ext fun w ↦ ?_⟩ + rw [QuadraticMap.polarBilin_apply_apply, QuadraticMap.polar, hcon v, hcon w, hcon (v + w), + LinearMap.zero_apply, sub_zero, sub_zero] + rw [h] at htop + exact absurd htop bot_ne_top + +/-- **The local half of `GN C.13(a)`, `(aii) ⇒ (ai)`.** For `q` non-singular and `M` of full +support, `q` represents a unit over every field `F ∈ R`-alg. + +Full support makes `F ⊗[R] M` nonzero and non-singularity makes the radical of `q_F` vanish, so +`q_F` cannot be identically zero; over a field a nonzero value is a unit. + +This is precisely the hypothesis the LG axiom consumes — see the module docstring for what still +stands between this and the global statement. -/ +theorem QuadraticForm.exists_isUnit_baseChange_of_hasFullSupport [Module.Finite R M] + [Module.Projective R M] {q : QuadraticForm R M} (hq : q.IsGPRNonsingular.{u, v, u}) + (hM : Module.HasFullSupport R M) (F : Type u) [Field F] [Algebra R F] : + ∃ x : F ⊗[R] M, IsUnit ((q.baseChangeOfProjective F) x) := by + have := hM F + obtain ⟨x, hx⟩ := (q.baseChangeOfProjective F).exists_apply_ne_zero_of_radical_eq_bot (hq F) + exact ⟨x, hx.isUnit⟩ + +/-! ### The hard direction of `GN C.13(a)`, `(aii) ⇒ (ai)` -/ + +/-- **`GN C.13(a)`, `(aii) ⇒ (ai)`.** Over an LG-ring, a non-singular quadratic form on a finitely +generated projective module of full support represents a unit. + +This is the point where the LG axiom is applied. `M` need not be free, so there is no basis in +which to write `q` as a polynomial; instead choose a presentation `π : Rⁿ ↠ M` and pull `q` back +to `q' := q ∘ π` on the *free* module `Rⁿ`, where `GPR 11.8` +(`QuadraticForm.aeval_toMvPolynomial`) does apply. Then + +* `q'` represents a unit at every residue field `k`, because `q` does + (`exists_isUnit_baseChange_of_hasFullSupport`) and `π ⊗ k` is still surjective, so the witness + in `k ⊗ M` lifts to one in `k ⊗ Rⁿ` — which is free, so it can be expanded in coordinates to + give the point of `Fin n → k` the LG axiom wants; +* the axiom descends that to `t : Fin n → R` with `q' t = q (π t)` a unit. + +The comparison `(q ∘ π)_k = q_k ∘ (π ⊗ k)` is +`QuadraticForm.baseChangeOfProjective_comp`. -/ +theorem QuadraticForm.exists_isUnit_apply_of_hasFullSupport [Module.Finite R M] + [Module.Projective R M] (hLG : IsLGRing R) {q : QuadraticForm R M} + (hq : q.IsGPRNonsingular.{u, v, u}) (hM : Module.HasFullSupport R M) : + ∃ m : M, IsUnit (q m) := by + obtain ⟨n, π, hπ⟩ := Module.Finite.exists_fin' R M + set bm : Module.Basis (Fin n) R (Fin n → R) := Pi.basisFun R (Fin n) with hbm + set q' : QuadraticForm R (Fin n → R) := q.comp π with hq' + have hrep : (QuadraticForm.toMvPolynomial q' bm).RepresentsUnit R := by + refine (hLG n _).mpr fun 𝔪 _ ↦ ?_ + let : Field (R ⧸ 𝔪) := Ideal.Quotient.field 𝔪 + obtain ⟨x, hx⟩ := q.exists_isUnit_baseChange_of_hasFullSupport hq hM (R ⧸ 𝔪) + obtain ⟨y, rfl⟩ := LinearMap.baseChange_surjective (R ⧸ 𝔪) hπ x + set b' := Algebra.TensorProduct.basis (R ⧸ 𝔪) bm with hb' + refine ⟨fun i ↦ b'.repr y i, ?_⟩ + have hy : ∑ i, b'.repr y i • ((1 : R ⧸ 𝔪) ⊗ₜ[R] bm i) = y := by + simpa [hb', Algebra.TensorProduct.basis_apply] using b'.sum_repr y + rw [QuadraticForm.aeval_toMvPolynomial, hy, hq', + QuadraticForm.baseChangeOfProjective_comp, QuadraticMap.comp_apply] + exact hx + obtain ⟨t, ht⟩ := hrep + rw [QuadraticForm.aeval_toMvPolynomial_self] at ht + have hsum : ∑ i, t i • bm i = t := by + simpa [hbm] using (Pi.basisFun R (Fin n)).sum_repr t + rw [hsum, hq', QuadraticMap.comp_apply] at ht + exact ⟨π t, ht⟩ + +/-- **`GPR 11.26`, `GN Lemma C.13(a)`.** Over an LG-ring, a non-singular quadratic form on a +finitely generated projective module represents a unit if and only if the module has full +support. -/ +theorem QuadraticForm.exists_isUnit_apply_iff_hasFullSupport [Module.Finite R M] + [Module.Projective R M] (hLG : IsLGRing R) {q : QuadraticForm R M} + (hq : q.IsGPRNonsingular.{u, v, u}) : + (∃ m : M, IsUnit (q m)) ↔ Module.HasFullSupport R M := + ⟨fun ⟨_, hm⟩ ↦ Module.hasFullSupport_of_isUnit_apply q hm, + q.exists_isUnit_apply_of_hasFullSupport hLG hq⟩ diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/WittCancellation.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/WittCancellation.lean new file mode 100644 index 0000000000..1992fa8461 --- /dev/null +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/WittCancellation.lean @@ -0,0 +1,220 @@ +/- +Copyright (c) 2026 Skip Garibaldi. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Skip Garibaldi +-/ +module + +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.Cancellation +public import LeanPool.CompositionAlgebrasOverRings.QuadraticForm.PlaneTransitivity + +/-! +# Witt cancellation over LG rings (`GN 6.5`, `GPR 11.27`) + +The capstone of Layer 0. `QuadraticForm/PlaneTransitivity.lean` cancels **one** hyperbolic plane; +this file passes from there to `QuadraticForm.dualProd R N` for an arbitrary finitely generated +projective `N`, and then to `GN 6.5` by way of the reduction in `QuadraticForm/Cancellation.lean`. + +## The route + +1. `dualProd R (Fin 0 → R)` is the form on a trivial module, so it can simply be dropped + (`QuadraticMap.IsometryEquiv.prodOfSubsingletonLeft`). +2. `dualProd R R ≅ plane R` (`QuadraticForm.isometryEquivPlane`) and + `dualProd R (M × N) ≅ dualProd R M ⊥ dualProd R N` + (mathlib's `QuadraticForm.dualProdProdIsometry`). Together with + `Fin (n+1) → R ≃ₗ R × (Fin n → R)` these turn `dualProd R (Fin n → R)` into `n` planes, so + `n` applications of `QuadraticForm.isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing` + cancel it — `QuadraticForm.cancel_dualProd_fin`. +3. A finitely generated projective `N` is a direct summand of some `Rⁿ` + (`QuadraticForm.exists_linearEquiv_prod_submodule`). Adding `dualProd R N'` for a complement `N'` + to both sides of `dualProd R N ⊥ q₁ ≅ dualProd R N ⊥ q₂` turns it into the free case — + `QuadraticForm.cancel_dualProd`. Note `N'` needs no hypotheses whatever: it is only ever fed + to `dualProd`, which is defined for every module. +4. `QuadraticForm.cancel` is `GN 6.5`, obtained from `cancel_dualProd` and + `QuadraticForm.isometryEquiv_prod_dualProd_of_isometryEquiv_prod`. + +Note where the hypotheses are consumed. Non-singularity is asked of `q₂` only, since the plane +cancellation of step 2 needs the *second* summand non-singular at each stage; `GN 6.5` also lists +`q₁`, which is redundant (it follows from the others — see `QuadraticForm/Cancellation.lean`). +Regularity — as opposed to non-singularity — is used exactly once, on `q₃`, in the reduction of +step 4, and `GN`'s counterexample (see `QuadraticForm/Cancellation.lean`) shows it cannot be +dropped there. + +## References + +* [GN] Gille, Neher, *Group schemes over LG-rings and applications to cancellation theorems and + Azumaya algebras*, European Journal of Mathematics **11** (2025), article 42, 6.5. +* [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 11.27. +* I. Dias, *Formas Quadráticas Sobre LG-Anéis*, Ph.D. thesis, Universidade Estadual de Campinas, + 1988, II.6.4. +-/ + +@[expose] public section + +universe u v v₁ v₂ v₃ + +namespace QuadraticMap.IsometryEquiv + +variable {R : Type u} [CommRing R] {M₁ : Type v₁} [AddCommGroup M₁] [Module R M₁] + {M₂ : Type v₂} [AddCommGroup M₂] [Module R M₂] + +/-- A summand on a trivial module can be dropped from an orthogonal sum. -/ +noncomputable def prodOfSubsingletonLeft (Q₁ : QuadraticForm R M₁) (Q₂ : QuadraticForm R M₂) + [Subsingleton M₁] : (Q₁.prod Q₂).IsometryEquiv Q₂ where + __ := LinearEquiv.ofBijective (LinearMap.snd R M₁ M₂) + ⟨fun x y h ↦ Prod.ext (Subsingleton.elim _ _) h, fun y ↦ ⟨(0, y), rfl⟩⟩ + map_app' x := by + have h : Q₁ x.1 = 0 := by rw [Subsingleton.elim x.1 0, map_zero] + rw [QuadraticMap.prod_apply, h, zero_add] + rfl + +end QuadraticMap.IsometryEquiv + +namespace QuadraticForm + +variable {R : Type u} [CommRing R] {M : Type v} [AddCommGroup M] [Module R M] + {N : Type v₁} [AddCommGroup N] [Module R N] + +/-! ### The hyperbolic form of `Rⁿ` -/ + +/-- **`dualProd R R` is the hyperbolic plane.** Evaluation at `1` identifies `R*` with `R`. -/ +noncomputable def isometryEquivPlane : (dualProd R R).IsometryEquiv (plane R) where + __ := (LinearMap.ringLmapEquivSelf R R R).prodCongr (LinearEquiv.refl R R) + map_app' x := by + change x.1 1 * x.2 = x.1 x.2 + rw [mul_comm, ← smul_eq_mul, ← map_smul, smul_eq_mul, mul_one] + +/-- Splitting off the first coordinate: `dualProd R (Rⁿ⁺¹) ≅ plane ⊥ dualProd R (Rⁿ)`. -/ +noncomputable def isometryEquivDualProdFinSucc (R : Type u) [CommRing R] (k : ℕ) : + (dualProd R (Fin (k + 1) → R)).IsometryEquiv + ((plane R).prod (dualProd R (Fin k → R))) := + (dualProdIsometry (Fin.consLinearEquiv R (fun _ : Fin (k + 1) ↦ R)).symm).trans + ((dualProdProdIsometry (M := R) (N := Fin k → R)).trans + (QuadraticMap.IsometryEquiv.prod isometryEquivPlane (QuadraticMap.IsometryEquiv.refl _))) + +/-! ### Cancelling a hyperbolic form -/ + +variable {M₁ : Type v₁} [AddCommGroup M₁] [Module R M₁] {M₂ : Type v₂} + [AddCommGroup M₂] + [Module R M₂] + +/-- **Cancellation of `dualProd R (Rⁿ)` over an LG ring**, by induction on `n`: strip off one +plane at a time with `isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing`. + +At the `k`-th stage the form being cancelled against is `dualProd R (Rᵏ) ⊥ q₂`, non-singular by +`GN (C.8.3)` since the hyperbolic summand is *regular*; that is why the hyperbolic form is kept on +the left. Nothing is assumed about `q₁`. -/ +theorem cancel_dualProd_fin (hLG : IsLGRing R) [Module.Finite R M₂] [Module.Projective R M₂] + {q₁ : QuadraticForm R M₁} {q₂ : QuadraticForm R M₂} + (h₂ : q₂.IsGPRNonsingular.{u, v₂, u}) + (n : ℕ) (h : Nonempty (((dualProd R (Fin n → R)).prod q₁).IsometryEquiv + ((dualProd R (Fin n → R)).prod q₂))) : + Nonempty (q₁.IsometryEquiv q₂) := by + induction n with + | zero => + have : Subsingleton (Module.Dual R (Fin 0 → R)) := + ⟨fun f g ↦ LinearMap.ext fun x ↦ by rw [Subsingleton.elim x 0, map_zero, map_zero]⟩ + obtain ⟨e⟩ := h + exact ⟨(((QuadraticMap.IsometryEquiv.prodOfSubsingletonLeft _ q₁).symm.trans e).trans + (QuadraticMap.IsometryEquiv.prodOfSubsingletonLeft _ q₂))⟩ + | succ k ih => + obtain ⟨e⟩ := h + set Hk := dualProd R (Fin k → R) with hHk + -- reassociate `H(Rᵏ⁺¹) ⊥ q` as `plane ⊥ (H(Rᵏ) ⊥ q)` + let step₁ : (((plane R).prod (Hk.prod q₁))).IsometryEquiv + (((dualProd R (Fin (k + 1) → R)).prod q₁)) := + (QuadraticMap.IsometryEquiv.prodAssoc (plane R) Hk q₁).symm.trans + (QuadraticMap.IsometryEquiv.prod (isometryEquivDualProdFinSucc R k).symm + (QuadraticMap.IsometryEquiv.refl q₁)) + let step₂ : (((plane R).prod (Hk.prod q₂))).IsometryEquiv + (((dualProd R (Fin (k + 1) → R)).prod q₂)) := + (QuadraticMap.IsometryEquiv.prodAssoc (plane R) Hk q₂).symm.trans + (QuadraticMap.IsometryEquiv.prod (isometryEquivDualProdFinSucc R k).symm + (QuadraticMap.IsometryEquiv.refl q₂)) + have e' : ((plane R).prod (Hk.prod q₁)).IsometryEquiv ((plane R).prod (Hk.prod q₂)) := + (step₁.trans e).trans step₂.symm + refine ih (isometryEquiv_of_isometryEquiv_plane_prod_of_isLGRing + (q₁ := Hk.prod q₁) (q₂ := Hk.prod q₂) hLG ?_ ⟨e'⟩) + exact (isGPRRegular_dualProd R (Fin k → R)).prod_isGPRNonsingular h₂ + +/-- **A finitely generated projective module is a direct summand of `Rⁿ`.** The complement is +produced as a submodule of `Rⁿ`, so that no auxiliary type has to be introduced. -/ +theorem exists_linearEquiv_prod_submodule (N : Type v₁) [AddCommGroup N] [Module R N] + [Module.Finite R N] [Module.Projective R N] : + ∃ (n : ℕ) (N' : Submodule R (Fin n → R)), + Nonempty ((N × N') ≃ₗ[R] (Fin n → R)) := by + obtain ⟨n, π, hπ⟩ := Module.Finite.exists_fin' R N + obtain ⟨i, hi⟩ := Module.projective_lifting_property π LinearMap.id hπ + have hsec : ∀ x : N, π (i x) = x := fun x ↦ DFunLike.congr_fun hi x + have hinj : Function.Injective i := fun a b hab ↦ by rw [← hsec a, ← hsec b, hab] + set p : (Fin n → R) →ₗ[R] LinearMap.range i := + (i.comp π).codRestrict (LinearMap.range i) + (fun x ↦ LinearMap.mem_range_self i (π x)) with hp + have hproj : ∀ y : LinearMap.range i, p y = y := by + rintro ⟨-, z, rfl⟩ + exact Subtype.ext (congrArg i (hsec z)) + refine ⟨n, LinearMap.ker p, ⟨?_⟩⟩ + exact ((LinearEquiv.ofInjective i hinj).prodCongr (LinearEquiv.refl R (LinearMap.ker p))).trans + (Submodule.prodEquivOfIsCompl _ _ (LinearMap.isCompl_of_proj hproj)) + +/-- **Cancellation of a hyperbolic form over an LG ring.** For `N` finitely generated projective +and `q₂` non-singular, `dualProd R N ⊥ q₁ ≅ dualProd R N ⊥ q₂` implies `q₁ ≅ q₂`. + +Choose a complement `N'` with `N × N' ≅ Rⁿ` and add `dualProd R N'` to both sides: since +`dualProd R (N × N') ≅ dualProd R N ⊥ dualProd R N'`, this turns the hypothesis into one +about `dualProd R (Rⁿ)`, which `cancel_dualProd_fin` handles. `N'` carries no hypotheses — +it is only ever fed to `dualProd`, which every module has. -/ +theorem cancel_dualProd (hLG : IsLGRing R) {N : Type v₃} [AddCommGroup N] [Module R N] + [Module.Finite R N] [Module.Projective R N] [Module.Finite R M₂] [Module.Projective R M₂] + {q₁ : QuadraticForm R M₁} {q₂ : QuadraticForm R M₂} + (h₂ : q₂.IsGPRNonsingular.{u, v₂, u}) + (h : Nonempty (((dualProd R N).prod q₁).IsometryEquiv ((dualProd R N).prod q₂))) : + Nonempty (q₁.IsometryEquiv q₂) := by + obtain ⟨n, N', ⟨eN⟩⟩ := exists_linearEquiv_prod_submodule (R := R) N + obtain ⟨e⟩ := h + -- `H(Rⁿ) ⊥ q ≅ H(N') ⊥ (H(N) ⊥ q)`, so `e` can be applied inside + let swap₁ : ((dualProd R (Fin n → R)).prod q₁).IsometryEquiv + ((dualProd R N').prod ((dualProd R N).prod q₁)) := + ((QuadraticMap.IsometryEquiv.prod (dualProdIsometry eN.symm) + (QuadraticMap.IsometryEquiv.refl q₁)).trans + ((QuadraticMap.IsometryEquiv.prod (dualProdProdIsometry (M := N) (N := N')) + (QuadraticMap.IsometryEquiv.refl q₁)).trans + ((QuadraticMap.IsometryEquiv.prod (QuadraticMap.IsometryEquiv.prodComm _ _) + (QuadraticMap.IsometryEquiv.refl q₁)).trans + (QuadraticMap.IsometryEquiv.prodAssoc _ _ _)))) + let swap₂ : ((dualProd R (Fin n → R)).prod q₂).IsometryEquiv + ((dualProd R N').prod ((dualProd R N).prod q₂)) := + ((QuadraticMap.IsometryEquiv.prod (dualProdIsometry eN.symm) + (QuadraticMap.IsometryEquiv.refl q₂)).trans + ((QuadraticMap.IsometryEquiv.prod (dualProdProdIsometry (M := N) (N := N')) + (QuadraticMap.IsometryEquiv.refl q₂)).trans + ((QuadraticMap.IsometryEquiv.prod (QuadraticMap.IsometryEquiv.prodComm _ _) + (QuadraticMap.IsometryEquiv.refl q₂)).trans + (QuadraticMap.IsometryEquiv.prodAssoc _ _ _)))) + refine cancel_dualProd_fin hLG h₂ n ⟨swap₁.trans (((QuadraticMap.IsometryEquiv.prod + (QuadraticMap.IsometryEquiv.refl (dualProd R N')) e)).trans swap₂.symm)⟩ + +/-- **Witt cancellation over an LG ring** (`GN 6.5`; cf. `GPR 11.27`). If `q₃` is **regular** and +`q₂` is non-singular, then `q₁ ⊥ q₃ ≅ q₂ ⊥ q₃` implies `q₁ ≅ q₂`. + +Adding `-q₃` turns `q₃` into a hyperbolic form +(`QuadraticForm.isometryEquiv_prod_dualProd_of_isometryEquiv_prod`), which `cancel_dualProd` +cancels. Regularity of `q₃` is consumed in that first step and nowhere else; it cannot be weakened +to non-singularity (`EKM`, p. 49 — see `QuadraticForm/Cancellation.lean`). + +`GN` also lists `q₁` non-singular. It is not carried here because it is implied: `q₂ ⊥ q₃` is +non-singular, hence so is `q₁ ⊥ q₃`, hence so is `q₁` +(`QuadraticForm.IsGPRNonsingular.of_prod_left`). -/ +theorem cancel (hLG : IsLGRing R) {M₃ : Type v₃} [AddCommGroup M₃] [Module R M₃] + [Module.Finite R M₃] [Module.Projective R M₃] + [Module.Finite R M₂] [Module.Projective R M₂] + {q₁ : QuadraticForm R M₁} {q₂ : QuadraticForm R M₂} {q₃ : QuadraticForm R M₃} + (h₂ : q₂.IsGPRNonsingular.{u, v₂, u}) (h₃ : q₃.IsGPRRegular) + (h : Nonempty ((q₁.prod q₃).IsometryEquiv (q₂.prod q₃))) : + Nonempty (q₁.IsometryEquiv q₂) := by + obtain ⟨e⟩ := isometryEquiv_prod_dualProd_of_isometryEquiv_prod h₃ h + exact cancel_dualProd hLG h₂ + ⟨((QuadraticMap.IsometryEquiv.prodComm _ _).trans e).trans + (QuadraticMap.IsometryEquiv.prodComm _ _)⟩ + +end QuadraticForm diff --git a/LeanPool/projects/composition-algebras-over-rings.yaml b/LeanPool/projects/composition-algebras-over-rings.yaml new file mode 100644 index 0000000000..fbd01dd4bf --- /dev/null +++ b/LeanPool/projects/composition-algebras-over-rings.yaml @@ -0,0 +1,67 @@ +slug: composition-algebras-over-rings +title: Composition Algebras over Commutative Rings +summary: 'Develops the theory of composition algebras over an arbitrary commutative + ring, following Garibaldi, Petersson and Racine: conic algebras, Cayley--Dickson + doubling, and composition algebras, which are shown to be alternative over every + base and to have constant rank 1, 2, 4 or 8. Over LG rings, a class containing all + fields and semilocal rings, composition algebras are classified by their norms, and + reduced composition algebras are shown to be split. Along the way the project proves + Witt cancellation for quadratic forms over LG rings by the elementary + Dias--Baeza--Knebusch route, Artin''s theorem that a ring is alternative if and only + if its two-generated subrings are associative, freeness of constant-rank projective + modules over LG rings, and the classification of composition algebras over the reals + and over finite fields. Nothing assumes that 2 is invertible.' +branch: nonassociative algebra +entry_module: LeanPool.CompositionAlgebrasOverRings +authors: +- Skip Garibaldi +source: + title: Albert Algebras over Commutative Rings + authors: + - Skip Garibaldi + - Holger P. Petersson + - Michel L. Racine + doi: 10.1017/9781009426862 + github_repo: skipgaribaldi/CompositionAlgebras-lean + commit: 87b1eeb4f9146c65ebe664a98a012819a970af95 +license: Apache-2.0 +status: verified +provenance: AI +main_declarations: +- ConicAlgebra.IsComposition.rankAtStalk_classification +- QuadraticForm.cancel +main_results: +- declaration: QuadraticForm.cancel + informal: Witt cancellation over an LG ring. If the orthogonal sums of q1 and of q2 + with q3 are isometric, where q2 is nonsingular and q3 is regular on finitely generated + projective modules, then q1 and q2 are isometric. +- declaration: IsAlternative.isAlternative_iff_two_generated_assoc + informal: Artin's theorem. A non-associative ring is alternative if and only if every + subring generated by two elements is associative. +- declaration: Module.free_of_isLGRing_of_rankAtStalk_eq + informal: Over an LG ring, a finitely generated projective module of constant rank + is free. +- declaration: ConicAlgebra.IsComposition.isAlternative_general + informal: Every composition algebra over every commutative ring is alternative, with + no hypothesis on 2, on the rank, or on nontriviality of the base ring. +- declaration: ConicAlgebra.IsComposition.rankAtStalk_classification + informal: A composition algebra of constant rank over a nontrivial commutative ring + has rank 1, 2, 4 or 8; it is the base ring in rank 1, commutative and associative + in rank 2, associative but not commutative in rank 4, and alternative but not + associative in rank 8. +- declaration: ConicAlgebra.IsComposition.exists_isometryEquiv_map_one_map_mul + informal: Over an LG ring, composition algebras with isometric norms are isomorphic. +- declaration: ConicAlgebra.IsReduced.isSplit_of_isLGRing + informal: Over an LG ring, every reduced composition algebra is split. +tags: +- nonassociative-algebra +- composition-algebras +- octonions +- quadratic-forms +- lg-rings +msc: +- 17A75 +- 17D05 +- 11E81 +- 11E08 +- 13C10 From 278ccd8758fe99ffdafa036b56cc286bcc994076 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Sat, 17 Oct 2026 00:14:03 +0000 Subject: [PATCH 2/6] Clarify constant-rank and finite-projective scope in composition algebra card --- .../composition-algebras-over-rings.yaml | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/LeanPool/projects/composition-algebras-over-rings.yaml b/LeanPool/projects/composition-algebras-over-rings.yaml index fbd01dd4bf..54e62864bd 100644 --- a/LeanPool/projects/composition-algebras-over-rings.yaml +++ b/LeanPool/projects/composition-algebras-over-rings.yaml @@ -1,16 +1,17 @@ slug: composition-algebras-over-rings title: Composition Algebras over Commutative Rings -summary: 'Develops the theory of composition algebras over an arbitrary commutative - ring, following Garibaldi, Petersson and Racine: conic algebras, Cayley--Dickson - doubling, and composition algebras, which are shown to be alternative over every - base and to have constant rank 1, 2, 4 or 8. Over LG rings, a class containing all - fields and semilocal rings, composition algebras are classified by their norms, and - reduced composition algebras are shown to be split. Along the way the project proves - Witt cancellation for quadratic forms over LG rings by the elementary - Dias--Baeza--Knebusch route, Artin''s theorem that a ring is alternative if and only - if its two-generated subrings are associative, freeness of constant-rank projective - modules over LG rings, and the classification of composition algebras over the reals - and over finite fields. Nothing assumes that 2 is invertible.' +summary: 'Develops conic algebras, Cayley--Dickson doubling, and finitely generated projective + composition algebras over an arbitrary commutative ring, following Garibaldi, + Petersson and Racine. Composition algebras are alternative over every base. Over a + nontrivial base, if the underlying module has constant rank, that rank is 1, 2, 4 or + 8. Over LG rings, a class containing all fields and semilocal rings, composition + algebras are classified by their norms, and reduced composition algebras are shown + to be split. Along the way the project proves Witt cancellation for quadratic forms + over LG rings by the elementary Dias--Baeza--Knebusch route, Artin''s theorem that a + ring is alternative if and only if its two-generated subrings are associative, + freeness of constant-rank projective modules over LG rings, and the classification + of composition algebras over the reals and over finite fields. Nothing assumes that + 2 is invertible.' branch: nonassociative algebra entry_module: LeanPool.CompositionAlgebrasOverRings authors: From 73c23ad048193c145bcc811e65ee6596fa707f5d Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Sat, 17 Oct 2026 00:17:15 +0000 Subject: [PATCH 3/6] Scope the characteristic-free claim to the listed main results --- LeanPool/projects/composition-algebras-over-rings.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeanPool/projects/composition-algebras-over-rings.yaml b/LeanPool/projects/composition-algebras-over-rings.yaml index 54e62864bd..9f11736cce 100644 --- a/LeanPool/projects/composition-algebras-over-rings.yaml +++ b/LeanPool/projects/composition-algebras-over-rings.yaml @@ -10,8 +10,8 @@ summary: 'Develops conic algebras, Cayley--Dickson doubling, and finitely genera over LG rings by the elementary Dias--Baeza--Knebusch route, Artin''s theorem that a ring is alternative if and only if its two-generated subrings are associative, freeness of constant-rank projective modules over LG rings, and the classification - of composition algebras over the reals and over finite fields. Nothing assumes that - 2 is invertible.' + of composition algebras over the reals and over finite fields. These main results do + not assume that 2 is invertible.' branch: nonassociative algebra entry_module: LeanPool.CompositionAlgebrasOverRings authors: From 91949006743f44f1f1b451076fed7c9d20cb7e7b Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Sat, 17 Oct 2026 01:15:39 +0000 Subject: [PATCH 4/6] Fix audit universe spelling and align source references Preserve the explicit-universe interfaces while allowing the unchanged axiom-name audit to resolve three declarations. Correct Cayley-Dickson, norm-associativity, and invertible-module documentation against the cited primary statements. No theorem statement or proof is changed. --- .../Composition/Defs.lean | 10 +++++-- .../Composition/Reduced/Defs.lean | 3 +- .../Conic/CayleyDicksonAssociative.lean | 30 +++++++++---------- .../Conic/CayleyDicksonMultiplicative.lean | 11 +++---- .../Conic/Kirmse.lean | 2 +- .../Conic/Multiplicative.lean | 5 ++-- .../Module/Invertible.lean | 3 +- .../QuadraticForm/Regularity.lean | 6 ++-- 8 files changed, 40 insertions(+), 30 deletions(-) diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean index b8fae174e8..928c476a5b 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Defs.lean @@ -84,6 +84,8 @@ namespace ConicAlgebra variable {k : Type u} {A : Type v} [CommRing k] [NonAssocRing A] [Module k A] [SMulCommClass k A A] [IsScalarTower k A A] [Module.Finite k A] [Module.Projective k A] +universe w' + /-- **`GPR 19.5`: `C` is a composition algebra.** A conic algebra whose underlying module is finitely generated projective (an instance argument, not a field) and whose norm is non-singular in `GPR`'s sense and multiplicative. @@ -97,7 +99,7 @@ base-change-stable vanishing of the radical (`GN C.8(e)`), which is what makes c stable under base change. It is strictly weaker than `QuadraticForm.IsGPRRegular` unless `2 ∈ kˣ` (`QuadraticForm.isGPRRegular_iff_isGPRNonsingular`), and it is not mathlib's `LinearMap.BilinForm.Nondegenerate`; see overview §6(b). -/ -structure IsComposition.{w'} (C : ConicAlgebra k A) : Prop where +structure IsComposition (C : ConicAlgebra k A) : Prop where /-- The norm is non-singular in `GPR`'s sense (`GN C.8(e)`): its radical vanishes after base change to every field. -/ isGPRNonsingular : QuadraticForm.IsGPRNonsingular.{u, v, w'} C.norm @@ -114,13 +116,15 @@ theorem norm_mul (h : C.IsComposition.{u, v, w}) (x y : A) : h.isMultiplicative.norm_mul x y omit [SMulCommClass k A A] in -/-- **Norm-associativity** of a composition algebra (`GPR 16.5`): `n(xy, z) = n(y, (conj x)z)`. -/ +/-- **Norm-associativity** of a composition algebra (`GPR 16.12(4)` and `17.2(a)`): +`n(xy, z) = n(y, (conj x)z)`. -/ theorem polar_mul_left (h : C.IsComposition.{u, v, w}) (x y z : A) : QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm y (C.conj x * z) := h.isMultiplicative.polar_mul_left x y z omit [IsScalarTower k A A] in -/-- **Norm-associativity** of a composition algebra (`GPR 16.5`): `n(xy, z) = n(x, z(conj y))`. -/ +/-- **Norm-associativity** of a composition algebra (`GPR 16.12(3)` and `17.2(a)`): +`n(xy, z) = n(x, z(conj y))`. -/ theorem polar_mul_right (h : C.IsComposition.{u, v, w}) (x y z : A) : QuadraticMap.polar C.norm (x * y) z = QuadraticMap.polar C.norm x (z * C.conj y) := h.isMultiplicative.polar_mul_right x y z diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean index 41aadb5bc5..a30856eebf 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Defs.lean @@ -308,7 +308,8 @@ produces an elementary idempotent. Given a unimodular null `u`, unimodularity gives a functional `l` with `l(u) = 1`; precomposing with the conjugation and inverting the polar map produces `v` with `n(v, conj u) = 1`. -Norm-associativity (`GPR 16.5`) turns that into `t(uv) = 1`, while multiplicativity gives +Norm-associativity (`GPR 16.12(3–4)` and `17.2(a)`) turns that into `t(uv) = 1`, while +multiplicativity gives `n(uv) = n(u) n(v) = 0`. So `c = uv` is elementary. -/ theorem exists_isElementaryIdempotent_of_isGPRIsotropic {C : ConicAlgebra k A} (hreg : C.norm.IsGPRRegular) (hmul : C.IsMultiplicative) diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean index f124709da6..c828cf9e96 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonAssociative.lean @@ -11,20 +11,20 @@ public import LeanPool.CompositionAlgebrasOverRings.Conic.CayleyDickson # Commutativity and associativity of the double (`GPR 18.14(a),(b)`) `Cay(B, μ)` is associative **if and only if** `B` is commutative and associative with involutive -conjugation (`GPR 18.14(b)`), and commutative **if and only if** `B` is the base ring -(`GPR 18.14(a)`). This file proves the directions that build algebras, and packages them as `Ring`, -`CommRing` and `Algebra` structures on the double so that the Cayley–Dickson tower can be iterated. +conjugation (`GPR 18.14(b)`), and commutative **if and only if** `B` is commutative with trivial +conjugation (`GPR 18.14(a)`). This file proves the directions that build algebras, and packages them +as `Ring`, `CommRing` and `Algebra` structures on the double so that the Cayley–Dickson tower can +be iterated. -The two results play different roles. Associativity of `Cay(B, μ)` is what -`ConicAlgebra.isMultiplicative_cay` and `ConicAlgebra.isAlternative_cay` need of *their* input, so -it is what carries the tower from one rung to the next. Commutativity is needed only once, to get -the tower started: `mul_assoc_cay` asks its input to be commutative, and the first double -`Cay(k, μ)` is the last rung for which that is true. +Associativity of `Cay(B, μ)` supplies the associative input needed for a further application of +`ConicAlgebra.isMultiplicative_cay` or `ConicAlgebra.isAlternative_cay`. To prove that a double is +associative, `mul_assoc_cay` asks its input to be commutative. The base ring starts this process, +but it is not the only possible commutative input: in characteristic two, iterated doubles with +trivial conjugation can remain commutative (`GPR 18.17(b)`). -Iteration is the whole point. `ConicAlgebra.isMultiplicative_cay` (`GPR 18.15`) and -`ConicAlgebra.isAlternative_cay` (`GPR 18.14(c)`) both require their input `B` to be *associative*, -which for a double `Cay(B₀, μ₀)` is exactly what this file supplies. Without it the tower stops one -rung up from the base ring. +For iteration, `ConicAlgebra.isMultiplicative_cay` (the associative special case of +`GPR Exc. 18.18`) and `ConicAlgebra.isAlternative_cay` (`GPR 18.14(c)`) both require their input +`B` to be *associative*, which for a double `Cay(B₀, μ₀)` is what this file supplies. ## The computation @@ -161,9 +161,9 @@ end Failure /-- If the conjugation of a commutative `B` is the **identity** then `Cay(B, μ)` is commutative. Both products come out as `(ac + μ db, da + bc)`; only commutativity of `B` is used, since with -`conj = id` there is nothing left for the conjugation to do. The hypothesis holds for the base ring -(`ConicAlgebra.baseRing_conj_apply`) and essentially only there — `GPR 18.14(a)` says -`Cay(B, μ)` is commutative exactly when `B = k`. -/ +`conj = id` there is nothing left for the conjugation to do. The base ring satisfies the hypothesis +(`ConicAlgebra.baseRing_conj_apply`). More generally, `GPR 18.14(a)` characterizes commutativity of +`Cay(B, μ)` by commutativity of `B` with trivial conjugation. -/ theorem mul_comm_cay (hconj : ∀ u : B, C.conj u = u) (x y : Cay C μ) : x * y = y * x := by refine Cay.ext ?_ ?_ <;> simp only [Cay.fst_mul, Cay.snd_mul, hconj, Algebra.smul_def] <;> ring diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean index ab3cf6c94d..3d49bce06b 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean @@ -11,10 +11,11 @@ public import LeanPool.CompositionAlgebrasOverRings.Conic.Multiplicative /-! # The double of an associative multiplicative conic algebra is multiplicative (`GPR Exc. 18.18`) -`Cay(B, μ)` has a multiplicative norm **if and only if** `B` is associative with a multiplicative -norm (`GPR Exc. 18.18`). This file proves the direction that builds algebras: it is what carries -`n(xy) = n(x)n(y)` up the tower `k → k[√·] → ℍ → 𝕆`, and — since `𝕆` is *not* associative — it is -also where the tower stops, which is the content of the sedenion non-example (`GPR 19.23`, +If `B` is associative with a multiplicative norm, then `Cay(B, μ)` has a multiplicative norm. +This is the associative special case of `GPR Exc. 18.18`: for multiplicative `B`, the sharp +criterion is `μ[B, B, B] ⊆ Rad(Dn_B)`, which is not proved here. In particular, `μ = 0` does not +require associativity. The sufficient case proved here carries `n(xy) = n(x)n(y)` up the usual +tower `k → k[√·] → ℍ → 𝕆`. The sedenion non-example is treated separately (`GPR 19.23`, Layer 8). ## The computation @@ -41,7 +42,7 @@ underlying `B`. ## Main results -* `ConicAlgebra.isMultiplicative_cay` : **`GPR Exc. 18.18`**, the direction `⇐`. +* `ConicAlgebra.isMultiplicative_cay` : the associative special case of **`GPR Exc. 18.18`**. ## References diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean index 421a41f561..0cc6474e26 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Kirmse.lean @@ -88,7 +88,7 @@ regularity where the rank exceeds one, and commutativity and associativity outri ## References * [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, 19.3 (composition - algebras are alternative), 16.5 (norm-associativity). + algebras are alternative), 16.12(3–4) and 17.2(a) (norm-associativity). -/ @[expose] public section diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean index c334059d21..59000229cb 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/Multiplicative.lean @@ -190,7 +190,7 @@ theorem polar_mul_add_polar_mul (h : C.IsMultiplicative) (x y z w : A) : QuadraticForm.polar_mul_add_polar_mul_of_map_mul h x y z w omit [SMulCommClass k A A] in -/-- **Norm-associativity** (`GPR 16.5`, and the reason multiplicativity is so rigid): +/-- **Norm-associativity** (`GPR 16.12(4)`, obtained from multiplicativity by `GPR 17.2(a)`): `n(xy, z) = n(y, (conj x)z)`. The left factor may be moved across the polar form at the cost of conjugating it. Specialize the @@ -204,7 +204,8 @@ theorem polar_mul_left (h : C.IsMultiplicative) (x y z : A) : linear_combination key omit [IsScalarTower k A A] in -/-- **Norm-associativity**, the other side (`GPR 16.5`): `n(xy, z) = n(x, z(conj y))`. +/-- **Norm-associativity**, the other side (`GPR 16.12(3)` and `17.2(a)`): +`n(xy, z) = n(x, z(conj y))`. Not a consequence of `ConicAlgebra.IsMultiplicative.polar_mul_left` — `A` is not assumed associative or commutative — but proved the same way, specializing the second linearization at diff --git a/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean b/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean index cca419791c..0d51ee3545 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Module/Invertible.lean @@ -46,6 +46,7 @@ definition of `Module.Invertible`. ## References * [Stacks, Tag 00NX] The Stacks Project, *Finite projective modules*. +* [Stacks, Tag 0B8I] The Stacks Project, *Invertible modules*. -/ @[expose] public section @@ -288,7 +289,7 @@ private theorem invertible_of_finite_projective_of_rankAtStalk_eq_one /-- An `R`-module is invertible if and only if it is finite locally free of rank one. This is the module-theoretic characterization of line bundles; see -[Stacks, Tag 00NX](https://stacks.math.columbia.edu/tag/00NX). -/ +[Stacks, Tag 0B8I](https://stacks.math.columbia.edu/tag/0B8I). -/ theorem invertible_iff_isLocallyFreeRankOne : Module.Invertible R M ↔ IsLocallyFreeRankOne R M := by constructor diff --git a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean index 79484280ee..a233059d98 100644 --- a/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean +++ b/LeanPool/CompositionAlgebrasOverRings/QuadraticForm/Regularity.lean @@ -1039,6 +1039,8 @@ theorem QuadraticForm.IsGPRRegular.prod_isGPRNonsingular {Q₁ : QuadraticForm R end OrthogonalSumNonsingular +universe w2 + /-- `Q` is **non-degenerate** in `EKM`'s sense (`EKM Definition 7.17`, condition (1) of `Lemma 7.16`): unlike every other predicate in this file, this is only meaningful for `Q` over a *field* `R` — `EKM` never considers quadratic forms over a general commutative ring, so there is @@ -1050,7 +1052,7 @@ stronger condition than `GPR`'s "non-degenerate" — see `QuadraticForm.IsGPRNon `EKM`'s own weaker condition, `radical Q = ⊥`, is what `EKM` calls "regular", and is *not* what this predicate captures — that is `QuadraticForm.IsGPRNondegenerate`, again via the naming clash noted there. -/ -def QuadraticForm.IsEKMNondegenerate.{w2} {F : Type u} [Field F] {V : Type v} +def QuadraticForm.IsEKMNondegenerate {F : Type u} [Field F] {V : Type v} [AddCommGroup V] [Module F V] [Module.Finite F V] [Module.Projective F V] (Q : QuadraticForm F V) : Prop := QuadraticForm.IsGPRNonsingular.{u, v, w2} Q @@ -1063,7 +1065,7 @@ formulations — is `QuadraticForm.isEKMNondegenerate_iff_nondegenerate`, in `QuadraticForm/NonsingularOverFields.lean`; this theorem only records that the definition chosen here for `IsEKMNondegenerate` (condition (1) of the lemma) coincides on the nose with the ring-theoretic `IsGPRNonsingular` once the ring is a field, which is `GN C.9`'s claim. -/ -theorem QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular.{w2} {F : Type u} [Field F] +theorem QuadraticForm.isEKMNondegenerate_iff_isGPRNonsingular {F : Type u} [Field F] {V : Type v} [AddCommGroup V] [Module F V] [Module.Finite F V] [Module.Projective F V] (Q : QuadraticForm F V) : QuadraticForm.IsEKMNondegenerate.{u, v, w2} Q ↔ QuadraticForm.IsGPRNonsingular.{u, v, w2} Q := From 4ec889b7d5780d035e2a96e8e760ab58528a52f9 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Sat, 17 Oct 2026 03:22:49 +0000 Subject: [PATCH 5/6] Correct Cayley-Dickson scope and reuse composition helpers --- .../Composition/Examples.lean | 9 ++-- .../Composition/Octonion.lean | 7 +-- .../Composition/Reduced/Classification.lean | 53 +------------------ .../Composition/Tower.lean | 38 ++----------- .../Conic/CayleyDicksonMultiplicative.lean | 7 +-- 5 files changed, 18 insertions(+), 96 deletions(-) diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean index 1aa4cade6f..eb1a07c9de 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Examples.lean @@ -173,8 +173,9 @@ theorem isDivision_realOctonion : IsDivision RealOctonion := `ℍ` is not commutative and `𝕆` is not associative, with explicit witnesses. These are what stop the tower: `ConicAlgebra.mul_assoc_cay` needs its input commutative, so `𝕆` gets no `Ring` structure, and `ConicAlgebra.isMultiplicative_cay` and `ConicAlgebra.isAlternative_cay` need their -input associative, so the sedenions `Cay(𝕆, μ)` get neither a multiplicative norm nor -alternativity. -/ +input associative. These sufficient results cannot be iterated from non-associative `𝕆`. +This does not imply failure of norm multiplicativity for every parameter: the criterion in +`GPR Exc. 18.18` is automatic for `μ = 0`. -/ /-- The conjugation of `ℂ` moves `i`, which is what makes `ℍ` non-commutative. -/ theorem conj_i_ne_i : (cay₂ ℝ (-1)).conj ((0, 1) : ℝ × ℝ) ≠ ((0, 1) : ℝ × ℝ) := by @@ -190,9 +191,7 @@ theorem conj_i_ne_i : (cay₂ ℝ (-1)).conj ((0, 1) : ℝ × ℝ) ≠ ((0, 1) : theorem exists_mul_ne_mul_realQuaternion : ∃ x y : RealQuaternion, x * y ≠ y * x := exists_mul_ne_mul_cay _ _ conj_i_ne_i -/-- **`𝕆` is not associative** — so the tower cannot be continued by the theorems that built -it, -and the sedenions are neither alternative nor multiplicative. -/ +/-- **`𝕆` is not associative.** -/ theorem exists_mul_mul_ne_mul_mul_realOctonion : ∃ x y z : RealOctonion, x * y * z ≠ x * (y * z) := let ⟨_, _, h⟩ := exists_mul_ne_mul_realQuaternion diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean index 50b9b64708..bdfda7d7c6 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Octonion.lean @@ -178,9 +178,10 @@ instance isAlternative_cay₈ : IsAlternative (Cay₈ k μ₁ μ₂ μ₃) := /-- **The octonion norm permits composition**, `n(xy) = n(x)n(y)` — `GPR Exc. 18.18` applied to the associative `Cay₄`. Again no hypothesis on `2` or on the `μᵢ`. -This is the last rung for which it holds: `Cay₈` is not associative, so `GPR Exc. 18.18` does not -apply -to it, and the sedenions `Cay(Cay₈, μ₄)` are not multiplicative. -/ +This is the last rung covered uniformly by the associative-input theorem used here. For a +further double, `GPR Exc. 18.18` gives the sharp criterion `μ₄[B, B, B] ⊆ Rad(Dn_B)`. +Non-associativity alone does not force failure of norm multiplicativity; the criterion is +automatic when `μ₄ = 0`. -/ theorem isMultiplicative_cay₈ : (cay₈ k μ₁ μ₂ μ₃).IsMultiplicative := isMultiplicative_cay (cay₄ k μ₁ μ₂) μ₃ (isMultiplicative_cay₄ k μ₁ μ₂) diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean index 35a1899bea..13a09a7403 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Reduced/Classification.lean @@ -330,57 +330,8 @@ omit [IsAlternative A] in /-- **`GPR 22.16`, reduced ⇒ split over an LG ring.** Each rank component has constant rank by the rank decomposition. Its base is again LG because it is an idempotent factor; ranks four and eight are therefore untwisted by freeness of constant-rank projective modules. -/ -theorem isSplit_of_isLGRing (h : C.IsReduced) (hLG : IsLGRing k) : C.IsSplit := by - let S₁ := SplitRankFactor k A 1 - let S₂ := SplitRankFactor k A 2 - let S₄ := SplitRankFactor k A 4 - let S₈ := SplitRankFactor k A 8 - have hrank₁ : Module.rankAtStalk (R := S₁) (S₁ ⊗[k] A) = fun _ ↦ 1 := - Module.rankAtStalk_quotientTensor_rankIdempotent k A 1 - have hrank₂ : Module.rankAtStalk (R := S₂) (S₂ ⊗[k] A) = fun _ ↦ 2 := - Module.rankAtStalk_quotientTensor_rankIdempotent k A 2 - have hrank₄ : Module.rankAtStalk (R := S₄) (S₄ ⊗[k] A) = fun _ ↦ 4 := - Module.rankAtStalk_quotientTensor_rankIdempotent k A 4 - have hrank₈ : Module.rankAtStalk (R := S₈) (S₈ ⊗[k] A) = fun _ ↦ 8 := - Module.rankAtStalk_quotientTensor_rankIdempotent k A 8 - have hcomp₄ := h.isComposition.baseChangeOfProjective S₄ - have hcomp₈ := h.isComposition.baseChangeOfProjective S₈ - have hone : (C.splitRankComponent 1).IsSplitOfRank 1 := by - rcases subsingleton_or_nontrivial S₁ with hS₁ | hS₁ - · let := hS₁ - exact Isomorphic.of_subsingleton - · let := hS₁ - exact isSplitOfRank_one hrank₁ - have htwo : (C.splitRankComponent 2).IsSplitOfRank 2 := by - obtain ⟨c₂, hc₂⟩ := h.hasElementaryIdempotent_splitRankComponent_two - exact hc₂.isSplitOfRank_two hrank₂ - have hfour : (C.splitRankComponent 4).IsSplitOfRank 4 := by - rcases subsingleton_or_nontrivial S₄ with hS₄ | hS₄ - · let := hS₄ - exact Isomorphic.of_subsingleton - · let := hS₄ - have hLG₄ : IsLGRing S₄ := - hLG.quotient_span_one_sub_of_isIdempotentElem - (Module.isIdempotentElem_rankIdempotent k A 4) - let hreg₄ := hcomp₄.isGPRRegular_of_rankAtStalk_ne_one hrank₄ (by omega) - let : IsAlternative (S₄ ⊗[k] A) := - hcomp₄.isMultiplicative.isAlternative hreg₄.isGPRNondegenerate - obtain ⟨c₄, hc₄⟩ := h.hasElementaryIdempotent_splitRankComponent_four - exact hc₄.isSplitOfRank_four_of_isLGRing hLG₄ hcomp₄ hrank₄ - have height : (C.splitRankComponent 8).IsSplitOfRank 8 := by - rcases subsingleton_or_nontrivial S₈ with hS₈ | hS₈ - · let := hS₈ - exact Isomorphic.of_subsingleton - · let := hS₈ - have hLG₈ : IsLGRing S₈ := - hLG.quotient_span_one_sub_of_isIdempotentElem - (Module.isIdempotentElem_rankIdempotent k A 8) - let hreg₈ := hcomp₈.isGPRRegular_of_rankAtStalk_ne_one hrank₈ (by omega) - let : IsAlternative (S₈ ⊗[k] A) := - hcomp₈.isMultiplicative.isAlternative hreg₈.isGPRNondegenerate - obtain ⟨c₈, hc₈⟩ := h.hasElementaryIdempotent_splitRankComponent_eight - exact hc₈.isSplitOfRank_eight_of_isLGRing hLG₈ hcomp₈ hrank₈ - exact ⟨h.isComposition, hone, htwo, hfour, height⟩ +theorem isSplit_of_isLGRing (h : C.IsReduced) (hLG : IsLGRing k) : C.IsSplit := + h.isSplit_of_projectiveConstantRankFree (.of_isLGRing hLG) end IsReduced diff --git a/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean b/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean index a2a79c7911..f838e296a8 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Composition/Tower.lean @@ -351,40 +351,10 @@ theorem IsComposition.exists_isGPRRegular_rankAtStalk_two_mul (hLG : IsLGRing k) obtain ⟨v, hu, hBv, hinj, -, -⟩ := h.exists_cayToAlgebra hLG hreg (hasFullSupport_polarOrthogonal_of_rankAtStalk_lt hreg hA hB hlt) obtain ⟨D, e, he⟩ := exists_subalgebra_equiv_cay hBv hu hinj - -- The norm of `D`, pulled back along `e`, is the Cayley–Dickson norm. - have hpull : (C.restrict D).norm.comp e.toLinearMap = ((C.restrict B).cay (-C.norm v)).norm := by - refine QuadraticMap.ext fun p ↦ ?_ - rw [QuadraticMap.comp_apply, LinearEquiv.coe_coe] - change C.norm ((e p : A)) = _ - rw [he p, norm_cayToAlgebra hBv h.isMultiplicative] - have : Module.Finite k D := Module.Finite.equiv e - have : Module.Projective k D := Module.Projective.of_equiv e - -- `D` is a composition algebra: `GN (C.8.3)` for the norm, restriction for multiplicativity. - have hcay : QuadraticForm.IsGPRNonsingular.{u, v, u} - ((C.restrict B).cay (-C.norm v)).norm := - hreg.prod_isGPRNonsingular - (hreg.isGPRNonsingular.smul_of_isUnit (by rwa [neg_neg] : IsUnit (-(-C.norm v)))) - have hDns : QuadraticForm.IsGPRNonsingular.{u, v, u} (C.restrict D).norm := by - have hcomp := hcay.comp_linearEquiv e.symm - have heq : ((C.restrict B).cay (-C.norm v)).norm.comp e.symm.toLinearMap = - (C.restrict D).norm := by - rw [← hpull] - refine QuadraticMap.ext fun d ↦ ?_ - simp - rwa [heq] at hcomp - have hDcomp : (C.restrict D).IsComposition.{u, v, u} := ⟨hDns, h.isMultiplicative.restrict⟩ - -- The rank doubles. - have hDrank : Module.rankAtStalk (R := k) D = fun _ ↦ 2 * s := by - rw [← Module.rankAtStalk_eq_of_equiv e, rankAtStalk_cay, ← rankAtStalk_toSubmodule, hB] - rfl - have hDrank' : Module.rankAtStalk (R := k) D.toNonUnitalSubalgebra.toSubmodule = - fun _ ↦ 2 * s := by - rw [rankAtStalk_toSubmodule] - exact hDrank - refine ⟨D, v, hu, hBv, hDcomp.isGPRRegular_of_rankAtStalk_ne_one hDrank (by omega), hDrank', - fun hfull ↦ ⟨hinj, fun x ↦ ?_⟩⟩ - have hmem : x ∈ D := mem_of_isGPRRegular_of_rankAtStalk_eq - (hDcomp.isGPRRegular_of_rankAtStalk_ne_one hDrank (by omega)) hA (hfull ▸ hDrank') x + obtain ⟨hDreg, hDrank'⟩ := + isGPRRegular_restrict_and_rankAtStalk_of_equiv_cay h hreg hBv hu D e he hB + refine ⟨D, v, hu, hBv, hDreg, hDrank', fun hfull ↦ ⟨hinj, fun x ↦ ?_⟩⟩ + have hmem : x ∈ D := mem_of_isGPRRegular_of_rankAtStalk_eq hDreg hA (hfull ▸ hDrank') x exact ⟨e.symm ⟨x, hmem⟩, by rw [← he, e.apply_symm_apply]⟩ /-! ### Iterating: `GPR 19.17` -/ diff --git a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean index 3d49bce06b..3e02970a9d 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Conic/CayleyDicksonMultiplicative.lean @@ -80,9 +80,10 @@ private theorem polar_shuffle (h : C.IsMultiplicative) (u₁ u₂ v₁ v₂ : B) norm of `Cay(B, μ)` is multiplicative, for every scalar `μ`. -This is the step that makes `ℍ` a composition algebra out of `ℂ`, and `𝕆` out of `ℍ`; it fails to -apply one rung further because `𝕆` is not associative, which is why the sedenions -`Cay(𝕆, μ)` are conic but not composition (`GPR 19.23`). -/ +This sufficient result constructs multiplicative norms on `ℍ` and `𝕆` from associative +inputs. It gives no converse for a non-associative input: further norm multiplicativity is +governed by the radical criterion of `GPR Exc. 18.18`, which is automatic for `μ = 0`. +Multiplicativity alone does not establish that the double is a composition algebra. -/ theorem isMultiplicative_cay (C : ConicAlgebra k B) (μ : k) (h : C.IsMultiplicative) : (C.cay μ).IsMultiplicative := by intro x y From 5882deab58b7c64bab0fe760f7b656367374c55b Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Sat, 17 Oct 2026 04:06:12 +0000 Subject: [PATCH 6/6] Correct the Artin theorem bibliography Remove the unverified 1927 entry; retain the Schafer reference followed by the proof. --- .../Nonassociative/Alternative/Artin.lean | 2 -- 1 file changed, 2 deletions(-) diff --git a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean index 9bb49b4af9..f2cdcdff61 100644 --- a/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean +++ b/LeanPool/CompositionAlgebrasOverRings/Nonassociative/Alternative/Artin.lean @@ -44,8 +44,6 @@ that proves `generators_nuclear`. ## References -* E. Artin, *Zur Theorie der hyperkomplexen Zahlen*, Abh. Math. Sem. Univ. Hamburg **5** (1927), - 251–260. * Schafer, *An Introduction to Nonassociative Algebras*, §3, Theorem 3.1. * Zhevlakov, Slin'ko, Shestakov, Shirshov, *Rings That Are Nearly Associative*, ch. 2. * [GPR] Garibaldi, Petersson, Racine, *Albert Algebras over Commutative Rings*, Ch. 13.