From cf826f6c011749499795f839dcdb8468a334cb4c Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 18:04:14 +0000 Subject: [PATCH 1/5] Import Classical several complex variables --- LeanPool.lean | 163 +++ LeanPool/SeveralComplexVariables.lean | 179 ++++ .../SeveralComplexVariables.lean | 215 ++++ .../SeveralComplexVariables/Analysis.lean | 12 + .../Analysis/Connected.lean | 75 ++ .../Analysis/LinearFunctional.lean | 105 ++ .../Analysis/OpenMapping.lean | 161 +++ .../Analysis/TaylorBounds.lean | 77 ++ .../SeveralComplexVariables/AnalyticGerm.lean | 346 +++++++ .../AnalyticGerm/CoefficientPolynomial.lean | 225 +++++ .../AnalyticGerm/CoordinateChange.lean | 270 +++++ .../AnalyticGerm/Elimination.lean | 129 +++ .../AnalyticGerm/Factorization.lean | 124 +++ .../AnalyticGerm/Fiber.lean | 135 +++ .../AnalyticGerm/IntrinsicOrder.lean | 142 +++ .../AnalyticGerm/Noetherian.lean | 236 +++++ .../AnalyticGerm/Order.lean | 724 ++++++++++++++ .../AnalyticGerm/Polynomial.lean | 221 ++++ .../AnalyticGerm/RelativePrimality.lean | 187 ++++ .../AnalyticGerm/Units.lean | 65 ++ .../AnalyticGerm/Weierstrass.lean | 424 ++++++++ .../SeveralComplexVariables/AnalyticSet.lean | 16 + .../AnalyticSet/Basic.lean | 249 +++++ .../AnalyticSet/Codimension.lean | 175 ++++ .../AnalyticSet/CoordinatePlane.lean | 137 +++ .../AnalyticSet/FunctionSpace.lean | 77 ++ .../AnalyticSet/Hartogs.lean | 200 ++++ .../AnalyticSet/Holomorphic.lean | 74 ++ .../AnalyticSet/Regular.lean | 297 ++++++ .../AnalyticSet/Removable.lean | 138 +++ .../SeveralComplexVariables/Analyticity.lean | 106 ++ .../BallAutomorphisms.lean | 385 +++++++ .../Biholomorphic.lean | 297 ++++++ .../BiholomorphicRigidity.lean | 177 ++++ .../CartanThullen.lean | 289 ++++++ .../CartanUniqueness.lean | 126 +++ .../CauchyCoefficients.lean | 327 ++++++ .../CauchyDerivatives.lean | 138 +++ .../CauchyEstimates.lean | 90 ++ .../CauchyIntegral.lean | 204 ++++ .../CauchyPompeiu.lean | 382 +++++++ .../CauchyRiemann.lean | 130 +++ .../SeveralComplexVariables/CauchySeries.lean | 679 +++++++++++++ .../CauchyTransform.lean | 277 +++++ .../SeveralComplexVariables/Circular.lean | 121 +++ .../CircularContinuation.lean | 238 +++++ .../CommonExtension.lean | 139 +++ .../SeveralComplexVariables/CompactHole.lean | 374 +++++++ .../ContourIntegral.lean | 123 +++ .../SeveralComplexVariables/Derivatives.lean | 429 ++++++++ .../DomainOfHolomorphy.lean | 222 +++++ .../DominatedIntegral.lean | 86 ++ .../FunctionSpace.lean | 210 ++++ .../FunctionSpace/Extension.lean | 212 ++++ .../HartogsContinuation.lean | 125 +++ .../HartogsDomain.lean | 260 +++++ .../HartogsExtension.lean | 189 ++++ .../HartogsLaurent.lean | 212 ++++ .../HartogsSeries.lean | 298 ++++++ .../HolomorphicConvexity.lean | 13 + .../BoundaryDistance.lean | 129 +++ .../HolomorphicConvexity/Exhaustion.lean | 264 +++++ .../HolomorphicConvexity/Hull.lean | 266 +++++ .../HolomorphicConvexity/Thullen.lean | 328 ++++++ .../HolomorphicConvexity/Transport.lean | 115 +++ .../HolomorphicLp.lean | 243 +++++ .../IdentityPrinciple.lean | 76 ++ .../ImplicitGraph.lean | 56 ++ .../ImplicitMapping.lean | 152 +++ .../InjectiveMapping.lean | 144 +++ .../InjectiveMapping/CorankOne.lean | 194 ++++ .../InjectiveMapping/CriticalSet.lean | 126 +++ .../InjectiveMapping/Immersion.lean | 193 ++++ .../InjectiveMapping/OneVariable.lean | 100 ++ .../SeveralComplexVariables/Integral.lean | 9 + .../Integral/Circle.lean | 47 + .../IsolatedSingularity.lean | 102 ++ .../LaurentApproximation.lean | 226 +++++ .../LaurentSeries.lean | 97 ++ .../LaurentSeries/Annulus.lean | 137 +++ .../LaurentSeries/Basic.lean | 216 ++++ .../LaurentSeries/Coefficients.lean | 114 +++ .../LaurentSeries/Convergence.lean | 229 +++++ .../LaurentSeries/Iterated.lean | 99 ++ .../LaurentSeries/Neighborhoods.lean | 120 +++ .../LaurentSeries/OneVariable.lean | 306 ++++++ .../LaurentSeries/ProductCoefficients.lean | 157 +++ .../LaurentSeries/ProductExpansion.lean | 128 +++ .../LaurentSeries/Uniqueness.lean | 108 ++ .../LeviConvexity.lean | 274 +++++ .../LeviConvexity/Independence.lean | 318 ++++++ .../LeviConvexity/Invariance.lean | 122 +++ .../LeviConvexity/Necessity.lean | 521 ++++++++++ .../LeviConvexity/Peak.lean | 498 +++++++++ .../SeveralComplexVariables/LeviForm.lean | 149 +++ .../LeviForm/Holomorphic.lean | 123 +++ .../LocallyBounded.lean | 161 +++ .../LocallyUniform.lean | 278 ++++++ .../MaximumModulus.lean | 70 ++ .../SeveralComplexVariables/Montel.lean | 245 +++++ .../SeveralComplexVariables/Osgood.lean | 116 +++ .../ParametricIntegral.lean | 181 ++++ .../Plurisubharmonic.lean | 255 +++++ .../SeveralComplexVariables/Polydisc.lean | 232 +++++ .../PolydiscMeanValue.lean | 186 ++++ .../PolydiscTaylor.lean | 334 +++++++ .../SeveralComplexVariables/Polynomial.lean | 9 + .../Polynomial/OfFn.lean | 72 ++ .../PolynomialDerivatives.lean | 51 + .../PowerSeriesConvergence.lean | 127 +++ .../PowerSeriesConvergence/Analytic.lean | 148 +++ .../PowerSeriesConvergence/Basic.lean | 192 ++++ .../Pseudoconvexity.lean | 656 ++++++++++++ .../RealUniqueness.lean | 129 +++ .../SeveralComplexVariables/Reindex.lean | 90 ++ .../SeveralComplexVariables/Reinhardt.lean | 295 ++++++ .../Reinhardt/Extension.lean | 250 +++++ .../Reinhardt/GeometricConvexity.lean | 270 +++++ .../Reinhardt/HolomorphicConvexity.lean | 103 ++ .../Reinhardt/Hull.lean | 237 +++++ .../Reinhardt/MonomialSeparation.lean | 215 ++++ .../Reinhardt/PartialHull.lean | 317 ++++++ .../RemovableSingularity.lean | 179 ++++ .../RemovableSingularity/Cauchy.lean | 54 + .../RemovableSingularity/ExceptionalSet.lean | 164 +++ .../RemovableSingularity/Geometry.lean | 116 +++ .../RemovableSingularity/Gluing.lean | 79 ++ .../RemovableSingularity/Local.lean | 105 ++ .../RemovableSingularity/OneVariable.lean | 81 ++ .../SeveralComplexVariables/Runge.lean | 382 +++++++ .../Runge/Examples.lean | 206 ++++ .../SeparateAnalytic.lean | 273 +++++ .../SeparateAnalytic/Baire.lean | 156 +++ .../SeparateAnalytic/FiberExtension.lean | 307 ++++++ .../SeparateAnalytic/HartogsLemma.lean | 143 +++ .../SeparateAnalytic/MeanValue.lean | 139 +++ .../SeparateAnalytic/Submean.lean | 155 +++ .../SphericalShell.lean | 109 ++ .../SeveralComplexVariables/Subharmonic.lean | 390 ++++++++ .../Subharmonic/Majorant.lean | 206 ++++ .../Subharmonic/SmoothCriterion.lean | 407 ++++++++ .../SeveralComplexVariables/Topology.lean | 13 + .../Topology/CompactExhaustion.lean | 49 + .../Topology/Frontier.lean | 28 + .../Topology/Graph.lean | 63 ++ .../Topology/Path.lean | 46 + .../Topology/UpperSemicontinuous.lean | 35 + .../SeveralComplexVariables/TubeDomain.lean | 177 ++++ .../TubeDomain/Basic.lean | 231 +++++ .../TubeDomain/Bochner.lean | 170 ++++ .../TubeDomain/Disc.lean | 414 ++++++++ .../TubeDomain/Gluing.lean | 156 +++ .../TubeDomain/StarConvex.lean | 495 +++++++++ .../WeierstrassDivision.lean | 655 ++++++++++++ .../WeierstrassDivision/Basic.lean | 167 ++++ .../WeierstrassDivision/CoordinatePower.lean | 748 ++++++++++++++ .../WeierstrassDivision/Picard.lean | 548 ++++++++++ .../WeierstrassPreparation.lean | 314 ++++++ .../SeveralComplexVariables/ZeroSets.lean | 71 ++ .../ZeroSets/Basic.lean | 106 ++ .../ZeroSets/Connected.lean | 104 ++ .../ZeroSets/Local.lean | 132 +++ .../ZeroSets/Persistence.lean | 98 ++ .../SeveralComplexVariables/Solution.lean | 943 ++++++++++++++++++ LeanPool/projects.yml | 36 + 165 files changed, 33591 insertions(+) create mode 100644 LeanPool/SeveralComplexVariables.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/Connected.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/LinearFunctional.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/OpenMapping.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/TaylorBounds.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Elimination.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Factorization.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Fiber.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/IntrinsicOrder.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Order.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Polynomial.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/RelativePrimality.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Units.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Codimension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/CoordinatePlane.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/FunctionSpace.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Hartogs.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Regular.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Removable.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analyticity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/BallAutomorphisms.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Biholomorphic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/BiholomorphicRigidity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanThullen.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanUniqueness.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyCoefficients.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyDerivatives.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyEstimates.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyIntegral.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyPompeiu.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchySeries.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyTransform.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CircularContinuation.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ContourIntegral.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/DominatedIntegral.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace/Extension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsContinuation.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsDomain.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsLaurent.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsSeries.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/BoundaryDistance.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Exhaustion.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Hull.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Thullen.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Transport.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicLp.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/IdentityPrinciple.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitGraph.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitMapping.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CorankOne.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/Immersion.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/OneVariable.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral/Circle.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/IsolatedSingularity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentApproximation.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Annulus.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Coefficients.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Convergence.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Iterated.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Neighborhoods.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/OneVariable.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductCoefficients.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductExpansion.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Uniqueness.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Independence.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Invariance.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Necessity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm/Holomorphic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyBounded.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/MaximumModulus.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Montel.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Osgood.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ParametricIntegral.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polydisc.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscMeanValue.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscTaylor.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial/OfFn.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Analytic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RealUniqueness.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reindex.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/GeometricConvexity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/HolomorphicConvexity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Cauchy.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/ExceptionalSet.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Geometry.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Gluing.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Local.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/OneVariable.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge/Examples.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/HartogsLemma.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/MeanValue.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Submean.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/SphericalShell.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/Majorant.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/SmoothCriterion.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/CompactExhaustion.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Frontier.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Graph.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Path.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/UpperSemicontinuous.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Bochner.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Disc.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Gluing.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/StarConvex.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Basic.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Connected.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Local.lean create mode 100644 LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Persistence.lean create mode 100644 LeanPool/SeveralComplexVariables/Solution.lean diff --git a/LeanPool.lean b/LeanPool.lean index 50fa6e5b30..12a4a56f66 100644 --- a/LeanPool.lean +++ b/LeanPool.lean @@ -6592,6 +6592,169 @@ import LeanPool.SetTheory.Realize import LeanPool.SetTheory.RealizeBuilders import LeanPool.SetTheory.RealizeCore import LeanPool.SetTheory.SimpAttr +import LeanPool.SeveralComplexVariables +import LeanPool.SeveralComplexVariables.SeveralComplexVariables +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.IntrinsicOrder +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.RelativePrimality +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Units +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BallAutomorphisms +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyRiemann +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DominatedIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsSeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicLp +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentApproximation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Peak +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.MaximumModulus +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolynomialDerivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RealUniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reindex +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.PartialHull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge.Examples +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence +import LeanPool.SeveralComplexVariables.Solution import LeanPool.Shannon1948Formalization import LeanPool.Shannon1948Formalization.Entropy import LeanPool.Shannon1948Formalization.Entropy.Approx diff --git a/LeanPool/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables.lean new file mode 100644 index 0000000000..59a540a4e9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.IntrinsicOrder +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.RelativePrimality +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Units +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BallAutomorphisms +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyRiemann +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DominatedIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsSeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicLp +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentApproximation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Peak +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.MaximumModulus +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolynomialDerivatives +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RealUniqueness +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reindex +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.PartialHull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge.Examples +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets +import LeanPool.SeveralComplexVariables.SeveralComplexVariables +import LeanPool.SeveralComplexVariables.Solution + +/-! +# Classical several complex variables + +Source: url:https://github.com/bjbraams/lean-scv +Authors: Bastiaan J Braams +Status: verified +Main declarations: `SCV.cauchy_formula_polydisc`, `SCV.osgood`, `SCV.identity_theorem` +Tags: complex-analysis, several-complex-variables, holomorphic-functions +MSC: 32A10, 32D05, 32E10 +-/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean new file mode 100644 index 0000000000..a994e1e7a3 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.IntrinsicOrder +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.RelativePrimality +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Units +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BallAutomorphisms +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyRiemann +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DominatedIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsSeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicLp +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentApproximation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Peak +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.MaximumModulus +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolynomialDerivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RealUniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reindex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.PartialHull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge.Examples +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence + +/-! +# Several complex variables + +This umbrella imports the classical function theory of open subsets of finite-dimensional +complex normed spaces. Analytic maps use Mathlib's `AnalyticOnNhd ℂ`; holomorphic maps on open +sets use `DifferentiableOn ℂ`. Banach-valued targets are retained where appropriate. Finite +coordinate spaces carry the supremum norm, so their balls are polydiscs; Euclidean ball geometry +uses the inner-product norm explicitly. + +## Local analysis and function spaces + +The library provides polydisc Cauchy and Taylor formulas with separate radii, mixed derivative +estimates, the Cauchy–Riemann equations, the identity and maximum principles, analytic parameter +integrals, and the Cauchy–Pompeiu identity. Locally uniform convergence preserves analyticity +and derivatives. Holomorphic maps form compact-open function spaces, with continuous evaluation, +restriction, and coordinate differentiation. Montel and Vitali theorems use finite-dimensional +targets for compactness. Holomorphic `Lp` spaces are complete, including exponent infinity. + +## Mapping theory and continuation + +Inverse and implicit mapping theorems, regular zero-set graphs, injective holomorphic maps, +Cartan uniqueness, circular rigidity, and explicit ball automorphisms are included. Reinhardt, +circular, and Hartogs geometry support Taylor and Laurent continuation, unrestricted separate +holomorphy, and removable singularities. Hartogs' compact-hole theorem follows from Ehrenpreis' +argument with real derivatives and the Cauchy transform, without differential forms. + +## Germs and analytic sets + +Analytic germs form local integral domains with residue field `ℂ`. Weierstrass division and +preparation, Taylor uniqueness, coordinate-independent total order, Noetherianity, and unique +factorization support zero-set and relative-primality results. Analytic subsets have local +finite equations, interior rigidity, dense connected complements, and regular and singular loci. +The Riemann extension theorems include Banach-valued removal and the holomorphic restriction +algebra equivalence across sets of slice codimension at least two. + +## Convexity, boundary geometry, and approximation + +Holomorphic hulls, compact exhaustions, and escaping sequences lead to the Cartan–Thullen +equivalences on finite-dimensional complex normed spaces. Thullen's Banach-valued Taylor +continuation lemma gives the coordinate hull-radius statements and Bochner's tube theorem. +Subharmonicity and plurisubharmonicity use the local submean property; the Laplacian and Levi +form give their `C²` criteria. Domains of holomorphy are pseudoconvex and satisfy continuity +principles. Levi's necessary condition, independence of the defining function, holomorphic +supporting polynomials, normalized local peak functions, and local holomorphic blow-up are +proved. Runge pairs and domains use approximation on compact sets; polynomial hulls and +Reinhardt and circular examples are included. + +The Oka–Weil theorem, the Levi sufficiency problem, and abstract envelopes of holomorphy remain +outside this library's scope. `SCVMainTheorems.md` gives the precise mathematical catalogue; +`SeveralComplexVariablesCoverage.md` records the development ledger. +-/ + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean new file mode 100644 index 0000000000..6ecb3614fb --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean @@ -0,0 +1,12 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/Connected.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/Connected.lean new file mode 100644 index 0000000000..8dfd1adf14 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/Connected.lean @@ -0,0 +1,75 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Module.Connected + +/-! +# Connectedness of shells and exteriors of balls + +In a real normed space of dimension at least two, spherical shells and exteriors of closed balls +centered at the origin are preconnected. The proofs are radial: a shell is the image of the product +of an interval and the unit sphere. + +## Main results + +* `isPreconnected_ball_diff_closedBall_zero`: A shell in a real normed space of dimension at least + two is preconnected. +* `isPreconnected_compl_closedBall_zero`: The exterior of a closed norm ball is preconnected in + real dimension at least two. +-/ + +public section + +open Metric Set + +/-- A shell in a real normed space of dimension at least two is preconnected. This radial argument +is independent of any analytic extension theorem. -/ +theorem isPreconnected_ball_diff_closedBall_zero {E : Type*} [NormedAddCommGroup E] + [NormedSpace ℝ E] + (hdim : 1 < Module.rank ℝ E) {ρ R : ℝ} (hρ : 0 ≤ ρ) : + IsPreconnected (ball (0 : E) R \ closedBall 0 ρ) := by + let A : Set (ℝ × E) := Ioo ρ R ×ˢ sphere 0 1 + have hA : IsPreconnected A := isPreconnected_Ioo.prod + (isPreconnected_sphere hdim (0 : E) 1) + have hc : Continuous (fun p : ℝ × E => p.1 • p.2) := continuous_fst.smul continuous_snd + have he : (fun p : ℝ × E => p.1 • p.2) '' A = ball (0 : E) R \ closedBall 0 ρ := by + apply Subset.antisymm + · rintro z ⟨⟨t, v⟩, ⟨ht, hv⟩, rfl⟩ + have hvn : ‖v‖ = 1 := by simpa [mem_sphere, dist_zero_right] using hv + have htn : 0 < t := hρ.trans_lt ht.1 + simpa [mem_ball, mem_closedBall, dist_zero_right, norm_smul, + Real.norm_of_nonneg htn.le, hvn] using ⟨ht.2, ht.1⟩ + · intro z hz + have hzR : ‖z‖ < R := by simpa [mem_ball, dist_zero_right] using hz.1 + have hzρ : ρ < ‖z‖ := by simpa [mem_closedBall, dist_zero_right] using hz.2 + have hn : 0 < ‖z‖ := hρ.trans_lt hzρ + refine ⟨(‖z‖, ‖z‖⁻¹ • z), ⟨⟨hzρ, hzR⟩, ?_⟩, ?_⟩ + · simp [norm_smul, Real.norm_of_nonneg (inv_nonneg.mpr hn.le), + inv_mul_cancel₀ hn.ne'] + · simp [smul_smul, mul_inv_cancel₀ hn.ne'] + rw [← he] + exact hA.image _ hc.continuousOn + +/-- The exterior of a closed norm ball is preconnected in real dimension at least two. It is the +directed union of the finite shells. -/ +theorem isPreconnected_compl_closedBall_zero {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] + (hdim : 1 < Module.rank ℝ E) {ρ : ℝ} (hρ : 0 ≤ ρ) : + IsPreconnected ((closedBall (0 : E) ρ)ᶜ) := by + have h : IsPreconnected (⋃ n : ℕ, ball (0 : E) (n : ℝ) \ closedBall 0 ρ) := by + rw [← sUnion_range] + apply IsPreconnected.sUnion_directed + · rintro s ⟨n, rfl⟩ t ⟨m, rfl⟩ + refine ⟨ball (0 : E) ((max n m : ℕ) : ℝ) \ closedBall 0 ρ, ⟨max n m, rfl⟩, ?_, ?_⟩ + · exact sdiff_subset_sdiff_left (ball_subset_ball (by exact_mod_cast le_max_left n m)) + · exact sdiff_subset_sdiff_left (ball_subset_ball (by exact_mod_cast le_max_right n m)) + · rintro s ⟨n, rfl⟩ + exact isPreconnected_ball_diff_closedBall_zero hdim hρ + simpa only [← iUnion_sdiff, iUnion_ball_nat, ← compl_eq_univ_sdiff] using h + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/LinearFunctional.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/LinearFunctional.lean new file mode 100644 index 0000000000..acc575d112 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/LinearFunctional.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.Module.LinearMap.DivisionRing +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.Normed.Operator.Basic + +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.NormNum +import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Push + +/-! +# Elementary facts on scalar actions and continuous linear functionals + +## Main results + +* `Complex.smul_eq_re_smul_add_im_smul`: A complex scalar acts on a vector of a complex module + through its real and imaginary parts. +* `ContinuousLinearMap.exists_apply_eq_one_of_ne_zero`: A nonzero continuous linear functional + attains the value `1` on a nonzero vector. +* `ContinuousLinearMap.exists_pos_smul_eq_of_neg_imp_nonpos`: Inclusion of negative half-spaces + forces two nonzero real continuous linear functionals to be positively proportional. +-/ + +public section + +/-- A complex scalar acts on a vector through its real and imaginary parts. -/ +theorem Complex.smul_eq_re_smul_add_im_smul {E : Type*} [AddCommGroup E] [Module ℂ E] + (ζ : ℂ) (c : E) : ζ • c = ζ.re • c + ζ.im • (Complex.I • c) := by + conv_lhs => rw [← Complex.re_add_im ζ] + rw [add_smul, mul_smul, Complex.coe_smul, Complex.coe_smul] + +/-- A nonzero continuous linear functional attains the value `1` on a nonzero vector. -/ +theorem ContinuousLinearMap.exists_apply_eq_one_of_ne_zero {𝕜 E : Type*} + [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] {ℓ : E →L[𝕜] 𝕜} + (hℓ : ℓ ≠ 0) : ∃ ν, ℓ ν = 1 ∧ 0 < ‖ν‖ := by + have hℓ' : (ℓ : E →ₗ[𝕜] 𝕜) ≠ 0 := fun h => hℓ (ContinuousLinearMap.coe_injective h) + obtain ⟨ν, hν⟩ := LinearMap.surjective hℓ' 1 + refine ⟨ν, hν, norm_pos_iff.mpr fun h0 => ?_⟩ + rw [h0, map_zero] at hν + exact zero_ne_one hν + +/-- A nonzero functional whose closed negative half-space contains the open negative half-space of +another nonzero functional is a positive multiple of it. -/ +theorem ContinuousLinearMap.exists_pos_smul_eq_of_neg_imp_nonpos + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {ℓ₁ ℓ₂ : E →L[ℝ] ℝ} + (h₁ : ℓ₁ ≠ 0) (h₂ : ℓ₂ ≠ 0) + (h : ∀ v, ℓ₂ v < 0 → ℓ₁ v ≤ 0) : ∃ c : ℝ, 0 < c ∧ ℓ₁ = c • ℓ₂ := by + obtain ⟨u, hu⟩ : ∃ u, ℓ₂ u ≠ 0 := by + by_contra hcon + push Not at hcon + exact h₂ (ContinuousLinearMap.ext hcon) + set u₀ : E := (1 / ℓ₂ u) • u with hu₀ + have hℓu₀ : ℓ₂ u₀ = 1 := by rw [hu₀, map_smul, smul_eq_mul, one_div, inv_mul_cancel₀ hu] + set c := ℓ₁ u₀ with hc + -- the kernel of `ℓ₂` is contained in the kernel of `ℓ₁` + have hker : ∀ v, ℓ₂ v = 0 → ℓ₁ v = 0 := by + intro v hv + have hle : ∀ ε : ℝ, 0 < ε → ℓ₁ v ≤ ε * c := by + intro ε hε + have := h (v - ε • u₀) (by rw [map_sub, map_smul, hv, hℓu₀, smul_eq_mul]; linarith) + rw [map_sub, map_smul, smul_eq_mul] at this + linarith + have hge : ∀ ε : ℝ, 0 < ε → -(ε * c) ≤ ℓ₁ v := by + intro ε hε + have := h (-v - ε • u₀) (by rw [map_sub, map_neg, map_smul, hv, hℓu₀, smul_eq_mul]; linarith) + rw [map_sub, map_neg, map_smul, smul_eq_mul] at this + linarith + have h1 : ℓ₁ v ≤ 0 := le_of_forall_pos_le_add fun ε hε => by + have := hle (ε / (|c| + 1)) (by positivity) + have hcb : ε / (|c| + 1) * c ≤ ε := by + rw [div_mul_eq_mul_div, div_le_iff₀ (by positivity)] + nlinarith [le_abs_self c, abs_nonneg c] + linarith + have h2 : 0 ≤ ℓ₁ v := by + by_contra hneg + push Not at hneg + have := hge (-ℓ₁ v / (2 * (|c| + 1))) (div_pos (by linarith) (by positivity)) + have hcb : -ℓ₁ v / (2 * (|c| + 1)) * c ≤ -ℓ₁ v / 2 := by + rw [div_mul_eq_mul_div, div_le_iff₀ (by positivity)] + nlinarith [le_abs_self c, abs_nonneg c] + linarith + exact le_antisymm h1 h2 + have heq : ℓ₁ = c • ℓ₂ := by + ext v + have hv : ℓ₂ (v - ℓ₂ v • u₀) = 0 := by rw [map_sub, map_smul, hℓu₀, smul_eq_mul, mul_one, + sub_self] + have := hker _ hv + rw [map_sub, map_smul, smul_eq_mul, sub_eq_zero] at this + rw [this, smul_apply, smul_eq_mul, hc, mul_comm] + have hc0 : 0 ≤ c := by + have := h (-u₀) (by rw [map_neg, hℓu₀]; norm_num) + rw [map_neg] at this + linarith + refine ⟨c, lt_of_le_of_ne hc0 fun hzero => h₁ ?_, heq⟩ + rw [heq, ← hzero, zero_smul] + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/OpenMapping.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/OpenMapping.lean new file mode 100644 index 0000000000..00b9c3990a --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/OpenMapping.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.SpecificLimits.Normed +public import Mathlib.Topology.Algebra.IsUniformGroup.Basic +public import Mathlib.Topology.Algebra.Module.Equiv +public import Mathlib.Topology.Baire.CompleteMetrizable +public import Mathlib.Topology.Baire.Lemmas + +/-! +# Open mapping for complete metrizable real or complex vector spaces + +This supplies the open-mapping argument needed for holomorphic function spaces with their +compact-open topology. Baire's theorem first gives neighborhoods in closures of images; +successive approximations and completeness remove the closure. The compatible metrics need not +arise from norms and scalar multiplication need not preserve them. + +## Main results + +`isOpenMap_of_surjective_complete` is the open mapping theorem for a surjective continuous +linear map from a complete metrizable space to a Hausdorff metrizable Baire space. Its proof goes +through a private neighborhood form: the image of every zero neighborhood is a zero neighborhood. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace ContinuousLinearMap + +variable {𝕜 E F : Type*} [RCLike 𝕜] [AddCommGroup E] [Module 𝕜 E] [PseudoMetricSpace E] + [IsUniformAddGroup E] [ContinuousSMul 𝕜 E] + [AddCommGroup F] [Module 𝕜 F] [PseudoMetricSpace F] + [IsUniformAddGroup F] [ContinuousSMul 𝕜 F] + +/-- Baire's theorem gives a neighborhood in the closure of the image of any zero neighborhood under +a surjective continuous linear map. -/ +private theorem closure_image_mem_nhds_of_surjective [BaireSpace F] + (T : E →L[𝕜] F) (hs : Function.Surjective T) {W : Set E} (hW : W ∈ 𝓝 0) : + closure (T '' W) ∈ 𝓝 0 := by + classical + have hsub : {p : E × E | p.1 - p.2 ∈ W} ∈ 𝓝 (0, 0) := + (continuous_fst.sub continuous_snd).continuousAt.preimage_mem_nhds (by simpa using hW) + obtain ⟨D, hD, D', hD', hDD⟩ := mem_nhds_prod_iff.mp hsub + let B := D ∩ D' + have hB : B ∈ 𝓝 (0 : E) := inter_mem hD hD' + have hBW {x y : E} (hx : x ∈ B) (hy : y ∈ B) : x - y ∈ W := + hDD (show (x, y) ∈ D ×ˢ D' from ⟨hx.1, hy.2⟩) + let c (n : ℕ) : 𝕜 := (n + 1 : ℕ) + have hc (n : ℕ) : c n ≠ 0 := by dsimp [c]; exact_mod_cast Nat.succ_ne_zero n + let e (n : ℕ) : F ≃L[𝕜] F := + ContinuousLinearEquiv.smulLeft (R₁ := 𝕜) (M₁ := F) (Units.mk0 (c n) (hc n)) + let S := closure (T '' B) + have hcover : ⋃ n, e n '' S = univ := by + apply iUnion_eq_univ_iff.mpr + intro y + obtain ⟨x, rfl⟩ := hs y + have ht : Tendsto (fun n => (c n)⁻¹ • x) atTop (𝓝 (0 : E)) := by + simpa [c, one_div] using + (tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := 𝕜)).smul_const x + obtain ⟨n, hn⟩ := (ht.eventually hB).exists + refine ⟨n, T ((c n)⁻¹ • x), subset_closure ⟨_, hn, rfl⟩, ?_⟩ + simp [e, map_smul, smul_smul, hc] + obtain ⟨n, z, hz⟩ := nonempty_interior_of_iUnion_of_closed + (fun n => (e n).toHomeomorph.isClosedMap S isClosed_closure) hcover + let a := (e n).symm z + have hS : S ∈ 𝓝 a := by + have hh := (e n).continuous.continuousAt.preimage_mem_nhds + (show e n '' S ∈ 𝓝 (e n a) by + simpa [a] using mem_interior_iff_mem_nhds.mp hz) + simpa only [preimage_image_eq _ (e n).injective] using hh + have ha : a ∈ S := mem_of_mem_nhds hS + have hN : (fun y : F => y + a) ⁻¹' S ∈ 𝓝 0 := + (continuous_id.add continuous_const).continuousAt.preimage_mem_nhds (by simpa using hS) + apply mem_of_superset hN + intro y hy + have hh : (y + a) - a ∈ closure (T '' W) := + map_mem_closure₂ continuous_sub hy ha (by + rintro _ ⟨x, hx, rfl⟩ _ ⟨x', hx', rfl⟩ + exact ⟨x - x', hBW hx hx', T.map_sub x x'⟩) + simpa only [add_sub_cancel_right] using hh + +/-- Completeness removes the closure from the neighborhood conclusion in the Baire argument by +successively correcting the error with geometrically small increments. -/ +private theorem image_mem_nhds_of_surjective [CompleteSpace E] [BaireSpace F] [T2Space F] + (T : E →L[𝕜] F) (hs : Function.Surjective T) {W : Set E} (hW : W ∈ 𝓝 0) : + T '' W ∈ 𝓝 0 := by + classical + obtain ⟨r, hr, hrW⟩ := Metric.nhds_basis_closedBall.mem_iff.mp hW + have hsmall (n : ℕ) : ∃ B ∈ 𝓝 (0 : E), + ∀ x ∈ B, ∀ s : E, dist s (s + x) ≤ (r / 2) * (1 / 2 : ℝ) ^ n := by + have h := dist_mem_uniformity (α := E) (show 0 < (r / 2) * (1 / 2 : ℝ) ^ n by positivity) + rw [uniformity_eq_comap_nhds_zero E] at h + obtain ⟨B, hB, hsub⟩ := Filter.mem_comap.mp h + refine ⟨B, hB, fun x hx s => le_of_lt (hsub + (show (s, s + x) ∈ (fun p : E × E => p.2 - p.1) ⁻¹' B from ?_))⟩ + change (s + x) - s ∈ B + simpa only [add_sub_cancel_left] using hx + choose B hB hdist using hsmall + let V (n : ℕ) := interior (closure (T '' B n)) ∩ ball 0 (1 / ((n : ℝ) + 1)) + have hVo (n : ℕ) : IsOpen (V n) := isOpen_interior.inter isOpen_ball + have hV0 (n : ℕ) : (0 : F) ∈ V n := by + refine ⟨mem_interior_iff_mem_nhds.mpr + (closure_image_mem_nhds_of_surjective T hs (hB n)), ?_⟩ + simp only [mem_ball, dist_self] + positivity + have happrox (n : ℕ) (y : F) (hy : y ∈ V n) : + ∃ x ∈ B n, y - T x ∈ V (n + 1) := by + have hopen : IsOpen ((fun z : F => y - z) ⁻¹' V (n + 1)) := + (hVo _).preimage (continuous_const.sub continuous_id) + obtain ⟨z, hz, x, hx, rfl⟩ := + _root_.mem_closure_iff.mp (interior_subset hy.1) _ hopen (by simpa using hV0 (n + 1)) + exact ⟨x, hx, hz⟩ + apply mem_of_superset ((hVo 0).mem_nhds (hV0 0)) + intro y hy + let step (n : ℕ) (s : {s : E // y - T s ∈ V n}) : + {s : E // y - T s ∈ V (n + 1)} := + ⟨s.val + (happrox n (y - T s.val) s.property).choose, by + have h := (happrox n (y - T s.val) s.property).choose_spec.2 + simpa only [map_add, sub_sub] using h⟩ + let seq : (n : ℕ) → {s : E // y - T s ∈ V n} := + fun n => Nat.rec (motive := fun n => {s : E // y - T s ∈ V n}) + ⟨0, by simpa using hy⟩ step n + have hd (n : ℕ) : dist (seq n).val (seq (n + 1)).val ≤ (r / 2) * (1 / 2 : ℝ) ^ n := + hdist n _ (happrox n (y - T (seq n).val) (seq n).property).choose_spec.1 _ + obtain ⟨x, hx⟩ := cauchySeq_tendsto_of_complete + (cauchySeq_of_le_geometric (1 / 2) (r / 2) (by norm_num) hd) + have hxW : x ∈ W := by + apply hrW + have h := dist_le_of_le_geometric_of_tendsto₀ (1 / 2) (r / 2) (by norm_num) hd hx + change dist x 0 ≤ r + norm_num [seq, dist_comm, div_div] at h ⊢ + exact h + have herr : Tendsto (fun n => y - T (seq n).val) atTop (𝓝 0) := by + apply tendsto_iff_dist_tendsto_zero.mpr + apply squeeze_zero (fun _ => dist_nonneg) + (fun n => le_of_lt (show dist (y - T (seq n).val) 0 < 1 / ((n : ℝ) + 1) from + (seq n).property.2)) + exact tendsto_one_div_add_atTop_nhds_zero_nat + have heq : y - T x = 0 := tendsto_nhds_unique + (tendsto_const_nhds.sub (T.continuous.tendsto x |>.comp hx)) herr + exact ⟨x, hxW, (sub_eq_zero.mp heq).symm⟩ + +/-- A surjective continuous real- or complex-linear map from a complete metrizable topological +vector space to a Hausdorff metrizable Baire vector space is open. The metrics only need to +induce the additive uniformities; they need not arise from norms. -/ +theorem isOpenMap_of_surjective_complete [CompleteSpace E] [BaireSpace F] [T2Space F] + (T : E →L[𝕜] F) (hs : Function.Surjective T) : IsOpenMap T := by + apply IsTopologicalAddGroup.isOpenMap_iff_nhds_zero.mpr + intro S hS + exact mem_of_superset (image_mem_nhds_of_surjective T hs hS) (image_preimage_subset _ _) + +end ContinuousLinearMap + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/TaylorBounds.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/TaylorBounds.lean new file mode 100644 index 0000000000..1ce09152d7 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis/TaylorBounds.lean @@ -0,0 +1,77 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.SpecialFunctions.Pow.Real + +import Mathlib.Tactic.GCongr +import Mathlib.Tactic.Linarith +import Mathlib.Tactic.Positivity +import Mathlib.Tactic.Ring + +/-! +# Elementary bounds for Taylor remainders + +These real inequalities choose a small radius and absorb a cubic error into a quadratic bound. + +## Main results + +* `le_one_and_mul_add_le_of_le_min`: Radius constraints used to absorb a cubic Taylor error into a + quadratic budget `η t ^ 2`. +* `taylor_remainder_add_cubic_le`: Combine a second-order remainder of size `O(t ^ 2)` with a cubic + error of size `O(t ^ 3)` into a single quadratic bound `η t ^ 2`. +-/ + +public section + +namespace SeveralComplexVariables.TaylorBounds + +/-- Radius constraints used to absorb a cubic Taylor error into a quadratic budget `η t ^ 2`. -/ +theorem le_one_and_mul_add_le_of_le_min {η M₀ M₁ δ' r : ℝ} (hM₀ : 0 ≤ M₀) + (hM₁ : 0 ≤ M₁) (hr : 0 < r) + (hr₀ : r ≤ min 1 (min (η / (2 * (M₁ + 1))) (δ' / (2 * (M₀ + 1))))) : + r ≤ 1 ∧ r * (M₁ + 1) ≤ η / 2 ∧ r * (M₀ + 1) < δ' := by + have hr1 : r ≤ 1 := hr₀.trans (min_le_left _ _) + have hrM₁ : r * (M₁ + 1) ≤ η / 2 := by + have := hr₀.trans ((min_le_right _ _).trans (min_le_left _ _)) + rw [le_div_iff₀ (by positivity)] at this + linarith + have hrδ' : r * (M₀ + 1) < δ' := by + have := hr₀.trans ((min_le_right _ _).trans (min_le_right _ _)) + rw [le_div_iff₀ (by positivity)] at this + have : 0 < r * (M₀ + 1) := by positivity + linarith + exact ⟨hr1, hrM₁, hrδ'⟩ + +/-- Combine a second-order remainder of size `O(t ^ 2)` with a cubic error of size `O(t ^ 3)` into a +single quadratic bound `η t ^ 2`. -/ +theorem taylor_remainder_add_cubic_le {η t M₀ M₁ rem cub : ℝ} (ht : 0 < t) (hη : 0 < η) + (htM₁ : t * (M₁ + 1) ≤ η / 2) + (hrem : |rem| ≤ η / (2 * (M₀ ^ 2 + 1)) * (t * M₀) ^ 2) (hcub : |cub| ≤ M₁ * t ^ 3) : + |rem + cub| ≤ η * t ^ 2 := by + have hR : |rem| ≤ η / 2 * t ^ 2 := by + refine hrem.trans ?_ + rw [mul_pow, div_mul_eq_mul_div, div_le_iff₀ (by positivity)] + have : M₀ ^ 2 ≤ M₀ ^ 2 + 1 := by linarith + calc η * (t ^ 2 * M₀ ^ 2) ≤ η * (t ^ 2 * (M₀ ^ 2 + 1)) := by gcongr + _ = η / 2 * t ^ 2 * (2 * (M₀ ^ 2 + 1)) := by ring + have hC : |cub| ≤ η / 2 * t ^ 2 := by + refine hcub.trans ?_ + calc M₁ * t ^ 3 = t * M₁ * t ^ 2 := by ring + _ ≤ η / 2 * t ^ 2 := by + refine mul_le_mul_of_nonneg_right ?_ (by positivity) + have : t * M₁ ≤ t * (M₁ + 1) := + mul_le_mul_of_nonneg_left (by linarith) ht.le + linarith + calc |rem + cub| ≤ |rem| + |cub| := abs_add_le _ _ + _ ≤ η / 2 * t ^ 2 + η / 2 * t ^ 2 := add_le_add hR hC + _ = η * t ^ 2 := by ring + +end SeveralComplexVariables.TaylorBounds + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean new file mode 100644 index 0000000000..6ccbe0ff3f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean @@ -0,0 +1,346 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.Ideal.Quotient.Operations +public import Mathlib.RingTheory.LocalRing.MaximalIdeal.Basic +public import Mathlib.Topology.Germ +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic + +/-! +# The local ring of analytic germs + +An analytic germ is a Mathlib `Filter.Germ` with a representative analytic at the base point. +Equality is agreement on a neighborhood, rather than equality just at the base point. The scalar +field `𝕜` is an explicit argument, `AnalyticGerm 𝕜 x`, and may be any nontrivially normed field: +the scalar germs form a `𝕜`-algebra, evaluation detects its units, identifies its unique maximal +ideal with the germs vanishing at the base point, and identifies the quotient with `𝕜`, and +analytic maps act contravariantly by `𝕜`-algebra homomorphisms. Over `ℝ` or `ℂ` the germs form an +integral domain, by the identity principle on connected balls. The rest of the germ theory in this +library is developed for `𝕜 = ℂ`. + +The motivating references are [Suwa][Suwa2024] (2024), Section 1.4, Propositions 1.5--1.7, and +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Section 1.8. We use `AnalyticAt` for +convergent power series; on finite-dimensional complex domains this agrees with the project's +holomorphic convention. The construction works on arbitrary normed spaces, including the zero +space. Analytic Weierstrass division and preparation are not asserted here. + +## Main definitions + +* `analyticGermSubring`: The subring of germs admitting a representative analytic at the base point. +* `AnalyticGerm`: Scalar analytic germs at `x`, with the ring operations inherited from Mathlib + germs. +* `ofAnalyticAt`: The germ of a function analytic at the base point. +* `eval`: Evaluation of an analytic germ at its base point, as a ring homomorphism. +* `const`: Constant functions define a ring homomorphism into analytic germs. +* `evalAlgHom`: Evaluation also preserves the `𝕜`-algebra structure. +* `pullback`: Composition with an analytic map pulls scalar germs back as a `𝕜`-algebra + homomorphism. +* `pullbackOfEq`: Pullback along a map whose value at the source point is only known up to a stated + equation, letting the target germ's base point be phrased as any value equal to `f x`. +* `quotientKerEvalEquiv`: Quotienting analytic germs by the evaluation kernel gives the scalar + field. +* `quotientMaximalIdealEquiv`: The quotient by the unique maximal ideal is canonically the scalar + field. +* `equivScalarOfSubsingleton`: Analytic germs on a zero-dimensional domain form exactly the scalar + field. + +## Main results + +* `isUnit_iff`: An analytic germ is invertible exactly when its value at the base point is nonzero. +* `maximalIdeal_eq_ker_eval`: Evaluation has the unique maximal ideal as its kernel. +* `pullback_comp`: Pullbacks compose in the reverse order to their analytic maps. +* `eval_surjective`: Evaluation onto the scalar field is surjective. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [T. Suwa, *Complex Analytic Geometry: From the Localization Viewpoint*][Suwa2024] +-/ + +public noncomputable section + +open Filter Set Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {𝕜 E : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] + +variable (𝕜) in + +/-- The subring of germs admitting a representative analytic at the base point. -/ +@[expose] def analyticGermSubring (x : E) : Subring (Germ (𝓝 x) 𝕜) where + carrier := {φ | ∃ f : E → 𝕜, AnalyticAt 𝕜 f x ∧ (f : Germ (𝓝 x) 𝕜) = φ} + zero_mem' := ⟨0, analyticAt_const, rfl⟩ + one_mem' := ⟨1, analyticAt_const, rfl⟩ + add_mem' := by + rintro _ _ ⟨f, hf, rfl⟩ ⟨g, hg, rfl⟩ + exact ⟨f + g, hf.add hg, rfl⟩ + neg_mem' := by + rintro _ ⟨f, hf, rfl⟩ + exact ⟨-f, hf.neg, rfl⟩ + mul_mem' := by + rintro _ _ ⟨f, hf, rfl⟩ ⟨g, hg, rfl⟩ + exact ⟨f * g, hf.mul hg, rfl⟩ + +/-- Membership of a represented germ is exactly analyticity of that representative. -/ +@[simp] theorem mem_analyticGermSubring {x : E} {f : E → 𝕜} : + (f : Germ (𝓝 x) 𝕜) ∈ analyticGermSubring 𝕜 x ↔ AnalyticAt 𝕜 f x := by + constructor + · rintro ⟨g, hg, heq⟩ + exact hg.congr (Germ.coe_eq.mp heq) + · intro hf + exact ⟨f, hf, rfl⟩ + +variable (𝕜) in +/-- Scalar analytic germs at `x` over the field `𝕜`, with the ring operations inherited from +Mathlib germs. -/ +abbrev AnalyticGerm (x : E) : Type _ := ↥(analyticGermSubring 𝕜 x) + +namespace AnalyticGerm + +variable {x : E} + +/-- The germ of a function analytic at the base point. -/ +@[expose] def ofAnalyticAt (f : E → 𝕜) (hf : AnalyticAt 𝕜 f x) : AnalyticGerm 𝕜 x := + ⟨f, f, hf, rfl⟩ + +/-- Every analytic germ has an analytic representative. -/ +theorem exists_rep (φ : AnalyticGerm 𝕜 x) : + ∃ (f : E → 𝕜) (hf : AnalyticAt 𝕜 f x), ofAnalyticAt f hf = φ := by + obtain ⟨f, hf, heq⟩ := φ.property + exact ⟨f, hf, Subtype.ext heq⟩ + +/-- Two analytic representatives define the same germ exactly when they agree nearby. -/ +@[simp] theorem ofAnalyticAt_eq_iff {f g : E → 𝕜} + {hf : AnalyticAt 𝕜 f x} {hg : AnalyticAt 𝕜 g x} : + ofAnalyticAt f hf = ofAnalyticAt g hg ↔ f =ᶠ[𝓝 x] g := by + rw [Subtype.ext_iff] + exact Germ.coe_eq + +/-- The zero germ is represented by the zero function. -/ +theorem ofAnalyticAt_zero : + ofAnalyticAt (0 : E → 𝕜) analyticAt_const = (0 : AnalyticGerm 𝕜 x) := rfl + +/-- Sums of analytic representatives compute sums of germs. -/ +theorem ofAnalyticAt_add (f g : E → 𝕜) (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : + ofAnalyticAt (f + g) (hf.add hg) = ofAnalyticAt f hf + ofAnalyticAt g hg := rfl + +/-- Products of analytic representatives compute products of germs. -/ +theorem ofAnalyticAt_mul (f g : E → 𝕜) (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) : + ofAnalyticAt (f * g) (hf.mul hg) = ofAnalyticAt f hf * ofAnalyticAt g hg := rfl + +/-- Powers of analytic representatives compute powers of germs. -/ +theorem ofAnalyticAt_pow (f : E → 𝕜) (hf : AnalyticAt 𝕜 f x) (n : ℕ) : + ofAnalyticAt (f ^ n) (hf.pow n) = ofAnalyticAt f hf ^ n := rfl + +/-- Finite sums of analytic representatives compute finite sums of germs. -/ +theorem ofAnalyticAt_sum {κ : Type*} (s : Finset κ) (f : κ → E → 𝕜) + (hf : ∀ i, AnalyticAt 𝕜 (f i) x) (hs : AnalyticAt 𝕜 (∑ i ∈ s, f i) x) : + ofAnalyticAt (∑ i ∈ s, f i) hs = ∑ i ∈ s, ofAnalyticAt (f i) (hf i) := by + apply Subtype.ext + show ((∑ i ∈ s, f i : E → 𝕜) : Germ (𝓝 x) 𝕜) = + ((∑ i ∈ s, ofAnalyticAt (f i) (hf i) : AnalyticGerm 𝕜 x) : Germ (𝓝 x) 𝕜) + rw [AddSubmonoidClass.coe_finsetSum] + exact map_sum (Filter.Germ.coeRingHom (𝓝 x)) f s + +/-- Evaluation of an analytic germ at its base point, as a ring homomorphism. -/ +@[expose] def eval (x : E) : AnalyticGerm 𝕜 x →+* 𝕜 := + Germ.valueRingHom.comp (analyticGermSubring 𝕜 x).subtype + +/-- Evaluation of a represented germ is evaluation of its representative. -/ +@[simp] theorem eval_ofAnalyticAt (f : E → 𝕜) (hf : AnalyticAt 𝕜 f x) : + eval x (ofAnalyticAt f hf) = f x := rfl + +/-- Constant functions define a ring homomorphism into analytic germs. -/ +@[expose] def const (x : E) : 𝕜 →+* AnalyticGerm 𝕜 x where + toFun c := ofAnalyticAt (fun _ => c) analyticAt_const + map_zero' := rfl + map_one' := rfl + map_add' _ _ := rfl + map_mul' _ _ := rfl + +/-- Analytic germs form a `𝕜`-algebra via constant germs. -/ +instance : Algebra 𝕜 (AnalyticGerm 𝕜 x) := (const x).toAlgebra + +/-- Evaluation of a constant germ recovers its constant value. -/ +@[simp] theorem eval_const (c : 𝕜) : eval x (const x c) = c := rfl + +/-- Evaluation onto the scalar field is surjective. -/ +theorem eval_surjective (x : E) : Function.Surjective (eval (𝕜 := 𝕜) x) := + fun c => ⟨const x c, rfl⟩ + +/-- Evaluation also preserves the `𝕜`-algebra structure. -/ +def evalAlgHom (x : E) : AnalyticGerm 𝕜 x →ₐ[𝕜] 𝕜 where + __ := eval x + commutes' _ := rfl + +section Pullback + +variable {F G : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + [NormedAddCommGroup G] [NormedSpace 𝕜 G] + +/-- Composition with an analytic map pulls scalar germs back as a `𝕜`-algebra homomorphism. +Mathlib's `compTendsto` makes the construction independent of representatives. -/ +@[expose] def pullback (f : E → F) (hf : AnalyticAt 𝕜 f x) : + AnalyticGerm 𝕜 (f x) →ₐ[𝕜] AnalyticGerm 𝕜 x where + toFun φ := ⟨φ.val.compTendsto f hf.continuousAt, by + obtain ⟨g, hg, heq⟩ := φ.property + refine ⟨g ∘ f, hg.comp hf, ?_⟩ + rw [← heq] + rfl⟩ + map_zero' := rfl + map_one' := rfl + map_add' a b := by + obtain ⟨g, hg, rfl⟩ := exists_rep a + obtain ⟨h, hh, rfl⟩ := exists_rep b + rfl + map_mul' a b := by + obtain ⟨g, hg, rfl⟩ := exists_rep a + obtain ⟨h, hh, rfl⟩ := exists_rep b + rfl + commutes' _ := rfl + +/-- Pullback of a represented germ is represented by composition. -/ +@[simp] theorem pullback_ofAnalyticAt (f : E → F) (hf : AnalyticAt 𝕜 f x) + (g : F → 𝕜) (hg : AnalyticAt 𝕜 g (f x)) : + pullback f hf (ofAnalyticAt g hg) = ofAnalyticAt (g ∘ f) (hg.comp hf) := rfl + +/-- Pullback along a map whose value at the source point is only known up to a stated equation, +letting the target germ's base point be phrased as any value equal to `f x`. Matches `pullback` +definitionally once the equation is substituted. -/ +def pullbackOfEq (f : E → F) (hf : AnalyticAt 𝕜 f x) {y : F} (hy : f x = y) : + AnalyticGerm 𝕜 y →ₐ[𝕜] AnalyticGerm 𝕜 x := + hy ▸ pullback f hf + +/-- Pullback along an equation-adjusted map of a represented germ is represented by composition. -/ +@[simp] theorem pullbackOfEq_ofAnalyticAt (f : E → F) (hf : AnalyticAt 𝕜 f x) {y : F} + (hy : f x = y) (g : F → 𝕜) (hg : AnalyticAt 𝕜 g y) : + pullbackOfEq f hf hy (ofAnalyticAt g hg) = ofAnalyticAt (g ∘ f) (hg.comp_of_eq hf hy) := by + subst hy + rfl + +/-- Evaluation commutes with pullback at the corresponding base points. -/ +@[simp] theorem eval_pullback (f : E → F) (hf : AnalyticAt 𝕜 f x) + (φ : AnalyticGerm 𝕜 (f x)) : eval x (pullback f hf φ) = eval (f x) φ := by + obtain ⟨g, hg, rfl⟩ := exists_rep φ + rfl + +/-- Pullback by the identity fixes every analytic germ. -/ +@[simp] theorem pullback_id (φ : AnalyticGerm 𝕜 x) : + pullback id analyticAt_id φ = φ := by + obtain ⟨f, hf, rfl⟩ := exists_rep φ + rfl + +/-- Pullbacks compose in the reverse order to their analytic maps. -/ +theorem pullback_comp (f : E → F) (hf : AnalyticAt 𝕜 f x) + (g : F → G) (hg : AnalyticAt 𝕜 g (f x)) (φ : AnalyticGerm 𝕜 (g (f x))) : + pullback (g ∘ f) (hg.comp hf) φ = pullback f hf (pullback g hg φ) := by + obtain ⟨h, hh, rfl⟩ := exists_rep φ + rfl + +end Pullback + +/-- An analytic germ is invertible exactly when its value at the base point is nonzero. -/ +theorem isUnit_iff (φ : AnalyticGerm 𝕜 x) : IsUnit φ ↔ eval x φ ≠ 0 := by + constructor + · intro h + exact (h.map (eval x)).ne_zero + · obtain ⟨f, hf, rfl⟩ := exists_rep φ + intro h + have hne : f x ≠ 0 := h + let ψ := ofAnalyticAt (fun y => (f y)⁻¹) (hf.inv hne) + have hmul : ofAnalyticAt f hf * ψ = 1 := by + apply Subtype.ext + apply Germ.coe_eq.mpr + filter_upwards [hf.continuousAt.eventually_ne hne] with y hy + exact mul_inv_cancel₀ hy + exact ⟨⟨ofAnalyticAt f hf, ψ, hmul, by rwa [mul_comm]⟩, rfl⟩ + +/-- Pullback preserves and reflects units, as required of a homomorphism of local rings. -/ +theorem isUnit_pullback_iff {F : Type*} [NormedAddCommGroup F] [NormedSpace 𝕜 F] + (f : E → F) (hf : AnalyticAt 𝕜 f x) (φ : AnalyticGerm 𝕜 (f x)) : + IsUnit (pullback f hf φ) ↔ IsUnit φ := by + simp only [isUnit_iff, eval_pullback] + +/-- The ring of analytic germs is local. -/ +instance : IsLocalRing (AnalyticGerm 𝕜 x) where + isUnit_or_isUnit_of_add_one {a b} h := by + rw [isUnit_iff, isUnit_iff] + by_cases ha : eval x a = 0 + · right + have hv := congrArg (eval x) h + have hb : eval x b = 1 := by simpa [ha] using hv + rw [hb] + exact one_ne_zero + · exact Or.inl ha + +/-- The unique maximal ideal consists precisely of germs vanishing at the base point. -/ +@[simp] theorem mem_maximalIdeal_iff (φ : AnalyticGerm 𝕜 x) : + φ ∈ IsLocalRing.maximalIdeal (AnalyticGerm 𝕜 x) ↔ eval x φ = 0 := by + simp [IsLocalRing.mem_maximalIdeal, mem_nonunits_iff, isUnit_iff] + +/-- Evaluation has the unique maximal ideal as its kernel. -/ +theorem maximalIdeal_eq_ker_eval (x : E) : + IsLocalRing.maximalIdeal (AnalyticGerm 𝕜 x) = RingHom.ker (eval (𝕜 := 𝕜) x) := by + ext φ + exact mem_maximalIdeal_iff φ + +variable (𝕜) in +/-- Quotienting analytic germs by the evaluation kernel gives the scalar field. -/ +def quotientKerEvalEquiv (x : E) : + AnalyticGerm 𝕜 x ⧸ RingHom.ker (eval (𝕜 := 𝕜) x) ≃+* 𝕜 := + (eval (𝕜 := 𝕜) x).quotientKerEquivOfSurjective (eval_surjective x) + +variable (𝕜) in +/-- The quotient by the unique maximal ideal is canonically the scalar field. -/ +def quotientMaximalIdealEquiv (x : E) : + AnalyticGerm 𝕜 x ⧸ IsLocalRing.maximalIdeal (AnalyticGerm 𝕜 x) ≃+* 𝕜 := + (Ideal.quotEquivOfEq (maximalIdeal_eq_ker_eval x)).trans (quotientKerEvalEquiv 𝕜 x) + +/-- In dimension zero, every analytic germ is the constant germ of its value. -/ +theorem const_eval_of_subsingleton [Subsingleton E] (φ : AnalyticGerm 𝕜 x) : + const x (eval x φ) = φ := by + obtain ⟨f, hf, rfl⟩ := exists_rep φ + apply Subtype.ext + apply Germ.coe_eq.mpr + exact Eventually.of_forall fun y => congrArg f (Subsingleton.elim x y) + +variable (𝕜) in +/-- Analytic germs on a zero-dimensional domain form exactly the scalar field. -/ +def equivScalarOfSubsingleton [Subsingleton E] (x : E) : AnalyticGerm 𝕜 x ≃+* 𝕜 := + RingEquiv.ofBijective (eval x) ⟨fun a b h => by + rw [← const_eval_of_subsingleton a, ← const_eval_of_subsingleton b, h], + eval_surjective x⟩ + +section RCLike + +variable {𝕜 E : Type*} [RCLike 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] {x : E} + +/-- Analytic germs over `ℝ` or `ℂ` have no zero divisors, by the analytic identity principle on +connected balls. -/ +instance : NoZeroDivisors (AnalyticGerm 𝕜 x) where + eq_zero_or_eq_zero_of_mul_eq_zero {a b} hab := by + obtain ⟨f, hf, rfl⟩ := exists_rep a + obtain ⟨g, hg, rfl⟩ := exists_rep b + have hfg : (fun y => f y * g y) =ᶠ[𝓝 x] 0 := + Germ.coe_eq.mp (congrArg Subtype.val hab) + rcases eventuallyEq_zero_or_eventuallyEq_zero_of_mul hf hg hfg with h | h + · exact Or.inl (Subtype.ext (Germ.coe_eq.mpr h)) + · exact Or.inr (Subtype.ext (Germ.coe_eq.mpr h)) + +/-- The ring of scalar analytic germs over `ℝ` or `ℂ` is an integral domain. -/ +instance : IsDomain (AnalyticGerm 𝕜 x) := NoZeroDivisors.to_isDomain _ + +end RCLike + +end AnalyticGerm +end SeveralComplexVariables + + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean new file mode 100644 index 0000000000..dda938030f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean @@ -0,0 +1,225 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn + +/-! +# Polynomials built from coefficient germs + +`ofCoefficients` and `remainderOfCoefficients` build a polynomial in `X` from a finite family of +coefficient germs indexed below a fixed degree `d`, with and without the extra monic `X ^ d` +term respectively. Evaluated in the last coordinate by `polynomialHom`, these match the analytic +`weierstrassPolynomial` and `weierstrassRemainder` built from representatives of the same +coefficients. Every monic polynomial of degree `d`, and every polynomial of degree below `d`, is +recovered from its own coefficients in one of these two shapes. The constructions are thin +wrappers around Mathlib's `Polynomial.ofFn`; the algebraic reconstruction results are proved +over arbitrary semirings in `SeveralComplexVariables.Polynomial.OfFn`. + +This coefficient-level bookkeeping underlies Weierstrass division and preparation in the +analytic germ ring, proved in `SeveralComplexVariables.AnalyticGerm.Weierstrass`. + +## Main definitions + +* `ofCoefficients`: The monic polynomial in `X` of degree `d` with prescribed coefficient germs + below `d`. +* `remainderOfCoefficients`: The polynomial in `X` of degree below `d` with prescribed coefficient + germs. + +## Main results + +* `isDistinguishedAt_ofCoefficients`: The distinguished-shape polynomial is distinguished + when its coefficients vanish at the parameter origin. +* `eq_ofCoefficients_of_monic`: Any monic polynomial of degree `d` is the distinguished-shape + polynomial built from its own coefficients. +* `polynomialHom_ofCoefficients`: Evaluating the distinguished-shape polynomial in the last + coordinate gives the Weierstrass polynomial built from analytic representatives of the coefficient + germs. +* `eq_remainderOfCoefficients_of_degree_lt`: Any polynomial of degree below `d` is the + remainder-shape polynomial built from its own coefficients. +-/ + +public noncomputable section + +namespace SeveralComplexVariables.AnalyticGerm + +open Filter +open scoped Topology Classical + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- The monic polynomial in `X` of degree `d` with prescribed coefficient germs below `d`. -/ +@[expose] def ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + Polynomial (AnalyticGerm ℂ (0 : E)) := + Polynomial.X ^ d + Polynomial.ofFn d b + +/-- The lower-degree part of `ofCoefficients` has degree strictly below `d`. -/ +theorem degree_sum_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + (∑ j : Fin d, Polynomial.C (b j) * Polynomial.X ^ (j : ℕ)).degree < (d : WithBot ℕ) := + Polynomial.degree_sum_fin_lt b + +/-- The distinguished-shape polynomial built from coefficient germs is monic. -/ +theorem monic_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + (ofCoefficients b).Monic := + Polynomial.monic_X_pow_add (Polynomial.ofFn_degree_lt b) + +/-- The distinguished-shape polynomial built from coefficient germs has degree `d`. -/ +theorem natDegree_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + (ofCoefficients b).natDegree = d := + Polynomial.natDegree_X_pow_add_ofFn b + +/-- Coefficients of `ofCoefficients` below `d` recover the prescribed germs. -/ +theorem coeff_ofCoefficients_of_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) {i : ℕ} + (hi : i < d) : (ofCoefficients b).coeff i = b ⟨i, hi⟩ := + Polynomial.coeff_X_pow_add_ofFn_of_lt b hi + +/-- The distinguished-shape polynomial is distinguished when its coefficients vanish at the +parameter origin. -/ +theorem isDistinguishedAt_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) + (hb : ∀ j, eval 0 (b j) = 0) : + (ofCoefficients b).IsDistinguishedAt (IsLocalRing.maximalIdeal _) := by + rw [isDistinguishedAt_iff] + refine ⟨monic_ofCoefficients b, fun i hi => ?_⟩ + rw [natDegree_ofCoefficients] at hi + rw [coeff_ofCoefficients_of_lt b hi] + exact hb _ + +/-- Any monic polynomial of degree `d` is the distinguished-shape polynomial built from its own +coefficients. -/ +theorem eq_ofCoefficients_of_monic {w : Polynomial (AnalyticGerm ℂ (0 : E))} {d : ℕ} + (hm : w.Monic) (hd : w.natDegree = d) : + w = ofCoefficients (fun j : Fin d => w.coeff (j : ℕ)) := by + subst hd + exact hm.eq_X_pow_add_ofFn + +/-- Evaluating the distinguished-shape polynomial in the last coordinate gives the Weierstrass +polynomial built from analytic representatives of the coefficient germs. -/ +theorem polynomialHom_ofCoefficients {d : ℕ} (a : Fin d → E → ℂ) + (ha : ∀ j, AnalyticAt ℂ (a j) 0) : + polynomialHom (ofCoefficients (fun j => ofAnalyticAt (a j) (ha j))) = + ofAnalyticAt (weierstrassPolynomial a) (analyticAt_weierstrassPolynomial ha) := by + have hfst : AnalyticAt ℂ (Prod.fst : E × ℂ → E) 0 := analyticAt_fst + have hsnd : AnalyticAt ℂ (Prod.snd : E × ℂ → ℂ) 0 := analyticAt_snd + have hlc : (lastCoordinate : AnalyticGerm ℂ (0 : E × ℂ)) = ofAnalyticAt Prod.snd hsnd := rfl + rw [ofCoefficients, Polynomial.ofFn_eq_sum_monomial] + simp only [← Polynomial.C_mul_X_pow_eq_monomial] + simp only [map_add, map_sum, map_mul, map_pow, polynomialHom_C, polynomialHom_X, hlc] + have hstep : ∀ j : Fin d, parameterHom (ofAnalyticAt (a j) (ha j)) * + ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = + ofAnalyticAt (a j ∘ Prod.fst * Prod.snd ^ (j : ℕ)) + (((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) := by + intro j + have hpar := pullback_ofAnalyticAt Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (a j) (ha j) + show pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * + ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = _ + rw [hpar, ← ofAnalyticAt_pow, ofAnalyticAt_mul] + rw [Finset.sum_congr rfl (fun j _ => hstep j), + ← ofAnalyticAt_sum Finset.univ (fun j => a j ∘ Prod.fst * Prod.snd ^ (j : ℕ)) + (fun j => ((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) + (Finset.analyticAt_sum _ fun j _ => ((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))), + ← ofAnalyticAt_pow, ← ofAnalyticAt_add] + congr 1 + funext z + simp [weierstrassPolynomial, weierstrassRemainder, Function.comp] + +/-- A distinguished polynomial's image is regular of order equal to its degree: the Weierstrass +polynomial built from representatives of its coefficients has central slice `t ↦ t ^ d`, whose +order at the origin is exactly `d`. -/ +theorem orderInLastVariable_polynomialHom_of_isDistinguishedAt + {w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) : + orderInLastVariable (polynomialHom w) = w.natDegree := by + obtain ⟨hwmon, hwcoeff0⟩ := (isDistinguishedAt_iff w).mp hw + set d := w.natDegree with hd_def + have hweq : w = ofCoefficients (fun j : Fin d => w.coeff (j : ℕ)) := + eq_ofCoefficients_of_monic hwmon hd_def + choose a0 ha0 haeq using fun j : Fin d => exists_rep (w.coeff (j : ℕ)) + have ha00 : ∀ j : Fin d, a0 j 0 = 0 := by + intro j + have h0 := hwcoeff0 (j : ℕ) j.isLt + rw [← haeq j, eval_ofAnalyticAt] at h0 + exact h0 + have hweq2 : w = ofCoefficients (fun j : Fin d => ofAnalyticAt (a0 j) (ha0 j)) := by + rw [hweq]; congr 1; funext j; exact (haeq j).symm + have hwhom : polynomialHom w = ofAnalyticAt (weierstrassPolynomial a0) + (analyticAt_weierstrassPolynomial ha0) := by + rw [hweq2]; exact polynomialHom_ofCoefficients a0 ha0 + rw [hwhom, orderInLastVariable_ofAnalyticAt] + have hcentral : (fun t : ℂ => weierstrassPolynomial a0 (0, t)) = fun t : ℂ => t ^ d := + funext (weierstrassPolynomial_central ha00) + rw [hcentral] + show analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d + rw [analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ)) d, analyticOrderAt_id] + simp + +/-- The polynomial in `X` of degree below `d` with prescribed coefficient germs. -/ +@[expose] def remainderOfCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + Polynomial (AnalyticGerm ℂ (0 : E)) := + Polynomial.ofFn d b + +/-- The remainder-shape polynomial has degree strictly below `d`. -/ +theorem degree_remainderOfCoefficients_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : + (remainderOfCoefficients b).degree < (d : WithBot ℕ) := Polynomial.ofFn_degree_lt b + +/-- Any polynomial of degree below `d` is the remainder-shape polynomial built from its own +coefficients. -/ +theorem eq_remainderOfCoefficients_of_degree_lt {r : Polynomial (AnalyticGerm ℂ (0 : E))} {d : ℕ} + (hr : r.degree < (d : WithBot ℕ)) : + r = remainderOfCoefficients (fun j : Fin d => r.coeff (j : ℕ)) := + (Polynomial.ofFn_toFn_eq_of_degree_lt hr).symm + +/-- Evaluating the remainder-shape polynomial in the last coordinate gives the Weierstrass remainder +built from analytic representatives of the coefficient germs. -/ +theorem polynomialHom_remainderOfCoefficients {d : ℕ} (a : Fin d → E → ℂ) + (ha : ∀ j, AnalyticAt ℂ (a j) 0) : + polynomialHom (remainderOfCoefficients (fun j => ofAnalyticAt (a j) (ha j))) = + ofAnalyticAt (weierstrassRemainder a) (analyticAt_weierstrassRemainder ha) := by + have hfst : AnalyticAt ℂ (Prod.fst : E × ℂ → E) 0 := analyticAt_fst + have hsnd : AnalyticAt ℂ (Prod.snd : E × ℂ → ℂ) 0 := analyticAt_snd + have hlc : (lastCoordinate : AnalyticGerm ℂ (0 : E × ℂ)) = ofAnalyticAt Prod.snd hsnd := rfl + rw [remainderOfCoefficients, Polynomial.ofFn_eq_sum_monomial] + simp only [← Polynomial.C_mul_X_pow_eq_monomial] + simp only [map_sum, map_mul, map_pow, polynomialHom_C, polynomialHom_X, hlc] + have hstep : ∀ j : Fin d, parameterHom (ofAnalyticAt (a j) (ha j)) * + ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = + ofAnalyticAt (a j ∘ Prod.fst * Prod.snd ^ (j : ℕ)) + (((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) := by + intro j + have hpar := pullback_ofAnalyticAt Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (a j) (ha j) + show pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * + ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = _ + rw [hpar, ← ofAnalyticAt_pow, ofAnalyticAt_mul] + rw [Finset.sum_congr rfl (fun j _ => hstep j), + ← ofAnalyticAt_sum Finset.univ (fun j => a j ∘ Prod.fst * Prod.snd ^ (j : ℕ)) + (fun j => ((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) + (Finset.analyticAt_sum _ fun j _ => ((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ)))] + congr 1 + funext z + simp [weierstrassRemainder, Function.comp] + +/-- `remainderOfCoefficients` is additive in the coefficient tuple. -/ +theorem remainderOfCoefficients_add {d : ℕ} (a b : Fin d → AnalyticGerm ℂ (0 : E)) : + remainderOfCoefficients (a + b) = remainderOfCoefficients a + remainderOfCoefficients b := + map_add (Polynomial.ofFn d) a b + +/-- `remainderOfCoefficients` scales by a constant-polynomial factor under a common germ multiplier +on the coefficient tuple. -/ +theorem remainderOfCoefficients_smul {d : ℕ} (c : AnalyticGerm ℂ (0 : E)) + (a : Fin d → AnalyticGerm ℂ (0 : E)) : + remainderOfCoefficients (c • a) = Polynomial.C c * remainderOfCoefficients a := by + simpa only [remainderOfCoefficients, Polynomial.smul_eq_C_mul] using + (Polynomial.ofFn d).map_smul c a + +/-- `remainderOfCoefficients` commutes with finite sums of coefficient tuples. -/ +theorem remainderOfCoefficients_sum {d : ℕ} {ι : Type*} (s : Finset ι) + (v : ι → Fin d → AnalyticGerm ℂ (0 : E)) : + remainderOfCoefficients (∑ i ∈ s, v i) = ∑ i ∈ s, remainderOfCoefficients (v i) := + map_sum (Polynomial.ofFn d) v s + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean new file mode 100644 index 0000000000..5afa855a06 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean @@ -0,0 +1,270 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Order +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Coordinate changes and regular analytic germs + +Analytic changes of coordinates induce algebra isomorphisms on scalar germs. A nonzero germ on a +finite-dimensional parameter space times `ℂ` becomes regular in the scalar coordinate after a +complex linear change of coordinates. Finite families are normalized by applying the single-germ +theorem to their product. This includes the finite-family version discussed in [Suwa][Suwa2024] +§1.4; the unitary and countable-family refinements in [Jakóbczak–Jarnicki][JakobczakJarnicki2021], +Lemma 1.8.3 are not needed here. + +## Main definitions + +* `pullbackEquiv`: An analytic homeomorphism with analytic inverse induces an algebra isomorphism of + germs. +* `pullbackEquivOfEq`: Pullback equivalence along a map whose value at the source point is only + known up to a stated equation, letting the target germ's base point be phrased as any value equal + to `e x`. +* `linearEquivPullback`: Continuous linear coordinate changes act contravariantly on analytic germs. +* `translateEquiv`: Translation identifies the germs at any point with the germs at the origin. +* `linearEquivPullbackZero`: A linear change of coordinates fixes the origin and identifies the + corresponding germ rings. +* `orderInLastVariable`: Order of a scalar germ along the distinguished coordinate axis. +* `regularizingLinearEquiv`: A triangular linear coordinate change sends the last coordinate axis to + the line through `v`, provided the last coordinate of `v` is nonzero. + +## Main results + +* `exists_regular_coordinate_change`: A nonzero analytic germ can be made regular in the last + coordinate by an invertible complex linear change. +* `exists_regular_coordinate_change_finite`: One linear coordinate change makes every member of a + finite family of nonzero analytic germs regular in the last variable. +* `isUnit_iff_orderInLastVariable_eq_zero`: A germ is a unit exactly when it has order zero along + the distinguished coordinate. +* `orderInLastVariable_mul`: Order along the distinguished coordinate is additive under + multiplication of germs. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [T. Suwa, *Complex Analytic Geometry: From the Localization Viewpoint*][Suwa2024] +-/ + +public noncomputable section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables +namespace AnalyticGerm + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- An analytic homeomorphism with analytic inverse induces an algebra isomorphism of germs. -/ +@[expose] def pullbackEquiv (e : E ≃ₜ F) (x : E) (he : AnalyticAt ℂ e x) + (hi : AnalyticAt ℂ e.symm (e x)) : AnalyticGerm ℂ (e x) ≃ₐ[ℂ] AnalyticGerm ℂ x := + AlgEquiv.ofBijective (pullback e he) (by + constructor + · intro a b hab + obtain ⟨f, hf, rfl⟩ := exists_rep a + obtain ⟨g, hg, rfl⟩ := exists_rep b + have hh : (f ∘ e) =ᶠ[𝓝 x] (g ∘ e) := + Germ.coe_eq.mp (congrArg Subtype.val hab) + apply ofAnalyticAt_eq_iff.mpr + have ht : Tendsto e.symm (𝓝 (e x)) (𝓝 x) := by + simpa using e.symm.continuous.tendsto (e x) + simpa only [Function.comp_def, e.apply_symm_apply] using hh.comp_tendsto ht + · intro a + obtain ⟨f, hf, rfl⟩ := exists_rep a + refine ⟨ofAnalyticAt (f ∘ e.symm) (hf.comp_of_eq hi (e.symm_apply_apply x)), ?_⟩ + apply Subtype.ext + apply Germ.coe_eq.mpr + exact .of_forall fun y => by simp [Function.comp_def]) + +/-- Pullback equivalence along a map whose value at the source point is only known up to a stated +equation, letting the target germ's base point be phrased as any value equal to `e x`. Matches +`pullbackEquiv` definitionally once the equation is substituted. -/ +def pullbackEquivOfEq (e : E ≃ₜ F) (x : E) (he : AnalyticAt ℂ e x) + (hi : AnalyticAt ℂ e.symm (e x)) {y : F} (hy : e x = y) : + AnalyticGerm ℂ y ≃ₐ[ℂ] AnalyticGerm ℂ x := + hy ▸ pullbackEquiv e x he hi + +/-- Applying an equation-adjusted pullback equivalence to a represented germ is represented by +composition, matching the plain pullback. -/ +theorem pullbackEquivOfEq_ofAnalyticAt (e : E ≃ₜ F) (x : E) (he : AnalyticAt ℂ e x) + (hi : AnalyticAt ℂ e.symm (e x)) {y : F} (hy : e x = y) (g : F → ℂ) + (hg : AnalyticAt ℂ g y) : + pullbackEquivOfEq e x he hi hy (ofAnalyticAt g hg) = + ofAnalyticAt (g ∘ e) (hg.comp_of_eq he hy) := by + subst hy + rfl + +/-- An equation-adjusted pullback equivalence is bijective, like the plain pullback equivalence it +matches definitionally. -/ +theorem pullbackEquivOfEq_bijective (e : E ≃ₜ F) (x : E) (he : AnalyticAt ℂ e x) + (hi : AnalyticAt ℂ e.symm (e x)) {y : F} (hy : e x = y) : + Function.Bijective (pullbackEquivOfEq e x he hi hy) := by + subst hy + exact (pullbackEquiv e x he hi).bijective + +/-- Continuous linear coordinate changes act contravariantly on analytic germs. -/ +def linearEquivPullback (e : E ≃L[ℂ] F) (x : E) : + AnalyticGerm ℂ (e x) ≃ₐ[ℂ] AnalyticGerm ℂ x := + pullbackEquiv e.toHomeomorph x (e.toContinuousLinearMap.analyticAt x) + (e.symm.toContinuousLinearMap.analyticAt (e x)) + +/-- Translation identifies the germs at any point with the germs at the origin. -/ +def translateEquiv (x : E) : AnalyticGerm ℂ x ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E) := by + have e : AnalyticGerm ℂ (0 + x) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E) := + pullbackEquiv (Homeomorph.addRight x) 0 + (analyticAt_id.add analyticAt_const) (by + change AnalyticAt ℂ (fun y : E => y + -x) _ + exact analyticAt_id.add analyticAt_const) + exact (zero_add x) ▸ e + +/-- A linear change of coordinates fixes the origin and identifies the corresponding germ rings. -/ +def linearEquivPullbackZero (e : E ≃L[ℂ] F) : + AnalyticGerm ℂ (0 : F) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E) := by + have h := linearEquivPullback e (0 : E) + exact (e.map_zero) ▸ h + +/-- Order of a scalar germ along the distinguished coordinate axis. The definition uses Mathlib's +one-variable analytic order and is independent of representatives. -/ +@[expose] def orderInLastVariable (φ : AnalyticGerm ℂ (0 : E × ℂ)) : ℕ∞ := + φ.val.liftOn (fun f => analyticOrderAt (fun w : ℂ => f (0, w)) 0) (by + intro f g h + have ht : Tendsto (fun w : ℂ => ((0 : E), w)) (𝓝 0) (𝓝 0) := + (continuous_const.prodMk continuous_id).tendsto 0 + exact analyticOrderAt_congr (h.comp_tendsto ht)) + +/-- The order of a represented germ is the order of its central scalar slice. -/ +@[simp] theorem orderInLastVariable_ofAnalyticAt (f : E × ℂ → ℂ) (hf : AnalyticAt ℂ f 0) : + orderInLastVariable (ofAnalyticAt f hf) = analyticOrderAt (fun w : ℂ => f (0, w)) 0 := rfl + +/-- The central slice of a represented germ is analytic at the scalar origin. -/ +theorem analyticAt_ofAnalyticAt_central (f : E × ℂ → ℂ) (hf : AnalyticAt ℂ f 0) : + AnalyticAt ℂ (fun w : ℂ => f (0, w)) 0 := + hf.comp_of_eq (analyticAt_const.prod analyticAt_id) rfl + +/-- Order along the distinguished coordinate is additive under multiplication of germs. -/ +theorem orderInLastVariable_mul (φ ψ : AnalyticGerm ℂ (0 : E × ℂ)) : + orderInLastVariable (φ * ψ) = orderInLastVariable φ + orderInLastVariable ψ := by + obtain ⟨f, hf, rfl⟩ := exists_rep φ + obtain ⟨g, hg, rfl⟩ := exists_rep ψ + rw [← ofAnalyticAt_mul] + simp only [orderInLastVariable_ofAnalyticAt] + exact analyticOrderAt_mul (analyticAt_ofAnalyticAt_central f hf) + (analyticAt_ofAnalyticAt_central g hg) + +/-- A germ is a unit exactly when it has order zero along the distinguished coordinate. -/ +theorem isUnit_iff_orderInLastVariable_eq_zero (φ : AnalyticGerm ℂ (0 : E × ℂ)) : + IsUnit φ ↔ orderInLastVariable φ = 0 := by + obtain ⟨f, hf, rfl⟩ := exists_rep φ + rw [isUnit_iff, eval_ofAnalyticAt, orderInLastVariable_ofAnalyticAt] + exact (analyticAt_ofAnalyticAt_central f hf).analyticOrderAt_eq_zero.symm + +end AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A triangular linear coordinate change sends the last coordinate axis to the line through `v`, +provided the last coordinate of `v` is nonzero. -/ +def regularizingLinearEquiv (v : E × ℂ) (hv : v.2 ≠ 0) : (E × ℂ) ≃ₗ[ℂ] (E × ℂ) where + toFun z := (z.1 + z.2 • v.1, z.2 * v.2) + invFun z := (z.1 - (z.2 / v.2) • v.1, z.2 / v.2) + left_inv z := by simp [hv] + right_inv z := by simp [hv] + map_add' z w := by + ext <;> simp [add_smul, add_mul]; module + map_smul' c z := by + ext <;> simp [smul_add, mul_smul, smul_eq_mul, mul_assoc] + +/-- A nonzero analytic germ can be made regular in the last coordinate by an invertible complex +linear change. The resulting order is finite, including order zero for units. Empty parameter +spaces are allowed, since the scalar coordinate is always present. -/ +theorem exists_regular_coordinate_change [FiniteDimensional ℂ E] + {f : E × ℂ → ℂ} (hf : AnalyticAt ℂ f 0) (hne : ¬ f =ᶠ[𝓝 0] 0) : + ∃ (L : (E × ℂ) ≃L[ℂ] (E × ℂ)) (d : ℕ), + analyticOrderAt (fun w : ℂ => f (L (0, w))) 0 = d := by + have hsnd : ¬ (Prod.snd : E × ℂ → ℂ) =ᶠ[𝓝 0] 0 := by + intro h + have ht : Tendsto (fun w : ℂ => ((0 : E), w)) (𝓝 0) (𝓝 0) := by + exact (continuous_const.prodMk continuous_id).tendsto 0 + have hi : (id : ℂ → ℂ) =ᶠ[𝓝 0] 0 := h.comp_tendsto ht + have ho := analyticOrderAt_eq_top.mpr hi + simp at ho + have hprod : ¬ (fun z : E × ℂ => f z * z.2) =ᶠ[𝓝 0] 0 := by + intro h + exact (eventuallyEq_zero_or_eventuallyEq_zero_of_mul hf analyticAt_snd h).elim hne hsnd + obtain ⟨r, hr, hfa⟩ := hf.exists_ball_analyticOnNhd + obtain ⟨v, hvball, hfv⟩ : ∃ v ∈ ball (0 : E × ℂ) r, f v * v.2 ≠ 0 := by + by_contra! h + exact hprod (Filter.mem_of_superset (ball_mem_nhds 0 hr) (fun z hz => h z hz)) + have hv : v.2 ≠ 0 := (mul_ne_zero_iff.mp hfv).2 + have hvn : 0 < ‖v‖ := norm_pos_iff.mpr (fun h => hv (by simp [h])) + have hline : AnalyticOnNhd ℂ (fun w : ℂ => f (w • v)) (ball 0 (r / ‖v‖)) := by + intro w hw + have hmem : w • v ∈ ball (0 : E × ℂ) r := by + rw [mem_ball_zero_iff, norm_smul] + exact (lt_div_iff₀ hvn).mp (mem_ball_zero_iff.mp hw) + have hs : AnalyticAt ℂ (fun t : ℂ => t • v) w := analyticAt_id.smul analyticAt_const + exact (hfa _ hmem).comp_of_eq hs rfl + have hlinene : analyticOrderAt (fun w : ℂ => f (w • v)) 0 ≠ ⊤ := by + intro h + have heq := hline.eqOn_zero_of_preconnected_of_eventuallyEq_zero + (convex_ball (0 : ℂ) (r / ‖v‖)).isPreconnected (mem_ball_self (div_pos hr hvn)) + (analyticOrderAt_eq_top.mp h) + have h1 : (1 : ℂ) ∈ ball 0 (r / ‖v‖) := by + rw [mem_ball_zero_iff, norm_one, lt_div_iff₀ hvn, one_mul] + exact mem_ball_zero_iff.mp hvball + exact (mul_ne_zero_iff.mp hfv).1 (by simpa using heq h1) + obtain ⟨d, hd⟩ := ENat.ne_top_iff_exists.mp hlinene + refine ⟨(regularizingLinearEquiv v hv).toContinuousLinearEquiv, d, ?_⟩ + convert hd.symm using 1 + congr 1 + funext w + simp [regularizingLinearEquiv] + rfl + +/-- One linear coordinate change makes every member of a finite family of nonzero analytic germs +regular in the last variable. Empty families and unit germs are allowed. Apply single-germ +normalization to the product, then use that no factor slice can vanish. -/ +theorem exists_regular_coordinate_change_finite [FiniteDimensional ℂ E] + {κ : Type*} [Fintype κ] {f : κ → E × ℂ → ℂ} + (hf : ∀ i, AnalyticAt ℂ (f i) 0) (hne : ∀ i, ¬ f i =ᶠ[𝓝 0] 0) : + ∃ (L : (E × ℂ) ≃L[ℂ] (E × ℂ)) (d : κ → ℕ), + ∀ i, analyticOrderAt (fun w : ℂ => f i (L (0, w))) 0 = d i := by + classical + have hp : ∀ s : Finset κ, ¬ (fun z => ∏ i ∈ s, f i z) =ᶠ[𝓝 0] 0 := by + intro s + induction s using Finset.induction_on with + | empty => + intro h + have h0 := h.self_of_nhds + simp at h0 + | @insert i s hi ih => + simp only [Finset.prod_insert hi] + intro h + exact (eventuallyEq_zero_or_eventuallyEq_zero_of_mul (hf i) + (s.analyticAt_fun_prod (fun j _ => hf j)) h).elim (hne i) ih + obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change + (Finset.univ.analyticAt_fun_prod (fun i _ => hf i)) (hp Finset.univ) + have hfin : ∀ i, analyticOrderAt (fun w : ℂ => f i (L (0, w))) 0 ≠ ⊤ := by + intro i hi + have he := analyticOrderAt_eq_top.mp hi + have hz : (fun w : ℂ => ∏ j, f j (L (0, w))) =ᶠ[𝓝 0] 0 := by + filter_upwards [he] with w hw + exact Finset.prod_eq_zero (Finset.mem_univ i) hw + have ht := analyticOrderAt_eq_top.mpr hz + rw [hd] at ht + simp at ht + refine ⟨L, fun i => (analyticOrderAt (fun w : ℂ => f i (L (0, w))) 0).toNat, ?_⟩ + intro i + exact (ENat.natCast_toNat (hfin i)).symm + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Elimination.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Elimination.lean new file mode 100644 index 0000000000..c828bf70d6 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Elimination.lean @@ -0,0 +1,129 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.LinearAlgebra.Matrix.ToLinearEquiv +public import Mathlib.RingTheory.Polynomial.Resultant.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass + +/-! +# Elimination of the scalar variable for relatively prime germs + +A distinguished polynomial and a relatively prime polynomial germ have nonzero resultant. The +proof uses Weierstrass division to show injectivity of the Sylvester map. Its adjugate then +supplies a nonzero parameter germ in the generated ideal. + +## Main results + +`resultant_ne_zero_of_isRelPrime_polynomialHom` is nonvanishing of the resultant of a +distinguished polynomial and a relatively prime polynomial germ. +`exists_base_combination_of_isRelPrime` produces a nonzero parameter germ in the generated +ideal. `sylvesterMap_injective_of_isRelPrime` is injectivity of the Sylvester map. +-/ + +public noncomputable section + +open Polynomial + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + +/-- A polynomial of smaller degree divisible as a germ by a distinguished polynomial is zero. -/ +theorem eq_zero_of_degree_lt_of_polynomialHom_dvd + {p w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (hdeg : p.degree < (w.natDegree : WithBot ℕ)) + (hdiv : polynomialHom w ∣ polynomialHom p) : p = 0 := by + obtain ⟨q, hq⟩ := hdiv + obtain ⟨r, hr⟩ := exists_polynomial_quotient p w hw q (by rw [hq, mul_comm]) + have hd : w ∣ p := ⟨r, polynomialHom_injective (by rw [map_mul, hr, hq])⟩ + by_contra hp + have := Polynomial.degree_le_of_dvd hd hp + rw [Polynomial.degree_eq_natDegree hw.monic.ne_zero] at this + exact (not_lt_of_ge this) hdeg + +/-- Relative primality of the germs makes the Sylvester map injective. -/ +private theorem sylvesterMap_injective_of_isRelPrime + {w p : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (hrel : IsRelPrime (polynomialHom w) (polynomialHom p)) : + Function.Injective (Polynomial.sylvesterMap w p le_rfl le_rfl) := by + apply (injective_iff_map_eq_zero _).mpr + intro q hq + have he : w * q.2.val + p * q.1.val = 0 := congrArg Subtype.val hq + have he' : polynomialHom w * polynomialHom q.2.val + + polynomialHom p * polynomialHom q.1.val = 0 := by + simpa only [map_add, map_mul, map_zero] using congrArg polynomialHom he + have hd : polynomialHom w ∣ polynomialHom q.1.val := + hrel.dvd_of_dvd_mul_left ⟨-polynomialHom q.2.val, by linear_combination he'⟩ + have hq1 : q.1.val = 0 := eq_zero_of_degree_lt_of_polynomialHom_dvd hw + (Polynomial.mem_degreeLT.mp q.1.property) hd + have hq2 : q.2.val = 0 := by + simpa only [hq1, mul_zero, add_zero, mul_eq_zero, hw.monic.ne_zero, false_or] using he + exact Prod.ext (Subtype.ext hq1) (Subtype.ext hq2) + +/-- A distinguished polynomial relatively prime to another polynomial as an analytic germ has +nonzero resultant in the parameter germ ring. -/ +theorem resultant_ne_zero_of_isRelPrime_polynomialHom + {w p : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (hrel : IsRelPrime (polynomialHom w) (polynomialHom p)) : w.resultant p ≠ 0 := by + let R := AnalyticGerm ℂ (0 : E) + let T := Polynomial.sylvesterMap w p le_rfl le_rfl + let b₁ := ((Polynomial.degreeLT.basis R w.natDegree).prod + (Polynomial.degreeLT.basis R p.natDegree)).reindex finSumFinEquiv + let b₂ := Polynomial.degreeLT.basis R (w.natDegree + p.natDegree) + have hM : T.toMatrix b₁ b₂ = Polynomial.sylvester w p w.natDegree p.natDegree := + Polynomial.toMatrix_sylvesterMap' w p le_rfl le_rfl + intro hz + obtain ⟨v, hv, hMv⟩ := Matrix.exists_mulVec_eq_zero_iff.mpr hz + let q := b₁.equivFun.symm v + have hrepr : (b₁.repr q : Fin (w.natDegree + p.natDegree) → R) = v := + b₁.equivFun.apply_symm_apply v + have hTq : T q = 0 := by + apply b₂.equivFun.injective + change (b₂.repr (T q) : Fin (w.natDegree + p.natDegree) → R) = b₂.equivFun 0 + rw [← T.toMatrix_mulVec_repr b₁ b₂ q, hM, hrepr, hMv, map_zero] + have hq : q = 0 := (sylvesterMap_injective_of_isRelPrime hw hrel) (hTq.trans (map_zero T).symm) + exact hv (by rw [← hrepr, hq, map_zero]; rfl) + +/-- Eliminating the scalar variable puts a nonzero parameter germ in the ideal generated by two +relatively prime germs, the first of finite order in the scalar variable. -/ +theorem exists_base_combination_of_isRelPrime + {f g : AnalyticGerm ℂ (0 : E × ℂ)} {d : ℕ} (hd : orderInLastVariable f = d) + (hrel : IsRelPrime f g) : + ∃ h : AnalyticGerm ℂ (0 : E), h ≠ 0 ∧ + ∃ a b : AnalyticGerm ℂ (0 : E × ℂ), basePullback 0 h = a * f + b * g := by + obtain ⟨⟨u, w⟩, ⟨hw, _, hfact⟩, _⟩ := existsUnique_preparation f hd + have hrel' : IsRelPrime (polynomialHom w) g := by + rw [hfact] at hrel + exact hrel.of_mul_left_right + by_cases hw0 : w.natDegree = 0 + · have hw1 : w = 1 := Polynomial.eq_one_of_monic_natDegree_zero hw.monic hw0 + refine ⟨1, one_ne_zero, ↑u⁻¹, 0, ?_⟩ + simp [hfact, hw1] + obtain ⟨⟨q, p⟩, ⟨_, hdiv⟩, _⟩ := existsUnique_division w hw g + have hwp : IsRelPrime (polynomialHom w) (polynomialHom p) := by + rw [hdiv] at hrel' + exact hrel'.of_mul_add_right_right + have hres := resultant_ne_zero_of_isRelPrime_polynomialHom hw hwp + obtain ⟨a, b, _, _, hab⟩ := Polynomial.exists_mul_add_mul_eq_C_resultant + w p le_rfl le_rfl (Or.inl hw0) + have hcomb : basePullback 0 (w.resultant p) = + polynomialHom w * polynomialHom a + polynomialHom p * polynomialHom b := by + simpa only [map_add, map_mul, polynomialHom_C, parameterHom, basePullback] using + (congrArg polynomialHom hab).symm + refine ⟨w.resultant p, hres, ↑u⁻¹ * (polynomialHom a - q * polynomialHom b), + polynomialHom b, ?_⟩ + rw [hcomb, hfact, hdiv] + have hu : (↑u⁻¹ : AnalyticGerm ℂ (0 : E × ℂ)) * ↑u = 1 := u.inv_val + linear_combination -(polynomialHom a - q * polynomialHom b) * polynomialHom w * hu + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Factorization.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Factorization.lean new file mode 100644 index 0000000000..ba36c8f5a3 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Factorization.lean @@ -0,0 +1,124 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.Coprime.Basic +public import Mathlib.RingTheory.Noetherian.UniqueFactorizationDomain +public import Mathlib.RingTheory.UniqueFactorizationDomain.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial + +/-! +# Elementary factorization of analytic germs + +[Jakóbczak–Jarnicki][JakobczakJarnicki2021], Proposition 1.8.4: scalar analytic germ rings in +finite dimension are unique factorization domains. The analytic ingredient is that an +irreducible germ is prime. Together with Noetherianity this supplies Mathlib's +`UniqueFactorizationMonoid` instance and its usual existence and uniqueness results. + +The source's “relatively prime” is expressed as `IsRelPrime`, meaning that common divisors are +units. It is not `IsCoprime`: two germs vanishing at the base point cannot generate the unit +ideal. No geometric conclusions from §1.8.5 are included. + +## Main results + +* `prime_of_irreducible`: Irreducible analytic germs are prime in finite dimension: transport to the + origin of a coordinate presentation using the induction on dimension above. +* `exists_prime_factors`: Every nonzero analytic germ is associated to a finite product of prime + germs. +* `factors_unique`: Irreducible factorizations agree up to reordering and multiplication by units. +* `isRelPrime_iff_common_divisors`: Relative primality of germs means that every common divisor is a + unit. +* `not_isCoprime_of_eval_eq_zero`: Two germs vanishing at the base point cannot generate the unit + ideal. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] {x : E} + +/-- Two germs vanishing at the base point cannot generate the unit ideal. This does not prevent them +from being relatively prime in the factorization sense. -/ +theorem not_isCoprime_of_eval_eq_zero {f g : AnalyticGerm ℂ x} + (hf : eval x f = 0) (hg : eval x g = 0) : ¬ IsCoprime f g := by + rintro ⟨a, b, h⟩ + have he := congrArg (eval x) h + simp [hf, hg] at he + +/-- Irreducible germs on `n` complex coordinates are prime, by induction using +`prime_of_irreducible_of_baseUFD`. Dimension zero has no irreducible elements, since the germ +ring there is a field. -/ +theorem prime_of_irreducible_coordinates (n : ℕ) : + ∀ {f : AnalyticGerm ℂ (0 : Fin n → ℂ)}, Irreducible f → Prime f := by + induction n with + | zero => + intro f hf + exfalso + set e := equivScalarOfSubsingleton ℂ (0 : Fin 0 → ℂ) + have hf' : Irreducible (e f) := hf.map e + rcases eq_or_ne (e f) 0 with h0 | h0 + · rw [h0] at hf' + exact (hf'.isUnit_or_isUnit (by ring)).elim not_isUnit_zero not_isUnit_zero + · exact hf'.not_isUnit (isUnit_iff_ne_zero.mpr h0) + | succ n ih => + intro f hf + have : UniqueFactorizationMonoid (AnalyticGerm ℂ (0 : Fin n → ℂ)) := + { irreducible_iff_prime := ⟨ih, Prime.irreducible⟩ } + let e : (Fin (n + 1) → ℂ) ≃ₗ[ℂ] (Fin n → ℂ) × ℂ := + (LinearEquiv.piCongrLeft ℂ (fun _ => ℂ) (finSuccEquiv n)).trans + ((LinearEquiv.piOptionEquivProd ℂ).trans (LinearEquiv.prodComm ℂ _ _)) + set eqv : AnalyticGerm ℂ (0 : Fin (n + 1) → ℂ) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : (Fin n → ℂ) × ℂ) := + (linearEquivPullbackZero e.toContinuousLinearEquiv).symm with heqv + have hfe : Irreducible (eqv f) := hf.map eqv + have hpe : Prime (eqv f) := prime_of_irreducible_of_baseUFD hfe + exact (MulEquiv.prime_iff eqv).mp hpe + +/-- Irreducible analytic germs are prime in finite dimension: transport to the origin of a +coordinate presentation using the induction on dimension above. -/ +theorem prime_of_irreducible [FiniteDimensional ℂ E] {f : AnalyticGerm ℂ x} + (hf : Irreducible f) : Prime f := by + let e := (Module.finBasis ℂ E).equivFunL + set eqv0 : AnalyticGerm ℂ (0 : E) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : Fin (Module.finrank ℂ E) → ℂ) := + (linearEquivPullbackZero e).symm with heqv0 + set eqvx : AnalyticGerm ℂ x ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E) := translateEquiv x with heqvx + have hf1 : Irreducible (eqvx f) := hf.map eqvx + have hf2 : Irreducible (eqv0 (eqvx f)) := hf1.map eqv0 + have hp2 : Prime (eqv0 (eqvx f)) := prime_of_irreducible_coordinates _ hf2 + have hp1 : Prime (eqvx f) := (MulEquiv.prime_iff eqv0).mp hp2 + exact (MulEquiv.prime_iff eqvx).mp hp1 + +/-- The finite-dimensional analytic germ ring is a unique factorization domain. This instance +combines Noetherianity with the prime-germ lemma. -/ +instance [FiniteDimensional ℂ E] : UniqueFactorizationMonoid (AnalyticGerm ℂ x) where + irreducible_iff_prime := ⟨prime_of_irreducible, Prime.irreducible⟩ + +/-- Every nonzero analytic germ is associated to a finite product of prime germs. The empty product +accounts for units, including all nonzero zero-dimensional germs. -/ +theorem exists_prime_factors [FiniteDimensional ℂ E] (f : AnalyticGerm ℂ x) (hf : f ≠ 0) : + ∃ s : Multiset (AnalyticGerm ℂ x), (∀ p ∈ s, Prime p) ∧ Associated s.prod f := + UniqueFactorizationMonoid.exists_prime_factors f hf + +/-- Irreducible factorizations agree up to reordering and multiplication by units. -/ +theorem factors_unique [FiniteDimensional ℂ E] {s t : Multiset (AnalyticGerm ℂ x)} + (hs : ∀ p ∈ s, Irreducible p) (ht : ∀ p ∈ t, Irreducible p) + (h : Associated s.prod t.prod) : Multiset.Rel Associated s t := + UniqueFactorizationMonoid.factors_unique hs ht h + +/-- Relative primality of germs means that every common divisor is a unit. -/ +theorem isRelPrime_iff_common_divisors {f g : AnalyticGerm ℂ x} : + IsRelPrime f g ↔ ∀ d, d ∣ f → d ∣ g → IsUnit d := by + rfl + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Fiber.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Fiber.lean new file mode 100644 index 0000000000..220d6e8404 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Fiber.lean @@ -0,0 +1,135 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization + +/-! +# Parameter germs and restriction to a fiber + +Adding an unused scalar variable preserves irreducible germs. Consequently a nonzero parameter +germ is relatively prime to every germ whose restriction to the scalar fiber is nonzero. This is +the local algebra needed for persistence of relative primality. + +## Main results + +`basePullback` pulls a parameter germ back along projection, adding an unused scalar variable; +`fiberPullback` restricts a germ to the scalar fiber. `irreducible_basePullback` preserves +irreducibility. `isRelPrime_basePullback_of_fiber_ne_zero` is relative primality of a nonzero +parameter germ to a germ with nonzero fiber restriction. `eventually_fiber_ne_zero_ofAnalyticAt` +is persistence of a nonzero fiber germ. +-/ + +public noncomputable section + +open Filter Set Metric +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Regard a parameter germ as a germ independent of the scalar variable. -/ +@[expose] def basePullback (y : E × ℂ) : AnalyticGerm ℂ y.1 →ₐ[ℂ] AnalyticGerm ℂ y := + pullback Prod.fst analyticAt_fst + +/-- Restrict a germ to the scalar fiber through its base point. -/ +def fiberPullback (y : E × ℂ) : AnalyticGerm ℂ y →ₐ[ℂ] AnalyticGerm ℂ y.2 := + pullback (fun w : ℂ => (y.1, w)) (analyticAt_const.prod analyticAt_id) + +/-- A parameter germ vanishing at its base point restricts to zero on the scalar fiber. -/ +theorem fiberPullback_basePullback_eq_zero (y : E × ℂ) {p : AnalyticGerm ℂ y.1} + (hp : ¬ IsUnit p) : fiberPullback y (basePullback y p) = 0 := by + obtain ⟨g, hg, rfl⟩ := exists_rep p + have h0 : g y.1 = 0 := by simpa only [isUnit_iff, eval_ofAnalyticAt, not_not] using hp + change ofAnalyticAt (fun _ : ℂ => g y.1) analyticAt_const = + ofAnalyticAt (0 : ℂ → ℂ) analyticAt_const + apply ofAnalyticAt_eq_iff.mpr + exact Filter.Eventually.of_forall (fun _ => h0) + +/-- Adding an unused scalar variable preserves irreducibility of a parameter germ. -/ +theorem irreducible_basePullback (y : E × ℂ) {p : AnalyticGerm ℂ y.1} (hp : Irreducible p) : + Irreducible (basePullback y p) := by + let s : AnalyticGerm ℂ y →ₐ[ℂ] AnalyticGerm ℂ y.1 := + pullback (fun z : E => (z, y.2)) (analyticAt_id.prod analyticAt_const) + have hs (q : AnalyticGerm ℂ y.1) : s (basePullback y q) = q := by + obtain ⟨g, hg, rfl⟩ := exists_rep q + rfl + refine ⟨fun hu => hp.not_isUnit ((isUnit_pullback_iff _ _ p).mp hu), ?_⟩ + intro a b hab + have he : p = s a * s b := by rw [← hs p, hab, map_mul] + have hu (q : AnalyticGerm ℂ y) : IsUnit (s q) ↔ IsUnit q := by + simp only [s, isUnit_iff, eval_pullback] + exact (hp.isUnit_or_isUnit he).imp (hu a).mp (hu b).mp + +/-- A nonzero parameter germ is relatively prime to a germ nonzero on its scalar fiber. -/ +theorem isRelPrime_basePullback_of_fiber_ne_zero [FiniteDimensional ℂ E] + (y : E × ℂ) {p : AnalyticGerm ℂ y.1} (hp : p ≠ 0) {f : AnalyticGerm ℂ y} + (hf : fiberPullback y f ≠ 0) : IsRelPrime (basePullback y p) f := by + induction p using UniqueFactorizationMonoid.induction_on_prime with + | h₁ => exact (hp rfl).elim + | h₂ p hu => exact (hu.map (basePullback y)).isRelPrime_left + | h₃ p q hp0 hq ih => + rw [map_mul] + apply IsRelPrime.mul_left _ (ih hp0) + apply (irreducible_basePullback y hq.irreducible).isRelPrime_iff_not_dvd.mpr + intro hdiv + have h := map_dvd (fiberPullback y) hdiv + rw [fiberPullback_basePullback_eq_zero y hq.not_isUnit] at h + exact hf (zero_dvd_iff.mp h) + +/-- A represented analytic germ is nonzero exactly when the representative is not locally zero. -/ +theorem ofAnalyticAt_ne_zero_iff {f : E → ℂ} {x : E} (hf : AnalyticAt ℂ f x) : + ofAnalyticAt f hf ≠ 0 ↔ ¬ f =ᶠ[𝓝 x] 0 := by + change ofAnalyticAt f hf ≠ ofAnalyticAt (0 : E → ℂ) analyticAt_const ↔ _ + exact not_congr ofAnalyticAt_eq_iff + +/-- A nonzero analytic germ has nonzero germs at all sufficiently nearby points. -/ +theorem eventually_ne_zero_ofAnalyticAt {f : E → ℂ} {x : E} (hf : AnalyticAt ℂ f x) + (hne : ofAnalyticAt f hf ≠ 0) : + ∀ᶠ y in 𝓝 x, ∃ hy : AnalyticAt ℂ f y, ofAnalyticAt f hy ≠ 0 := by + obtain ⟨r, hr, hfr⟩ := hf.exists_ball_analyticOnNhd + filter_upwards [ball_mem_nhds x hr] with y hy + refine ⟨hfr y hy, ?_⟩ + rw [ofAnalyticAt_ne_zero_iff] + intro hzero + have he := hfr.eqOn_zero_of_preconnected_of_eventuallyEq_zero isPreconnected_ball hy hzero + exact (ofAnalyticAt_ne_zero_iff hf).mp hne + (Filter.mem_of_superset (ball_mem_nhds x hr) (fun z hz => he hz)) + +/-- Nonvanishing of the central fiber germ persists for nearby scalar fiber germs. -/ +theorem eventually_fiber_ne_zero_ofAnalyticAt {f : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hne : ¬ (fun w : ℂ => f (0, w)) =ᶠ[𝓝 0] 0) : + ∀ᶠ y in 𝓝 (0 : E × ℂ), ∃ hy : AnalyticAt ℂ f y, + fiberPullback y (ofAnalyticAt f hy) ≠ 0 := by + obtain ⟨r, hr, hfr⟩ := hf.exists_ball_analyticOnNhd + have hprod : AnalyticOnNhd ℂ f (ball (0 : E) r ×ˢ ball (0 : ℂ) r) := by + simpa only [ball_prod_same, Prod.mk_zero_zero] using hfr + obtain ⟨w, hw, hfw⟩ : ∃ w ∈ ball (0 : ℂ) r, f (0, w) ≠ 0 := by + by_contra! h + exact hne (Filter.mem_of_superset (ball_mem_nhds 0 hr) h) + have hc : ContinuousAt (fun a : E => f (a, w)) 0 := + (hprod (0, w) ⟨mem_ball_self hr, hw⟩).continuousAt.comp_of_eq + (continuousAt_id.prodMk continuousAt_const) rfl + have hb : ∀ᶠ y : E × ℂ in 𝓝 0, f (y.1, w) ≠ 0 := + (continuous_fst.continuousAt : Tendsto (Prod.fst : E × ℂ → E) (𝓝 0) (𝓝 0)).eventually + (hc.eventually_ne hfw) + filter_upwards [((isOpen_ball.prod isOpen_ball).mem_nhds + (show (0 : E × ℂ) ∈ ball (0 : E) r ×ˢ ball (0 : ℂ) r from + ⟨mem_ball_self hr, mem_ball_self hr⟩)), hb] with y hy hfyw + refine ⟨hprod y hy, ?_⟩ + have hslice : AnalyticOnNhd ℂ (fun t : ℂ => f (y.1, t)) (ball 0 r) := by + intro t ht + exact (hprod (y.1, t) ⟨hy.1, ht⟩).comp_of_eq (analyticAt_const.prod analyticAt_id) rfl + change ofAnalyticAt (fun t : ℂ => f (y.1, t)) (hslice y.2 hy.2) ≠ 0 + rw [ofAnalyticAt_ne_zero_iff] + intro hzero + exact hfyw (hslice.eqOn_zero_of_preconnected_of_eventuallyEq_zero + isPreconnected_ball hy.2 hzero hw) + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/IntrinsicOrder.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/IntrinsicOrder.lean new file mode 100644 index 0000000000..f282937fcb --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/IntrinsicOrder.lean @@ -0,0 +1,142 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.MvPowerSeries.Rename +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order + +/-! +# Coordinate-independent order of analytic germs + +`inCoordinates` transports a germ to a finite coordinate space. `orderInCoordinates` is +independent of the continuous complex-linear coordinates, so `intrinsicOrder` defines total +order on every finite-dimensional complex normed space, including zero-dimensional spaces. The +coordinate Taylor implementation remains in `Order`. `finiteIndexTaylorSeries` supplies a Taylor +series indexed by any finite coordinate type. + +## Main definitions + +* `inCoordinates`: Express a germ in continuous complex-linear coordinates, by pulling back the + inverse map. +* `orderInCoordinates`: The total order computed in a chosen system of continuous linear + coordinates. +* `intrinsicOrder`: Total order of an analytic germ on a finite-dimensional complex normed space. +* `finiteIndexTaylorSeries`: Taylor series with variables indexed by an arbitrary finite coordinate + type. + +## Main results + +* `intrinsicOrder_eq_orderInCoordinates`: Intrinsic order can be computed using any continuous + complex-linear coordinate system. +* `intrinsicOrder_eq_order`: Intrinsic order agrees with the original order on finite coordinate + spaces. +* `intrinsicOrder_mul`: Intrinsic order is additive under multiplication. +* `intrinsicOrder_eq_top_iff`: A germ has infinite intrinsic order exactly when it is zero. +-/ + +public noncomputable section +open Filter +open scoped Topology +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] {x : E} {n m : ℕ} + +/-- Express a germ in continuous complex-linear coordinates, by pulling back the inverse map. -/ +def inCoordinates (L : E ≃L[ℂ] (Fin n → ℂ)) (x : E) : + AnalyticGerm ℂ x ≃ₐ[ℂ] AnalyticGerm ℂ (L x) := + pullbackEquivOfEq L.symm.toHomeomorph (L x) + (L.symm.toContinuousLinearMap.analyticAt _) (L.toContinuousLinearMap.analyticAt _) + (L.symm_apply_apply x) + +/-- A represented germ in coordinates is represented by composition with the inverse map. -/ +theorem inCoordinates_ofAnalyticAt (L : E ≃L[ℂ] (Fin n → ℂ)) + (f : E → ℂ) (hf : AnalyticAt ℂ f x) : + inCoordinates L x (ofAnalyticAt f hf) = + ofAnalyticAt (f ∘ L.symm) + (hf.comp_of_eq (L.symm.toContinuousLinearMap.analyticAt _) (L.symm_apply_apply x)) := + pullbackEquivOfEq_ofAnalyticAt _ _ _ _ _ _ _ + +/-- The total order computed in a chosen system of continuous linear coordinates. -/ +@[expose] def orderInCoordinates (L : E ≃L[ℂ] (Fin n → ℂ)) (f : AnalyticGerm ℂ x) : ℕ∞ := + order (inCoordinates L x f) + +/-- Comparing two coordinate systems cannot lower the computed order. -/ +private theorem orderInCoordinates_le (L : E ≃L[ℂ] (Fin n → ℂ)) + (M : E ≃L[ℂ] (Fin m → ℂ)) (f : AnalyticGerm ℂ x) : + orderInCoordinates L f ≤ orderInCoordinates M f := by + obtain ⟨f, hf, rfl⟩ := exists_rep f + let e := M.symm.trans L + have ha : AnalyticAt ℂ (f ∘ L.symm) (e (M x)) := by + simpa [e] using hf.comp_of_eq (L.symm.toContinuousLinearMap.analyticAt (L x)) + (L.symm_apply_apply x) + have h := order_le_order_pullback e (e.toContinuousLinearMap.analyticAt (M x)) + (ofAnalyticAt (f ∘ L.symm) ha) + change (holomorphicTaylorSeries (f ∘ L.symm) (e (M x))).order ≤ + (holomorphicTaylorSeries ((f ∘ L.symm) ∘ e) (M x)).order at h + unfold orderInCoordinates + rw [inCoordinates_ofAnalyticAt L f hf, inCoordinates_ofAnalyticAt M f hf] + simpa only [order, taylorSeries_ofAnalyticAt, e, ContinuousLinearEquiv.trans_apply, + ContinuousLinearEquiv.symm_apply_apply, Function.comp_def] using h + +/-- Total order is independent of the chosen continuous complex-linear coordinates. -/ +theorem orderInCoordinates_eq (L : E ≃L[ℂ] (Fin n → ℂ)) + (M : E ≃L[ℂ] (Fin m → ℂ)) (f : AnalyticGerm ℂ x) : + orderInCoordinates L f = orderInCoordinates M f := + le_antisymm (orderInCoordinates_le L M f) (orderInCoordinates_le M L f) + +variable [FiniteDimensional ℂ E] + +/-- Total order of an analytic germ on a finite-dimensional complex normed space. The chosen basis +in the implementation does not affect its value. -/ +@[expose] def intrinsicOrder (f : AnalyticGerm ℂ x) : ℕ∞ := + orderInCoordinates (Module.finBasis ℂ E).equivFunL f + +/-- Intrinsic order can be computed using any continuous complex-linear coordinate system. -/ +theorem intrinsicOrder_eq_orderInCoordinates (L : E ≃L[ℂ] (Fin n → ℂ)) + (f : AnalyticGerm ℂ x) : intrinsicOrder f = orderInCoordinates L f := + orderInCoordinates_eq _ _ f + +/-- Intrinsic order agrees with the original order on finite coordinate spaces. -/ +@[simp] theorem intrinsicOrder_eq_order {x : Fin n → ℂ} (f : AnalyticGerm ℂ x) : + intrinsicOrder f = order f := by + rw [intrinsicOrder_eq_orderInCoordinates (ContinuousLinearEquiv.refl ℂ (Fin n → ℂ))] + obtain ⟨g, hg, rfl⟩ := exists_rep f + unfold orderInCoordinates + rw [inCoordinates_ofAnalyticAt _ g hg] + rfl + +/-- A germ has infinite intrinsic order exactly when it is zero. -/ +@[simp] theorem intrinsicOrder_eq_top_iff (f : AnalyticGerm ℂ x) : + intrinsicOrder f = ⊤ ↔ f = 0 := by + rw [intrinsicOrder, orderInCoordinates, order_eq_top_iff] + exact (inCoordinates (Module.finBasis ℂ E).equivFunL x).map_eq_zero_iff + +/-- Intrinsic order is additive under multiplication. -/ +theorem intrinsicOrder_mul (f g : AnalyticGerm ℂ x) : + intrinsicOrder (f * g) = intrinsicOrder f + intrinsicOrder g := by + simp only [intrinsicOrder, orderInCoordinates, map_mul, order_mul] + +/-- Cancellation can only raise the intrinsic order of a sum. -/ +theorem min_intrinsicOrder_le_intrinsicOrder_add (f g : AnalyticGerm ℂ x) : + min (intrinsicOrder f) (intrinsicOrder g) ≤ intrinsicOrder (f + g) := by + simpa only [intrinsicOrder, orderInCoordinates, map_add] using + min_order_le_order_add (inCoordinates (Module.finBasis ℂ E).equivFunL x f) + (inCoordinates (Module.finBasis ℂ E).equivFunL x g) + +/-- Taylor series with variables indexed by an arbitrary finite coordinate type. A finite +enumeration is used for the ordered derivative implementation, then the formal variables are +renamed back to the original coordinate type. -/ +def finiteIndexTaylorSeries {ι : Type*} [Fintype ι] {x : ι → ℂ} + (f : AnalyticGerm ℂ x) : MvPowerSeries ι ℂ := + MvPowerSeries.renameEquiv ℂ (Fintype.equivFin ι).symm + (taylorSeries (inCoordinates + (ContinuousLinearEquiv.piCongrLeft ℂ (fun _ : Fin (Fintype.card ι) => ℂ) + (Fintype.equivFin ι)) x f)) + +end SeveralComplexVariables.AnalyticGerm +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean new file mode 100644 index 0000000000..04bf478ef7 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean @@ -0,0 +1,236 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.Finiteness.Ideal +public import Mathlib.RingTheory.Noetherian.Basic +public import Mathlib.RingTheory.Polynomial.UniqueFactorization +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass + +/-! +# Noetherianity of analytic germ rings + +[Jakóbczak–Jarnicki][JakobczakJarnicki2021], Proposition 1.8.6: scalar analytic germs on +finite-dimensional complex spaces form Noetherian rings. The analytic induction step normalizes +a nonzero element of an ideal, divides by it, and uses finite generation of the resulting +submodule of the finite module of remainder coefficients. The dimension induction, +zero-dimensional base case, and coordinate transport are proved here from that step. No claim is +made for infinite-dimensional source spaces. + +## Main results + +`ideal_fg` is finite generation of ideals of finite-dimensional analytic germs. `ideal_fg_prod` +is the analytic induction step. `isNoetherianRing_coordinates` is Noetherianity on coordinate +spaces, from which the general instance is transported. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Filter +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Given an ideal element regular in the distinguished coordinate, division against its Weierstrass +preparation shows the ideal is finitely generated: every element reduces, modulo the ideal +element, to a polynomial remainder of degree below the order; those remainders occurring in the +ideal form a submodule of the finite free module of degree-bounded coefficient tuples, finitely +generated since the coefficient ring is Noetherian. -/ +theorem ideal_fg_of_orderInLastVariable_eq_nat [FiniteDimensional ℂ E] + [IsNoetherianRing (AnalyticGerm ℂ (0 : E))] (J : Ideal (AnalyticGerm ℂ (0 : E × ℂ))) + {g : AnalyticGerm ℂ (0 : E × ℂ)} (hgJ : g ∈ J) {d : ℕ} (hd : orderInLastVariable g = d) : + J.FG := by + classical + obtain ⟨⟨u, w⟩, ⟨hwdist, hwdeg, hgeq⟩, -⟩ := existsUnique_preparation g hd + simp only at hwdist hwdeg hgeq + have hgu : polynomialHom w = (↑u⁻¹ : AnalyticGerm ℂ (0 : E × ℂ)) * g := by + rw [hgeq, ← mul_assoc, ← Units.val_mul, inv_mul_cancel, Units.val_one, one_mul] + let M : Submodule (AnalyticGerm ℂ (0 : E)) (Fin d → AnalyticGerm ℂ (0 : E)) := + { carrier := {a | polynomialHom (remainderOfCoefficients a) ∈ J} + zero_mem' := by + show polynomialHom (remainderOfCoefficients 0) ∈ J + simp [remainderOfCoefficients] + add_mem' := by + intro a b ha hb + simp only [Set.mem_ofPred_eq, remainderOfCoefficients_add, map_add] at ha hb ⊢ + exact J.add_mem ha hb + smul_mem' := by + intro c a ha + simp only [Set.mem_ofPred_eq, remainderOfCoefficients_smul, map_mul, + polynomialHom_C] at ha ⊢ + exact J.mul_mem_left _ ha } + have hMfg : M.FG := IsNoetherian.noetherian M + obtain ⟨S, hS⟩ := hMfg + refine ⟨insert g (S.image (fun a => polynomialHom (remainderOfCoefficients a))), ?_⟩ + apply le_antisymm + · rw [Ideal.span_le] + intro x hx + simp only [Finset.coe_insert, Set.mem_insert_iff, Finset.coe_image, Set.mem_image, + Finset.mem_coe] at hx + rcases hx with rfl | ⟨a, haS, rfl⟩ + · exact hgJ + · show a ∈ M + rw [← hS] + exact Submodule.subset_span haS + · intro h hhJ + obtain ⟨⟨q, r⟩, ⟨hrdeg, heq⟩, -⟩ := existsUnique_division w hwdist h + simp only at hrdeg heq + rw [hwdeg] at hrdeg + have hreq : polynomialHom r = h - q * (↑u⁻¹ : AnalyticGerm ℂ (0 : E × ℂ)) * g := by + rw [heq, hgu]; ring + have hmem : polynomialHom r ∈ J := by + rw [hreq] + exact J.sub_mem hhJ (J.mul_mem_left _ hgJ) + have har : r = remainderOfCoefficients (fun j : Fin d => r.coeff (j : ℕ)) := + eq_remainderOfCoefficients_of_degree_lt hrdeg + have hmemM : (fun j : Fin d => r.coeff (j : ℕ)) ∈ M := by + show polynomialHom (remainderOfCoefficients _) ∈ J + rwa [← har] + rw [← hS] at hmemM + obtain ⟨f, hf⟩ := Submodule.mem_span_finset'.mp hmemM + have hrsum : r = + ∑ a : S, f a • remainderOfCoefficients (a : Fin d → AnalyticGerm ℂ (0 : E)) := by + rw [har, ← hf, remainderOfCoefficients_sum] + refine Finset.sum_congr rfl fun a _ => ?_ + rw [Polynomial.smul_eq_C_mul] + exact remainderOfCoefficients_smul (f a) (a : Fin d → AnalyticGerm ℂ (0 : E)) + have hpolyr : polynomialHom r = ∑ a : S, parameterHom (f a) * + polynomialHom (remainderOfCoefficients (a : Fin d → AnalyticGerm ℂ (0 : E))) := by + rw [hrsum, map_sum] + refine Finset.sum_congr rfl fun a _ => ?_ + rw [Polynomial.smul_eq_C_mul, map_mul, polynomialHom_C] + have hheq : h = q * ((↑u⁻¹ : AnalyticGerm ℂ (0 : E × ℂ)) * g) + + ∑ a : S, parameterHom (f a) * + polynomialHom (remainderOfCoefficients (a : Fin d → AnalyticGerm ℂ (0 : E))) := by + rw [heq, hgu, hpolyr] + rw [hheq] + apply Ideal.add_mem + · exact Ideal.mul_mem_left _ q (Ideal.mul_mem_left _ _ + (Ideal.subset_span (Finset.mem_coe.mpr (Finset.mem_insert_self g _)))) + · apply Ideal.sum_mem + intro a _ + apply Ideal.mul_mem_left + apply Ideal.subset_span + exact Finset.mem_coe.mpr (Finset.mem_insert_of_mem + (Finset.mem_image.mpr ⟨(a : Fin d → AnalyticGerm ℂ (0 : E)), a.2, rfl⟩)) + +/-- Analytic induction step for Noetherianity. A nonzero element becomes regular in the +distinguished coordinate after a linear coordinate change; finite generation transports back +along the induced ring automorphism of the germ ring. -/ +theorem ideal_fg_prod [FiniteDimensional ℂ E] + [IsNoetherianRing (AnalyticGerm ℂ (0 : E))] + (I : Ideal (AnalyticGerm ℂ (0 : E × ℂ))) : I.FG := by + rcases eq_or_ne I ⊥ with hI0 | hI0 + · exact hI0 ▸ Submodule.fg_bot + · obtain ⟨g, hgI, hg0⟩ := Submodule.exists_mem_ne_zero_of_ne_bot hI0 + obtain ⟨g0, hg0A, rfl⟩ := exists_rep g + have hg0ne : ¬ g0 =ᶠ[𝓝 0] 0 := fun h => hg0 (Subtype.ext (Germ.coe_eq.mpr h)) + obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change hg0A hg0ne + have hL0 : L (0 : E × ℂ) = 0 := L.map_zero + have hΦ : AnalyticAt ℂ L (0 : E × ℂ) := L.toContinuousLinearMap.analyticAt 0 + have hΦsymm0 : AnalyticAt ℂ L.symm (L (0 : E × ℂ)) := by + rw [hL0]; exact L.symm.toContinuousLinearMap.analyticAt 0 + set Φ : AnalyticGerm ℂ (0 : E × ℂ) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E × ℂ) := + pullbackEquivOfEq L.toHomeomorph 0 hΦ hΦsymm0 hL0 with hΦdef + have hΦg : Φ (ofAnalyticAt g0 hg0A) = ofAnalyticAt (g0 ∘ L) (hg0A.comp_of_eq hΦ hL0) := + pullbackEquivOfEq_ofAnalyticAt L.toHomeomorph 0 hΦ hΦsymm0 hL0 g0 hg0A + have hΦbij : Function.Bijective (Φ : AnalyticGerm ℂ (0 : E × ℂ) → AnalyticGerm ℂ (0 : E × ℂ)) := + pullbackEquivOfEq_bijective L.toHomeomorph 0 hΦ hΦsymm0 hL0 + have hΦorder : orderInLastVariable (Φ (ofAnalyticAt g0 hg0A)) = d := by + rw [hΦg, orderInLastVariable_ofAnalyticAt] + exact hd + have hFG : (I.map (Φ.toRingEquiv : AnalyticGerm ℂ (0 : E × ℂ) →+* + AnalyticGerm ℂ (0 : E × ℂ))).FG := + ideal_fg_of_orderInLastVariable_eq_nat _ (Ideal.mem_map_of_mem _ hgI) hΦorder + have hcomap : (I.map (Φ.toRingEquiv : AnalyticGerm ℂ (0 : E × ℂ) →+* + AnalyticGerm ℂ (0 : E × ℂ))).comap + (Φ.toRingEquiv : AnalyticGerm ℂ (0 : E × ℂ) →+* AnalyticGerm ℂ (0 : E × ℂ)) = I := + Ideal.comap_map_of_bijective _ hΦbij + have hI : I = (I.map (Φ.toRingEquiv : AnalyticGerm ℂ (0 : E × ℂ) →+* + AnalyticGerm ℂ (0 : E × ℂ))).map + (Φ.toRingEquiv.symm : AnalyticGerm ℂ (0 : E × ℂ) →+* AnalyticGerm ℂ (0 : E × ℂ)) := by + conv_lhs => rw [← hcomap] + rw [Ideal.map_comap_of_equiv Φ.toRingEquiv.symm, RingEquiv.symm_symm] + rfl + rw [hI] + exact Ideal.FG.map hFG _ + +/-- Analytic induction step for factorization: an irreducible germ becomes regular in the +distinguished coordinate after a linear change, Weierstrass-prepares to a distinguished +polynomial, and irreducibility of the polynomial (hence, given a unique factorization base ring, +its primality) transports back to primality of the germ. -/ +theorem prime_of_irreducible_of_baseUFD [FiniteDimensional ℂ E] + [UniqueFactorizationMonoid (AnalyticGerm ℂ (0 : E))] + {g : AnalyticGerm ℂ (0 : E × ℂ)} (hg : Irreducible g) : Prime g := by + obtain ⟨g0, hg0A, rfl⟩ := exists_rep g + have hg0ne : ¬ g0 =ᶠ[𝓝 0] 0 := fun h => hg.ne_zero (Subtype.ext (Germ.coe_eq.mpr h)) + obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change hg0A hg0ne + have hL0 : L (0 : E × ℂ) = 0 := L.map_zero + have hΦ : AnalyticAt ℂ L (0 : E × ℂ) := L.toContinuousLinearMap.analyticAt 0 + have hΦsymm0 : AnalyticAt ℂ L.symm (L (0 : E × ℂ)) := by + rw [hL0]; exact L.symm.toContinuousLinearMap.analyticAt 0 + set Φ : AnalyticGerm ℂ (0 : E × ℂ) ≃ₐ[ℂ] AnalyticGerm ℂ (0 : E × ℂ) := + pullbackEquivOfEq L.toHomeomorph 0 hΦ hΦsymm0 hL0 with hΦdef + have hΦg : Φ (ofAnalyticAt g0 hg0A) = ofAnalyticAt (g0 ∘ L) (hg0A.comp_of_eq hΦ hL0) := + pullbackEquivOfEq_ofAnalyticAt L.toHomeomorph 0 hΦ hΦsymm0 hL0 g0 hg0A + have hΦorder : orderInLastVariable (Φ (ofAnalyticAt g0 hg0A)) = d := by + rw [hΦg, orderInLastVariable_ofAnalyticAt] + exact hd + have hΦirr : Irreducible (Φ (ofAnalyticAt g0 hg0A)) := hg.map Φ + obtain ⟨⟨u, w⟩, ⟨hwdist, hwdeg, hgeq⟩, -⟩ := + existsUnique_preparation (Φ (ofAnalyticAt g0 hg0A)) hΦorder + simp only at hwdist hwdeg hgeq + have hpolyirr : Irreducible (polynomialHom w) := + (irreducible_isUnit_mul u.isUnit).mp (hgeq ▸ hΦirr) + have hwirr : Irreducible w := (irreducible_polynomialHom_iff w hwdist).mp hpolyirr + have hwp : Prime w := UniqueFactorizationMonoid.irreducible_iff_prime.mp hwirr + have hpw : Prime (polynomialHom w) := prime_polynomialHom_of_isDistinguishedAt hwdist hwp + have hpΦg : Prime (Φ (ofAnalyticAt g0 hg0A)) := by + rw [hgeq]; exact (prime_units_mul u).mpr hpw + exact (MulEquiv.prime_iff Φ).mp hpΦg + +/-- The origin germ ring in `n` complex coordinates is Noetherian, by induction using +`ideal_fg_prod`. In dimension zero it is the scalar field. -/ +theorem isNoetherianRing_coordinates (n : ℕ) : + IsNoetherianRing (AnalyticGerm ℂ (0 : Fin n → ℂ)) := by + induction n with + | zero => + exact isNoetherianRing_of_ringEquiv ℂ (equivScalarOfSubsingleton ℂ (0 : Fin 0 → ℂ)).symm + | succ n ih => + let := ih + let : IsNoetherianRing (AnalyticGerm ℂ (0 : (Fin n → ℂ) × ℂ)) := + (isNoetherianRing_iff_ideal_fg _).mpr ideal_fg_prod + let e : (Fin (n + 1) → ℂ) ≃ₗ[ℂ] (Fin n → ℂ) × ℂ := + (LinearEquiv.piCongrLeft ℂ (fun _ => ℂ) (finSuccEquiv n)).trans + ((LinearEquiv.piOptionEquivProd ℂ).trans (LinearEquiv.prodComm ℂ _ _)) + exact isNoetherianRing_of_ringEquiv _ + (linearEquivPullbackZero e.toContinuousLinearEquiv).toRingEquiv + +/-- Scalar analytic germs at any point of a finite-dimensional complex normed space form a +Noetherian ring. This instance combines the analytic induction step with the dimension +induction. -/ +instance [FiniteDimensional ℂ E] (x : E) : IsNoetherianRing (AnalyticGerm ℂ x) := by + let e := (Module.finBasis ℂ E).equivFunL + let := isNoetherianRing_coordinates (Module.finrank ℂ E) + let : IsNoetherianRing (AnalyticGerm ℂ (0 : E)) := + isNoetherianRing_of_ringEquiv _ (linearEquivPullbackZero e).toRingEquiv + exact isNoetherianRing_of_ringEquiv _ (translateEquiv x).symm.toRingEquiv + +/-- Every ideal of finite-dimensional analytic germs has finitely many generators. -/ +theorem ideal_fg [FiniteDimensional ℂ E] {x : E} (I : Ideal (AnalyticGerm ℂ x)) : I.FG := + (isNoetherianRing_iff_ideal_fg _).mp inferInstance I + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Order.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Order.lean new file mode 100644 index 0000000000..6e828d67ca --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Order.lean @@ -0,0 +1,724 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.MvPolynomial.Funext +public import Mathlib.Analysis.Analytic.Polynomial +public import Mathlib.RingTheory.MvPowerSeries.Derivative +public import Mathlib.RingTheory.MvPowerSeries.NoZeroDivisors +public import Mathlib.RingTheory.MvPowerSeries.Trunc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor + +/-! +# Total order of analytic germs + +The Taylor series of a scalar germ in finite complex coordinates is a Mathlib `MvPowerSeries`. +Its `order` is the least total degree with a nonzero coefficient, with infinity for the zero +series. This is different from order along a chosen axis. The empty coordinate type `Fin 0` is +included. + +The basic order characterization and sum rules use Mathlib directly. Taylor uniqueness and the +infinite-order criterion follow from the convergent polydisc expansion. The product rule follows +from multiplicativity of Taylor series. The coordinate chain rule proves that analytic pullback +cannot lower order; applying this to a map and its inverse gives coordinate invariance. Exact +total order along the last axis after a linear change follows [Suwa][Suwa2024], Lemma 1.2: the +leading homogeneous part is a nonzero polynomial, hence nonvanishing at some point. An +invertible shear sends the last basis vector to a suitable such point. These are classical local +analytic facts, as in [Suwa][Suwa2024] §1.4, rather than a development of local algebra. + +## Main definitions + +* `taylorSeries`: Taylor series of a scalar analytic germ, independent of its representative. +* `order`: Total order of vanishing: the least total degree in the germ's Taylor series. +* `shearToLastAxis`: A linear automorphism sending the last coordinate axis to the line through `c`, + provided the `i`-th coordinate of `c` is nonzero. + +## Main results + +* `taylorSeries_injective`: The multivariate Taylor-series map is injective on analytic germs. +* `taylorSeries_mul`: Taylor series preserve multiplication of analytic germs. +* `order_mul`: The order of a product is the sum of the orders, including zero germs. +* `min_order_le_order_add`: Cancellation can only raise the order of a sum. +* `order_eq_zero_iff`: A germ has order zero exactly when it is a unit. +* `order_eq_top_iff`: Infinite order is equivalent to being the zero germ, by uniqueness of the + convergent multivariate Taylor expansion. +* `order_pullbackEquiv`: An analytic change of coordinates preserves total order. +* `exists_coordinate_change_order`: **[Suwa][Suwa2024], Lemma 1.2.** A linear change makes the order + on the last axis equal to the total order. + +## References + +* [T. Suwa, *Complex Analytic Geometry: From the Localization Viewpoint*][Suwa2024] +-/ + +public noncomputable section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {n m : ℕ} {x : Fin n → ℂ} + +/-- The multivariate Taylor series depends only on the function germ. -/ +theorem holomorphicTaylorSeries_congr {f g : (Fin n → ℂ) → ℂ} + (h : f =ᶠ[𝓝 x] g) : holomorphicTaylorSeries f x = holomorphicTaylorSeries g x := by + obtain ⟨U, hU, ho, hx⟩ := _root_.eventually_nhds_iff.mp h + funext k + dsimp [holomorphicTaylorSeries, multiIndexDeriv] + rw [iteratedPartialDeriv_congrOn ho hU (multiIndexList k) hx] + +/-- Taylor series of a scalar analytic germ, independent of its representative. -/ +@[expose] def taylorSeries (f : AnalyticGerm ℂ x) : MvPowerSeries (Fin n) ℂ := + f.val.liftOn (fun g => holomorphicTaylorSeries g x) + (fun _ _ h => holomorphicTaylorSeries_congr h) + +/-- Taylor series of a represented germ is the existing Taylor series of the function. -/ +@[simp] theorem taylorSeries_ofAnalyticAt (f : (Fin n → ℂ) → ℂ) (hf : AnalyticAt ℂ f x) : + taylorSeries (ofAnalyticAt f hf) = holomorphicTaylorSeries f x := rfl + +/-- Taylor series preserve addition of analytic germs. -/ +theorem taylorSeries_add (f g : AnalyticGerm ℂ x) : + taylorSeries (f + g) = taylorSeries f + taylorSeries g := by + obtain ⟨f, hf, rfl⟩ := exists_rep f + obtain ⟨g, hg, rfl⟩ := exists_rep g + obtain ⟨U, hsub, hU, hx⟩ := _root_.eventually_nhds_iff.mp + (hf.eventually_analyticAt.and hg.eventually_analyticAt) + have hA : ∀ b ∈ (Finset.univ : Finset Bool), + AnalyticOnNhd ℂ (if b then f else g) U := by + intro b _ z hz + cases b + · exact (hsub z hz).2 + · exact (hsub z hz).1 + change holomorphicTaylorSeries (f + g) x = + holomorphicTaylorSeries f x + holomorphicTaylorSeries g x + funext k + have hD : iteratedPartialDeriv (multiIndexList k) (f + g) x = + iteratedPartialDeriv (multiIndexList k) f x + + iteratedPartialDeriv (multiIndexList k) g x := by + simpa [Fintype.sum_bool, Pi.add_def] using + (iteratedPartialDeriv_finset_sum Finset.univ hA hU (multiIndexList k) hx) + change (∏ i, (k i).factorial : ℂ)⁻¹ * iteratedPartialDeriv (multiIndexList k) (f + g) x = + (∏ i, (k i).factorial : ℂ)⁻¹ * iteratedPartialDeriv (multiIndexList k) f x + + (∏ i, (k i).factorial : ℂ)⁻¹ * iteratedPartialDeriv (multiIndexList k) g x + rw [hD, mul_add] + +/-- The zero germ has zero Taylor series, including in dimension zero. -/ +@[simp] theorem taylorSeries_zero : taylorSeries (0 : AnalyticGerm ℂ x) = 0 := by + have hz : ∀ l : List (Fin n), iteratedPartialDeriv l (0 : (Fin n → ℂ) → ℂ) = 0 := by + intro l + induction l with + | nil => rfl + | cons i l ih => + change partialDeriv i (iteratedPartialDeriv l 0) = 0 + rw [ih] + funext z + simp [partialDeriv] + change holomorphicTaylorSeries (0 : (Fin n → ℂ) → ℂ) x = 0 + funext k + change holomorphicTaylorSeries (0 : (Fin n → ℂ) → ℂ) x k = 0 + simp [holomorphicTaylorSeries, multiIndexDeriv, hz] + +/-- The Taylor series of a coordinate derivative is the formal partial derivative. -/ +theorem holomorphicTaylorSeries_partialDeriv {f : (Fin n → ℂ) → ℂ} + (hf : AnalyticAt ℂ f x) (i : Fin n) : + holomorphicTaylorSeries (partialDeriv i f) x = + MvPowerSeries.pderiv i (holomorphicTaylorSeries f x) := by + obtain ⟨U, hU, ho, hx⟩ := _root_.eventually_nhds_iff.mp hf.eventually_analyticAt + ext k + rw [MvPowerSeries.coeff_pderiv] + have happ (l : List (Fin n)) : + iteratedPartialDeriv (l ++ [i]) f = iteratedPartialDeriv l (partialDeriv i f) := by + induction l with + | nil => rfl + | cons j l ih => + simpa only [List.cons_append, iteratedPartialDeriv] using congrArg (partialDeriv j) ih + have hD : multiIndexDeriv k (partialDeriv i f) x = + multiIndexDeriv (k + Finsupp.single i 1 : Fin n →₀ ℕ) f x := by + rw [multiIndexDeriv, ← happ] + apply iteratedPartialDeriv_eq_multiIndexDeriv hU ho hx + intro j + by_cases hji : j = i + · subst j; simp + · simp [hji, Ne.symm hji] + have hfac : (∏ j, ((k + Finsupp.single i 1 : Fin n →₀ ℕ) j).factorial : ℂ) = + (∏ j, (k j).factorial : ℂ) * (k i + 1) := by + rw [← Finset.prod_erase_mul _ _ (Finset.mem_univ i), + ← Finset.prod_erase_mul _ _ (Finset.mem_univ i)] + have he : (∏ j ∈ Finset.univ.erase i, (((k + Finsupp.single i 1 : Fin n →₀ ℕ) j).factorial : + ℂ)) = + ∏ j ∈ Finset.univ.erase i, ((k j).factorial : ℂ) := by + apply Finset.prod_congr rfl + intro j hj + simp [Finsupp.single_eq_of_ne (Finset.ne_of_mem_erase hj)] + rw [he] + simp [Nat.factorial_succ] + ring + change (∏ j, (k j).factorial : ℂ)⁻¹ * multiIndexDeriv k (partialDeriv i f) x = + (∏ j, ((k + Finsupp.single i 1 : Fin n →₀ ℕ) j).factorial : ℂ)⁻¹ * + multiIndexDeriv (k + Finsupp.single i 1 : Fin n →₀ ℕ) f x * (k i + 1) + rw [hD, hfac] + have hk : (k i : ℂ) + 1 ≠ 0 := by exact_mod_cast Nat.succ_ne_zero (k i) + field_simp + +/-- Total order of vanishing: the least total degree in the germ's Taylor series. -/ +@[expose] def order (f : AnalyticGerm ℂ x) : ℕ∞ := (taylorSeries f).order + +/-- The total order is computed by Mathlib's multivariate power-series order. -/ +theorem order_eq_taylorSeries_order (f : AnalyticGerm ℂ x) : + order f = (taylorSeries f).order := rfl + +/-- The constant Taylor coefficient is evaluation at the base point. -/ +@[simp] theorem constantCoeff_taylorSeries (f : AnalyticGerm ℂ x) : + (taylorSeries f).constantCoeff = eval x f := by + obtain ⟨g, hg, rfl⟩ := exists_rep f + change holomorphicTaylorSeries g x 0 = g x + simp [holomorphicTaylorSeries, multiIndexDeriv, multiIndexList, iteratedPartialDeriv] + +/-- A germ has order zero exactly when it is a unit. -/ +@[simp] theorem order_eq_zero_iff (f : AnalyticGerm ℂ x) : order f = 0 ↔ IsUnit f := by + rw [isUnit_iff, order] + have h := MvPowerSeries.order_ne_zero_iff_constCoeff_eq_zero (f := taylorSeries f) + simpa using not_congr h + +/-- The zero germ has infinite total order. -/ +@[simp] theorem order_zero : order (0 : AnalyticGerm ℂ x) = ⊤ := by + simp [order] + +/-- Distinct orders prevent cancellation of the leading terms of a sum. -/ +theorem order_add_of_ne {f g : AnalyticGerm ℂ x} (h : order f ≠ order g) : + order (f + g) = min (order f) (order g) := by + simpa only [order, taylorSeries_add] using MvPowerSeries.order_add_of_order_ne h + +/-- A scalar analytic germ is determined to be zero by its Taylor coefficients. The proof uses the +convergent polydisc Taylor expansion, including dimension zero. -/ +@[simp] theorem taylorSeries_eq_zero_iff (f : AnalyticGerm ℂ x) : + taylorSeries f = 0 ↔ f = 0 := by + classical + constructor + · intro hzero + obtain ⟨g, hg, rfl⟩ := exists_rep f + change holomorphicTaylorSeries g x = 0 at hzero + have hb : ∀ᶠ z in 𝓝 x, ‖g z‖ < ‖g x‖ + 1 := + hg.continuousAt.norm.eventually_lt_const (by linarith) + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hg.eventually_analyticAt.and hb) + have hr₂ : 0 < r / 2 := half_pos hr + have hsub : closedPolydisc x (fun _ => r / 2) ⊆ ball x r := by + rw [closedPolydisc_eq_closedBall hr₂.le] + exact closedBall_subset_ball (half_lt_self hr) + have hA : AnalyticOnNhd ℂ g (closedPolydisc x (fun _ => r / 2)) := + fun z hz => (hball (hsub hz)).1 + have hslice : ∀ z ∈ closedPolydisc x (fun _ => r / 2), ∀ i, + AnalyticAt ℂ (fun w => g (Function.update z i w)) (z i) := by + intro z hz i + exact hA.analyticAt_update hz i + have hcoeff : ∀ m : Fin n → ℕ, + polydiscCauchyCoeffWithRadii g x (fun _ => r / 2) m = 0 := by + intro m + have h := (coeff_holomorphicTaylorSeries (fun _ => hr₂) hA.continuousOn hslice + (Finsupp.equivFunOnFinite.symm m)).symm + rw [hzero, Finsupp.coe_equivFunOnFinite_symm] at h + exact h + have he : g =ᶠ[𝓝 x] 0 := by + filter_upwards [ball_mem_nhds x hr₂] with z hz + have hh : ∀ i, ‖(z - x) i‖ < r / 2 := by + intro i + exact lt_of_le_of_lt (norm_le_pi_norm (z - x) i) + (by simpa only [mem_ball, dist_eq_norm] using hz) + have hsum := hasSum_polydiscTaylor (fun _ => hr₂) hh hA.continuousOn hslice + (fun z hz => (hball (hsub hz)).2.le) + have hxz : x + (z - x) = z := by abel + have hsum0 : HasSum (fun _ : Fin n → ℕ => (0 : ℂ)) (g z) := by + simpa only [hcoeff, smul_zero, hxz] using hsum + exact hsum0.unique hasSum_zero + exact Subtype.ext (Germ.coe_eq.mpr he) + · rintro rfl + exact taylorSeries_zero + +/-- The multivariate Taylor-series map is injective on analytic germs. -/ +theorem taylorSeries_injective : Function.Injective (taylorSeries (x := x)) := by + let T : AnalyticGerm ℂ x →+ MvPowerSeries (Fin n) ℂ := + { toFun := taylorSeries + map_zero' := taylorSeries_zero + map_add' := taylorSeries_add } + intro f g h + have hs : taylorSeries (f - g) = 0 := by + change T (f - g) = 0 + rw [map_sub] + exact sub_eq_zero.mpr h + exact sub_eq_zero.mp ((taylorSeries_eq_zero_iff _).mp hs) + +/-- Infinite order is equivalent to being the zero germ, by uniqueness of the convergent +multivariate Taylor expansion. -/ +@[simp] theorem order_eq_top_iff (f : AnalyticGerm ℂ x) : order f = ⊤ ↔ f = 0 := by + rw [order, MvPowerSeries.order_eq_top_iff, taylorSeries_eq_zero_iff] + +/-- Taylor series preserve multiplication of analytic germs. The proof compares coefficients +inductively, using the analytic and formal coordinate product rules. -/ +theorem taylorSeries_mul (f g : AnalyticGerm ℂ x) : + taylorSeries (f * g) = taylorSeries f * taylorSeries g := by + let P (k : Fin n →₀ ℕ) : Prop := ∀ f g : AnalyticGerm ℂ x, + MvPowerSeries.coeff k (taylorSeries (f * g)) = + MvPowerSeries.coeff k (taylorSeries f * taylorSeries g) + have hzero : P 0 := by + intro f g + simp only [MvPowerSeries.coeff_zero_eq_constantCoeff, map_mul, + constantCoeff_taylorSeries] + have hstep (k : Fin n →₀ ℕ) (i : Fin n) (ih : P k) : P (k + Finsupp.single i 1) := by + intro f g + obtain ⟨f, hf, rfl⟩ := exists_rep f + obtain ⟨g, hg, rfl⟩ := exists_rep g + obtain ⟨U, hU, ho, hx⟩ := _root_.eventually_nhds_iff.mp + (hf.eventually_analyticAt.and hg.eventually_analyticAt) + have hAf : AnalyticOnNhd ℂ f U := fun y hy => (hU y hy).1 + have hAg : AnalyticOnNhd ℂ g U := fun y hy => (hU y hy).2 + have hdf := (hAf.partialDeriv ho i) x hx + have hdg := (hAg.partialDeriv ho i) x hx + have hdm := ((hAf.mul hAg).partialDeriv ho i) x hx + have heq : ofAnalyticAt (partialDeriv i (f * g)) hdm = + ofAnalyticAt (partialDeriv i f) hdf * ofAnalyticAt g hg + + ofAnalyticAt f hf * ofAnalyticAt (partialDeriv i g) hdg := by + rw [← ofAnalyticAt_mul, ← ofAnalyticAt_mul, ← ofAnalyticAt_add] + apply ofAnalyticAt_eq_iff.mpr + filter_upwards [ho.eventually_mem hx] with y hy + exact partialDeriv_mul (hAf y hy).differentiableAt (hAg y hy).differentiableAt i + have hD : MvPowerSeries.coeff k + (MvPowerSeries.pderiv i (holomorphicTaylorSeries (f * g) x)) = + MvPowerSeries.coeff k (MvPowerSeries.pderiv i + (holomorphicTaylorSeries f x * holomorphicTaylorSeries g x)) := by + rw [← holomorphicTaylorSeries_partialDeriv (hf.mul hg) i] + change MvPowerSeries.coeff k (taylorSeries (ofAnalyticAt (partialDeriv i (f * g)) hdm)) = _ + rw [heq, taylorSeries_add, map_add, ih, ih] + simp only [taylorSeries_ofAnalyticAt, holomorphicTaylorSeries_partialDeriv hf i, + holomorphicTaylorSeries_partialDeriv hg i, Derivation.leibniz, smul_eq_mul, map_add] + rw [mul_comm (MvPowerSeries.pderiv i (holomorphicTaylorSeries f x))] + exact add_comm _ _ + simp only [MvPowerSeries.coeff_pderiv] at hD + exact mul_right_cancel₀ (by exact_mod_cast Nat.succ_ne_zero (k i)) hD + have hall (k : Fin n →₀ ℕ) : P k := by + induction k using Finsupp.induction₂ with + | zero => exact hzero + | add_single i b k _ _ ih => + have h (b : ℕ) : P (k + Finsupp.single i b) := by + induction b with + | zero => simpa using ih + | succ b hb => + simpa only [Finsupp.single_add, add_assoc] using hstep (k + Finsupp.single i b) i hb + exact h b + exact MvPowerSeries.ext fun k => hall k f g + +/-- The order of a product is the sum of the orders, including zero germs. This follows from +multiplicativity of Taylor series and `MvPowerSeries.order_mul`. -/ +theorem order_mul (f g : AnalyticGerm ℂ x) : order (f * g) = order f + order g := by + simpa only [order, taylorSeries_mul] using MvPowerSeries.order_mul (taylorSeries f) + (taylorSeries g) + +/-- Cancellation can only raise the order of a sum. -/ +theorem min_order_le_order_add (f g : AnalyticGerm ℂ x) : + min (order f) (order g) ≤ order (f + g) := by + simpa only [order, taylorSeries_add] using + (MvPowerSeries.min_order_le_add (f := taylorSeries f) (g := taylorSeries g)) + +/-- Order at least `d + 1` is equivalent to a zero constant term and order at least `d` for every +formal coordinate derivative. -/ +private theorem nat_succ_le_series_order_iff (p : MvPowerSeries (Fin n) ℂ) (d : ℕ) : + (d + 1 : ℕ) ≤ p.order ↔ p.constantCoeff = 0 ∧ + ∀ i, (d : ℕ∞) ≤ (MvPowerSeries.pderiv i p).order := by + constructor + · intro h + constructor + · exact MvPowerSeries.one_le_order_iff_constCoeff_eq_zero.mp + (le_trans (by exact_mod_cast Nat.succ_pos d) h) + · intro i + apply MvPowerSeries.nat_le_order + intro k hk + rw [MvPowerSeries.coeff_pderiv] + have hdeg : (k + Finsupp.single i 1).degree < d + 1 := by simpa using hk + rw [MvPowerSeries.coeff_of_lt_order + (lt_of_lt_of_le (by exact_mod_cast hdeg) h), zero_mul] + · rintro ⟨hzero, hd⟩ + apply MvPowerSeries.nat_le_order + intro k hk + by_cases hk0 : k = 0 + · simpa [hk0] using hzero + obtain ⟨i, hi⟩ := Finsupp.support_nonempty_iff.mpr hk0 + have hip : 0 < k i := Nat.pos_of_ne_zero (Finsupp.mem_support_iff.mp hi) + have hsingle : Finsupp.single i 1 ≤ k := Finsupp.single_le_iff.mpr hip + let l := k - Finsupp.single i 1 + have hl : l + Finsupp.single i 1 = k := tsub_add_cancel_of_le hsingle + have hdeg : l.degree < d := by + have := congrArg Finsupp.degree hl + simp only [map_add, Finsupp.degree_single] at this + omega + have hh := MvPowerSeries.coeff_of_lt_order (f := MvPowerSeries.pderiv i p) + (lt_of_lt_of_le (by exact_mod_cast hdeg) (hd i)) + rw [MvPowerSeries.coeff_pderiv, hl] at hh + exact (mul_eq_zero.mp hh).resolve_right (by exact_mod_cast Nat.succ_ne_zero (l i)) + +/-- A common lower bound on orders is preserved by finite sums of analytic germs. -/ +theorem le_order_sum {κ : Type*} (s : Finset κ) (f : κ → AnalyticGerm ℂ x) {d : ℕ∞} + (h : ∀ i ∈ s, d ≤ order (f i)) : d ≤ order (∑ i ∈ s, f i) := by + classical + induction s using Finset.induction_on with + | empty => simp + | @insert i s hi ih => + rw [Finset.sum_insert hi] + exact le_trans (le_min (h i (Finset.mem_insert_self _ _)) + (ih fun j hj => h j (Finset.mem_insert_of_mem hj))) (min_order_le_order_add _ _) + +/-- Coordinate differentiation preserves analyticity at a point. -/ +private theorem analyticAt_partialDeriv {f : (Fin n → ℂ) → ℂ} + (hf : AnalyticAt ℂ f x) (i : Fin n) : AnalyticAt ℂ (partialDeriv i f) x := by + obtain ⟨r, hr, hfa⟩ := hf.exists_ball_analyticOnNhd + exact (hfa.partialDeriv isOpen_ball i) x (mem_ball_self hr) + +/-- Analytic pullback cannot lower the total order of a scalar germ. This includes maps between +spaces of different dimensions and empty coordinate types. -/ +theorem order_le_order_pullback (e : (Fin n → ℂ) → (Fin m → ℂ)) (he : AnalyticAt ℂ e x) + (f : AnalyticGerm ℂ (e x)) : order f ≤ order (pullback e he f) := by + apply ENat.forall_natCast_le_iff_le.mp + intro d + obtain ⟨f, hf, rfl⟩ := exists_rep f + induction d generalizing f with + | zero => exact fun _ => bot_le + | succ d ih => + intro hd + obtain ⟨hzero, hderiv⟩ := (nat_succ_le_series_order_iff + (holomorphicTaylorSeries f (e x)) d).mp hd + change ((d + 1 : ℕ) : ℕ∞) ≤ (holomorphicTaylorSeries (f ∘ e) x).order + apply (nat_succ_le_series_order_iff _ d).mpr + constructor + · have h0 : f (e x) = 0 := by + simpa only [← taylorSeries_ofAnalyticAt f hf, constantCoeff_taylorSeries, + eval_ofAnalyticAt] using hzero + simpa only [← taylorSeries_ofAnalyticAt (f ∘ e) (hf.comp he), + constantCoeff_taylorSeries, eval_ofAnalyticAt, Function.comp_apply] using h0 + · intro i + let a (j : Fin m) := partialDeriv i (fun z => e z j) + let b (j : Fin m) := partialDeriv j f ∘ e + have ha (j : Fin m) : AnalyticAt ℂ (a j) x := + analyticAt_partialDeriv (analyticAt_pi_iff.mp he j) i + have hb (j : Fin m) : AnalyticAt ℂ (b j) x := + (analyticAt_partialDeriv hf j).comp he + have hsum := Finset.univ.analyticAt_sum (fun j _ => (ha j).mul (hb j)) + have heq : ofAnalyticAt (partialDeriv i (f ∘ e)) + (analyticAt_partialDeriv (hf.comp he) i) = + ∑ j, ofAnalyticAt (a j) (ha j) * ofAnalyticAt (b j) (hb j) := by + simp_rw [← ofAnalyticAt_mul] + rw [← ofAnalyticAt_sum Finset.univ (fun j => a j * b j) + (fun j => (ha j).mul (hb j)) hsum] + apply ofAnalyticAt_eq_iff.mpr + filter_upwards [he.eventually_analyticAt, + he.continuousAt.eventually hf.eventually_analyticAt] with z hez hfz + simpa [a, b, complexJacobian, smul_eq_mul] using + partialDeriv_comp hfz.differentiableAt hez.differentiableAt i + rw [← holomorphicTaylorSeries_partialDeriv (hf.comp he) i] + change (d : ℕ∞) ≤ order (ofAnalyticAt (partialDeriv i (f ∘ e)) + (analyticAt_partialDeriv (hf.comp he) i)) + rw [heq] + apply le_order_sum + intro j _ + rw [order_mul] + apply le_trans _ (le_add_left (le_refl _)) + apply ih (partialDeriv j f) (analyticAt_partialDeriv hf j) + simpa only [order, taylorSeries_ofAnalyticAt, + holomorphicTaylorSeries_partialDeriv hf j] using hderiv j + +/-- An analytic change of coordinates preserves total order. Apply order monotonicity to the +coordinate map and its analytic inverse. -/ +theorem order_pullbackEquiv (e : (Fin n → ℂ) ≃ₜ (Fin m → ℂ)) + (he : AnalyticAt ℂ e x) (hi : AnalyticAt ℂ e.symm (e x)) + (f : AnalyticGerm ℂ (e x)) : order (pullbackEquiv e x he hi f) = order f := by + apply le_antisymm + · obtain ⟨f, hf, rfl⟩ := exists_rep f + have hc : AnalyticAt ℂ (f ∘ e) (e.symm (e x)) := by simpa using hf.comp he + have h := order_le_order_pullback e.symm hi (ofAnalyticAt (f ∘ e) hc) + have heq : ofAnalyticAt ((f ∘ e) ∘ e.symm) (hc.comp hi) = ofAnalyticAt f hf := by + apply ofAnalyticAt_eq_iff.mpr + exact .of_forall fun z => by simp + rw [pullback_ofAnalyticAt, heq] at h + change (holomorphicTaylorSeries (f ∘ e) (e.symm (e x))).order ≤ + (holomorphicTaylorSeries f (e x)).order at h + change (holomorphicTaylorSeries (f ∘ e) x).order ≤ + (holomorphicTaylorSeries f (e x)).order + simpa only [Homeomorph.symm_apply_apply] using h + · exact order_le_order_pullback e he f + +/-- Exact order is characterized by the first nonzero total-degree Taylor coefficient. -/ +theorem order_eq_nat_iff (f : AnalyticGerm ℂ x) (d : ℕ) : + order f = d ↔ + (∃ k, MvPowerSeries.coeff k (taylorSeries f) ≠ 0 ∧ k.degree = d) ∧ + ∀ k, k.degree < d → MvPowerSeries.coeff k (taylorSeries f) = 0 := + MvPowerSeries.order_eq_nat + +/-- A linear automorphism sending the last coordinate axis to the line through `c`, provided the +`i`-th coordinate of `c` is nonzero. This is the shear used in [Suwa][Suwa2024], Lemma 1.2, +after swapping `i` with the last index. -/ +def shearToLastAxis (c : Fin (n + 1) → ℂ) (i : Fin (n + 1)) (hi : c i ≠ 0) : + (Fin (n + 1) → ℂ) ≃ₗ[ℂ] (Fin (n + 1) → ℂ) where + toFun z j := if j = i then z i * c i else z j + z i * c j + invFun z j := if j = i then z i / c i else z j - (z i / c i) * c j + left_inv z := by + ext j + by_cases hj : j = i + · subst hj + simp [hi] + · simp [hj]; field_simp [hi]; ring + right_inv z := by + ext j + by_cases hj : j = i + · subst hj + simp [hi] + · simp [hj] + map_add' z w := by + ext j + by_cases hj : j = i + · simp [hj]; ring + · simp [hj]; ring + map_smul' a z := by + ext j + by_cases hj : j = i + · simp [hj, smul_eq_mul]; ring + · simp [hj, smul_eq_mul]; ring + +/-- The shear sends the `i`-th axis to the line through `c`. -/ +theorem shearToLastAxis_single (c : Fin (n + 1) → ℂ) (i : Fin (n + 1)) (hi : c i ≠ 0) + (w : ℂ) : shearToLastAxis c i hi (Pi.single i w) = w • c := by + ext j + by_cases hj : j = i + · subst j; simp [shearToLastAxis, Pi.single_eq_same, smul_eq_mul] + · simp [shearToLastAxis, hj, smul_eq_mul] + +/-- Constant functions have constant multivariate Taylor series. -/ +theorem holomorphicTaylorSeries_const (a : ℂ) (x : Fin n → ℂ) : + holomorphicTaylorSeries (fun _ => a) x = MvPowerSeries.C a := by + ext k + by_cases hk : k = 0 + · subst k + change holomorphicTaylorSeries (fun _ => a) x 0 = a + simp [holomorphicTaylorSeries, multiIndexDeriv, multiIndexList, iteratedPartialDeriv] + · have hzero (l : List (Fin n)) (hl : l ≠ []) : + iteratedPartialDeriv l (fun _ : (Fin n → ℂ) => a) = 0 := by + induction l with + | nil => exact (hl rfl).elim + | cons i l ih => + by_cases hl0 : l = [] + · subst l + funext z + simp [iteratedPartialDeriv, partialDeriv] + · funext z + simp [iteratedPartialDeriv, ih hl0, partialDeriv] + rw [MvPowerSeries.coeff_C_of_ne_zero hk] + have hlist : multiIndexList k ≠ [] := by + intro h + have hcount := congrArg (fun l => l.count) h + have : k = 0 := by + ext i + have := congrFun hcount i + simpa only [count_multiIndexList, List.count_nil, Finsupp.zero_apply] using this + exact hk this + change holomorphicTaylorSeries (fun _ => a) x k = 0 + simp [holomorphicTaylorSeries, multiIndexDeriv, hzero _ hlist] + +/-- Coordinate functions have the corresponding formal variable as their Taylor series at zero. -/ +theorem holomorphicTaylorSeries_coord (i : Fin n) : + holomorphicTaylorSeries (fun z : Fin n → ℂ => z i) 0 = MvPowerSeries.X i := by + have hder (j : Fin n) : partialDeriv j (fun z : Fin n → ℂ => z i) = + fun _ => if j = i then (1 : ℂ) else 0 := by + funext z + by_cases hji : j = i + · subst j; simp [partialDeriv] + · simp [partialDeriv, hji, Ne.symm hji] + have hai : AnalyticAt ℂ (fun z : Fin n → ℂ => z i) 0 := + analyticAt_pi_iff.mp analyticAt_id i + have hd (j : Fin n) : MvPowerSeries.pderiv j + (holomorphicTaylorSeries (fun z : Fin n → ℂ => z i) 0) = + MvPowerSeries.pderiv j (MvPowerSeries.X i) := by + rw [← holomorphicTaylorSeries_partialDeriv hai j, hder, + holomorphicTaylorSeries_const] + by_cases hji : j = i <;> simp [MvPowerSeries.pderiv_X, hji] + ext k + by_cases hk : k = 0 + · subst k + simp only [MvPowerSeries.coeff_zero_eq_constantCoeff, MvPowerSeries.constantCoeff_X] + change holomorphicTaylorSeries (fun z : Fin n → ℂ => z i) 0 0 = 0 + simp [holomorphicTaylorSeries, multiIndexDeriv, multiIndexList, iteratedPartialDeriv] + · obtain ⟨j, hj⟩ := Finsupp.support_nonempty_iff.mpr hk + have hjp : 0 < k j := Nat.pos_of_ne_zero (Finsupp.mem_support_iff.mp hj) + let l := k - Finsupp.single j 1 + have hl : l + Finsupp.single j 1 = k := + tsub_add_cancel_of_le (Finsupp.single_le_iff.mpr hjp) + have hh := congrArg (MvPowerSeries.coeff l) (hd j) + simp only [MvPowerSeries.coeff_pderiv, hl] at hh + exact mul_right_cancel₀ (by exact_mod_cast Nat.succ_ne_zero (l j)) hh + +/-- The Taylor series at zero of polynomial evaluation is the polynomial itself. -/ +theorem holomorphicTaylorSeries_eval (p : MvPolynomial (Fin n) ℂ) : + holomorphicTaylorSeries (fun z => MvPolynomial.eval z p) 0 = p := by + have ha (q : MvPolynomial (Fin n) ℂ) : AnalyticAt ℂ (fun z => MvPolynomial.eval z q) 0 := + AnalyticAt.aeval_mvPolynomial (fun i => analyticAt_pi_iff.mp analyticAt_id i) q + induction p using MvPolynomial.induction_on with + | C a => simpa using holomorphicTaylorSeries_const a (0 : Fin n → ℂ) + | add p q hp hq => + change taylorSeries (ofAnalyticAt (fun z => MvPolynomial.eval z (p + q)) (ha _)) = _ + have heq : ofAnalyticAt (fun z => MvPolynomial.eval z (p + q)) (ha _) = + ofAnalyticAt (fun z => MvPolynomial.eval z p) (ha _) + + ofAnalyticAt (fun z => MvPolynomial.eval z q) (ha _) := by + rw [← ofAnalyticAt_add] + apply ofAnalyticAt_eq_iff.mpr + exact .of_forall fun z => map_add _ _ _ + rw [heq, taylorSeries_add] + simp only [taylorSeries_ofAnalyticAt, hp, hq, MvPolynomial.coe_add] + | mul_X p i hp => + change taylorSeries (ofAnalyticAt (fun z => MvPolynomial.eval z (p * MvPolynomial.X i)) + (ha _)) = _ + have heq : ofAnalyticAt (fun z => MvPolynomial.eval z (p * MvPolynomial.X i)) (ha _) = + ofAnalyticAt (fun z => MvPolynomial.eval z p) (ha _) * + ofAnalyticAt (fun z : Fin n → ℂ => z i) (analyticAt_pi_iff.mp analyticAt_id i) := by + rw [← ofAnalyticAt_mul] + apply ofAnalyticAt_eq_iff.mpr + exact .of_forall fun z => by simp + rw [heq, taylorSeries_mul] + simp only [taylorSeries_ofAnalyticAt, hp, holomorphicTaylorSeries_coord, + MvPolynomial.coe_mul, MvPolynomial.coe_X] + +/-- Total Taylor order in one coordinate agrees with Mathlib's scalar analytic order. -/ +theorem order_one_coordinate {g : ℂ → ℂ} (hg : AnalyticAt ℂ g 0) : + order (ofAnalyticAt (fun z : Fin 1 → ℂ => g (z 0)) + (hg.comp_of_eq + ((ContinuousLinearMap.proj (0 : Fin 1) : (Fin 1 → ℂ) →L[ℂ] ℂ).analyticAt 0) rfl)) = + analyticOrderAt g 0 := by + have ha {g : ℂ → ℂ} (hg : AnalyticAt ℂ g 0) : + AnalyticAt ℂ (fun z : Fin 1 → ℂ => g (z 0)) 0 := + hg.comp_of_eq ((ContinuousLinearMap.proj (0 : Fin 1) : (Fin 1 → ℂ) →L[ℂ] ℂ).analyticAt 0) rfl + apply ENat.eq_of_forall_natCast_le_iff + intro d + change (d : ℕ∞) ≤ (holomorphicTaylorSeries (fun z : Fin 1 → ℂ => g (z 0)) 0).order ↔ _ + induction d generalizing g with + | zero => simp + | succ d ih => + rw [nat_succ_le_series_order_iff] + have hc : (holomorphicTaylorSeries (fun z : Fin 1 → ℂ => g (z 0)) 0).constantCoeff = g 0 := + constantCoeff_taylorSeries (ofAnalyticAt _ (ha hg)) + rw [hc] + by_cases hz : g 0 = 0 + · rw [and_iff_right hz, Fin.forall_fin_one] + rw [← holomorphicTaylorSeries_partialDeriv (ha hg) 0] + have hd : partialDeriv 0 (fun z : Fin 1 → ℂ => g (z 0)) = + fun z => deriv g (z 0) := by + funext z + simp [partialDeriv] + rw [hd, ih hg.deriv] + simpa only [Nat.cast_add, Nat.cast_one] using analyticOrderAt_deriv_ge_iff hg hz + · simp [hz, hg.analyticOrderAt_eq_zero.mpr hz] + +/-- Restriction to a complex line cannot lower total order. -/ +theorem order_le_analyticOrderAt_line {f : (Fin n → ℂ) → ℂ} + (hf : AnalyticAt ℂ f 0) (v : Fin n → ℂ) : + order (ofAnalyticAt f hf) ≤ analyticOrderAt (fun w : ℂ => f (w • v)) 0 := by + let e : (Fin 1 → ℂ) → (Fin n → ℂ) := fun z => z 0 • v + have he : AnalyticAt ℂ e 0 := + ((ContinuousLinearMap.proj (0 : Fin 1) : (Fin 1 → ℂ) →L[ℂ] ℂ).analyticAt 0).smul + analyticAt_const + have hf' : AnalyticAt ℂ f (e 0) := by simpa [e] using hf + have h := order_le_order_pullback e he (ofAnalyticAt f hf') + rw [pullback_ofAnalyticAt] at h + have hl : AnalyticAt ℂ (fun w : ℂ => f (w • v)) 0 := + hf.comp_of_eq (analyticAt_id.smul analyticAt_const) (zero_smul _ _) + have hscalar := order_one_coordinate hl + simp only [order, taylorSeries_ofAnalyticAt] at h hscalar ⊢ + simpa [e, Function.comp_def, hscalar] using h + +/-- **[Suwa][Suwa2024], Lemma 1.2.** A linear change makes the order on the last axis equal to the +total order. Positive ambient dimension is explicit; units are permitted and give +order zero. Evaluate the leading homogeneous part at a point with nonzero last +coordinate; the higher-order remainder cannot cancel it along the resulting line. -/ +theorem exists_coordinate_change_order {f : (Fin (n + 1) → ℂ) → ℂ} + (hf : AnalyticAt ℂ f 0) (hne : ofAnalyticAt f hf ≠ 0) : + ∃ L : (Fin (n + 1) → ℂ) ≃L[ℂ] (Fin (n + 1) → ℂ), + analyticOrderAt (fun w : ℂ => f (L (Pi.single (Fin.last n) w))) 0 = + order (ofAnalyticAt f hf) := by + obtain ⟨d, hd⟩ := ENat.ne_top_iff_exists.mp + (show order (ofAnalyticAt f hf) ≠ ⊤ from fun h => hne ((order_eq_top_iff _).mp h)) + let p := taylorSeries (ofAnalyticAt f hf) + let q := MvPowerSeries.truncTotal (d + 1) p + have hp : p.order = d := hd.symm + have hqcoeff (k : Fin (n + 1) →₀ ℕ) : q.coeff k = + if k.degree < d + 1 then MvPowerSeries.coeff k p else 0 := + MvPowerSeries.coeff_truncTotal_eq_ite p + have hqdeg (k : Fin (n + 1) →₀ ℕ) (hk : k ∈ q.support) : k.degree = d := by + have hn := MvPolynomial.mem_support_iff.mp hk + rw [hqcoeff] at hn + split_ifs at hn with hlt + · have hge : d ≤ k.degree := by + by_contra! h + exact hn (MvPowerSeries.coeff_of_lt_order (by simpa [hp] using h)) + omega + · exact (hn rfl).elim + have hqne : q ≠ 0 := by + obtain ⟨k, hk, hkd⟩ := (order_eq_nat_iff (ofAnalyticAt f hf) d).mp hd.symm |>.1 + intro hq + have h := congrArg (fun q : MvPolynomial (Fin (n + 1)) ℂ => q.coeff k) hq + simp only [hqcoeff, hkd, Nat.lt_succ_self, ite_true, AddMonoidAlgebra.coeff_zero] at h + exact hk h + obtain ⟨v, hv⟩ : ∃ v : Fin (n + 1) → ℂ, + MvPolynomial.eval v (q * MvPolynomial.X (Fin.last n)) ≠ 0 := by + by_contra! h + exact (mul_ne_zero hqne (MvPolynomial.X_ne_zero _)) + (MvPolynomial.funext fun z => by simpa using h z) + have hvq : MvPolynomial.eval v q ≠ 0 := (mul_ne_zero_iff.mp (by simpa using hv)).1 + have hvi : v (Fin.last n) ≠ 0 := (mul_ne_zero_iff.mp (by simpa using hv)).2 + have hqline (w : ℂ) : MvPolynomial.eval (w • v) q = w ^ d * MvPolynomial.eval v q := by + simp only [MvPolynomial.eval_eq', Pi.smul_apply, smul_eq_mul, mul_pow, + Finset.prod_mul_distrib, Finset.prod_pow_eq_pow_sum, ← Finsupp.degree_eq_sum, + Finset.mul_sum] + apply Finset.sum_congr rfl + intro k hk + rw [hqdeg k hk] + ring + let g : (Fin (n + 1) → ℂ) → ℂ := fun z => MvPolynomial.eval z q + have hg : AnalyticAt ℂ g 0 := + AnalyticAt.aeval_mvPolynomial (fun i => analyticAt_pi_iff.mp analyticAt_id i) q + have ht : taylorSeries (ofAnalyticAt g hg) = q := holomorphicTaylorSeries_eval q + have hr : (d + 1 : ℕ) ≤ order (ofAnalyticAt (f - g) (hf.sub hg)) := by + have hs : taylorSeries (ofAnalyticAt (f - g) (hf.sub hg)) = p - q := by + have heq : ofAnalyticAt (f - g) (hf.sub hg) + ofAnalyticAt g hg = + ofAnalyticAt f hf := by + rw [← ofAnalyticAt_add] + apply ofAnalyticAt_eq_iff.mpr + exact .of_forall fun z => sub_add_cancel _ _ + have h := congrArg taylorSeries heq + rw [taylorSeries_add, ht] at h + exact eq_sub_of_add_eq h + apply MvPowerSeries.nat_le_order + intro k hk + rw [hs, map_sub, MvPolynomial.coeff_coe, hqcoeff, ite_eq_left hk, sub_self] + have hrem := le_trans hr (order_le_analyticOrderAt_line (hf.sub hg) v) + have hgo : analyticOrderAt (fun w : ℂ => g (w • v)) 0 = d := by + apply (AnalyticAt.analyticOrderAt_eq_natCast + (hg.comp_of_eq (analyticAt_id.smul analyticAt_const) (by simp))).mpr + refine ⟨fun _ => MvPolynomial.eval v q, analyticAt_const, hvq, ?_⟩ + exact .of_forall fun w => by simpa [g, sub_zero, smul_eq_mul] using hqline w + have hlt : analyticOrderAt (fun w : ℂ => g (w • v)) 0 < + analyticOrderAt (fun w : ℂ => (f - g) (w • v)) 0 := by + rw [hgo] + exact lt_of_lt_of_le (by exact_mod_cast Nat.lt_succ_self d) hrem + have hsum := analyticOrderAt_add_eq_left_of_lt hlt + have hfo : analyticOrderAt (fun w : ℂ => f (w • v)) 0 = d := by + have heq : (fun w : ℂ => g (w • v)) + (fun w : ℂ => (f - g) (w • v)) = + fun w : ℂ => f (w • v) := by + funext w + dsimp + ring + rw [heq, hgo] at hsum + exact hsum + refine ⟨(shearToLastAxis v (Fin.last n) hvi).toContinuousLinearEquiv, ?_⟩ + simpa only [LinearEquiv.coe_toContinuousLinearEquiv', shearToLastAxis_single, hd] using hfo + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Polynomial.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Polynomial.lean new file mode 100644 index 0000000000..027bbb8cde --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Polynomial.lean @@ -0,0 +1,221 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.Polynomial.Eisenstein.Distinguished +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation + +/-! +# Polynomials with analytic-germ coefficients + +Evaluation in the last coordinate maps `Polynomial (AnalyticGerm ℂ 0)` into the analytic germs on +the product with `ℂ`. Weierstrass polynomials are expressed using Mathlib's +`Polynomial.IsDistinguishedAt` at the coefficient ring's maximal ideal. + +Polynomial injectivity is proved by restriction to the zero section and Horner induction. +Normalization of factors of distinguished polynomials (Lemma 1.8.2) is proved by reduction +modulo the maximal ideal. Irreducibility (Lemma 1.8.1(b)) is proved in `Weierstrass.lean`; the +coefficient bookkeeping behind Weierstrass division and preparation, and the resulting quotient +comparison (Lemma 1.8.1(a)), are in `CoefficientPolynomial.lean` and `Weierstrass.lean`. The +irreducibility statement explicitly excludes units in the analytic germ ring: without that +hypothesis the source's Lemma 1.8.1(b) fails, for example for `X - 1`. + +## Main definitions + +* `parameterHom`: Parameter germs pull back to the product by forgetting its last coordinate. +* `lastCoordinate`: The analytic germ of the last coordinate. +* `polynomialHom`: Evaluate a polynomial in the last coordinate, pulling back its coefficient germs. + +## Main results + +* `polynomialHom_injective`: Polynomial expressions in the last coordinate have unique coefficient + germs. +* `isDistinguishedAt_iff`: Distinguished polynomials have precisely the usual Weierstrass + coefficient conditions. +* `isDistinguishedAt_of_monic_dvd`: A monic divisor of a distinguished polynomial is distinguished. +* `exists_distinguished_factors`: Factors of a distinguished polynomial become distinguished after + multiplying by reciprocal coefficient units (Lemma 1.8.2). +-/ + +public noncomputable section + +namespace SeveralComplexVariables.AnalyticGerm + +open Filter +open scoped Topology + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Parameter germs pull back to the product by forgetting its last coordinate. -/ +@[expose] def parameterHom : AnalyticGerm ℂ (0 : E) →ₐ[ℂ] AnalyticGerm ℂ (0 : E × ℂ) := + pullback (x := (0 : E × ℂ)) Prod.fst analyticAt_fst + +/-- The analytic germ of the last coordinate. -/ +@[expose] def lastCoordinate : AnalyticGerm ℂ (0 : E × ℂ) := + ofAnalyticAt Prod.snd analyticAt_snd + +/-- Evaluate a polynomial in the last coordinate, pulling back its coefficient germs. -/ +@[expose] def polynomialHom : Polynomial (AnalyticGerm ℂ (0 : E)) →+* AnalyticGerm ℂ (0 : E × ℂ) := + Polynomial.eval₂RingHom parameterHom.toRingHom lastCoordinate + +/-- A constant polynomial gives the corresponding parameter germ on the product. -/ +@[simp] theorem polynomialHom_C (a : AnalyticGerm ℂ (0 : E)) : + polynomialHom (Polynomial.C a) = parameterHom a := by + simp [polynomialHom] + +/-- The indeterminate gives the last-coordinate germ. -/ +@[simp] theorem polynomialHom_X : + polynomialHom (Polynomial.X : Polynomial (AnalyticGerm ℂ (0 : E))) = lastCoordinate := by + simp [polynomialHom] + +/-- Distinguished polynomials have precisely the usual Weierstrass coefficient conditions. -/ +theorem isDistinguishedAt_iff (p : Polynomial (AnalyticGerm ℂ (0 : E))) : + p.IsDistinguishedAt (IsLocalRing.maximalIdeal _) ↔ + p.Monic ∧ ∀ i < p.natDegree, eval 0 (p.coeff i) = 0 := by + constructor + · intro h + exact ⟨h.monic, fun i hi => (mem_maximalIdeal_iff _).mp (h.mem hi)⟩ + · rintro ⟨hm, h⟩ + exact ⟨⟨fun {i} hi => (mem_maximalIdeal_iff _).mpr (h i hi)⟩, hm⟩ + +/-- Restricting a polynomial germ to the zero section recovers its constant coefficient. -/ +@[simp] theorem pullback_zeroSection_polynomialHom + (p : Polynomial (AnalyticGerm ℂ (0 : E))) : + pullback (fun z : E => (z, (0 : ℂ))) (analyticAt_id.prod analyticAt_const) + (polynomialHom p) = p.coeff 0 := by + have h : (pullback (fun z : E => (z, (0 : ℂ))) + (analyticAt_id.prod analyticAt_const)).toRingHom.comp polynomialHom = + Polynomial.constantCoeff := by + apply Polynomial.ringHom_ext + · intro a + obtain ⟨f, hf, rfl⟩ := exists_rep a + change pullback (fun z : E => (z, (0 : ℂ))) (analyticAt_id.prod analyticAt_const) + (polynomialHom (Polynomial.C (ofAnalyticAt f hf))) = + (Polynomial.C (ofAnalyticAt f hf)).coeff 0 + rw [polynomialHom_C, Polynomial.coeff_C_zero] + rfl + · change pullback (fun z : E => (z, (0 : ℂ))) (analyticAt_id.prod analyticAt_const) + (polynomialHom (Polynomial.X : Polynomial (AnalyticGerm ℂ (0 : E)))) = + (Polynomial.X : Polynomial (AnalyticGerm ℂ (0 : E))).coeff 0 + rw [polynomialHom_X, Polynomial.coeff_X_zero] + rfl + exact DFunLike.congr_fun h p + +/-- The distinguished coordinate is a nonzero germ, even with no parameter variables. -/ +theorem lastCoordinate_ne_zero : (lastCoordinate (E := E)) ≠ 0 := by + intro h + have he : (Prod.snd : E × ℂ → ℂ) =ᶠ[𝓝 0] 0 := + Germ.coe_eq.mp (congrArg Subtype.val h) + have ht : Tendsto (fun w : ℂ => ((0 : E), w)) (𝓝 0) (𝓝 0) := + continuous_const.prodMk continuous_id |>.tendsto 0 + have hi : (id : ℂ → ℂ) =ᶠ[𝓝 0] 0 := he.comp_tendsto ht + exact one_ne_zero ((hasDerivAt_id (0 : ℂ)).congr_of_eventuallyEq hi.symm |>.unique + (hasDerivAt_const (0 : ℂ) (0 : ℂ))) + +/-- Polynomial expressions in the last coordinate have unique coefficient germs. Restriction to the +zero section detects constants; Horner induction and cancellation of the nonzero last-coordinate +germ detect all remaining coefficients. -/ +theorem polynomialHom_injective : Function.Injective (polynomialHom (E := E)) := by + have hker : ∀ p : Polynomial (AnalyticGerm ℂ (0 : E)), polynomialHom p = 0 → p = 0 := by + intro p + induction p using Polynomial.recOnHorner with + | M0 => exact fun _ => rfl + | MC p a hp ha ih => + intro h + have hc := congrArg (pullback (fun z : E => (z, (0 : ℂ))) + (analyticAt_id.prod analyticAt_const)) h + have : a = 0 := by + simpa only [pullback_zeroSection_polynomialHom, map_zero, + Polynomial.coeff_add, Polynomial.coeff_C_zero, hp, zero_add] using hc + exact (ha this).elim + | MX p hp ih => + intro h + have hz : polynomialHom p = 0 := + (mul_eq_zero.mp (by simpa using h)).resolve_right lastCoordinate_ne_zero + simp [ih hz] + intro p q h + have hz := hker (p - q) (by simp [h]) + exact sub_eq_zero.mp hz + +/-- A monic divisor of a distinguished polynomial is distinguished. Reduction modulo the maximal +ideal makes it a monic divisor of a power of `X`, hence itself a power of `X`. -/ +theorem isDistinguishedAt_of_monic_dvd {p w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hp : p.Monic) (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) (hd : p ∣ w) : + p.IsDistinguishedAt (IsLocalRing.maximalIdeal _) := by + classical + let I := IsLocalRing.maximalIdeal (AnalyticGerm ℂ (0 : E)) + let π := Ideal.Quotient.mk I + have hdiv : p.map π ∣ Polynomial.X ^ w.natDegree := by + rw [← hw.map_eq_X_pow] + exact Polynomial.map_dvd π hd + obtain ⟨k, _, hk⟩ := (dvd_prime_pow Polynomial.prime_X w.natDegree).mp hdiv + have he : p.map π = Polynomial.X ^ k := + Polynomial.eq_of_monic_of_associated (hp.map π) (Polynomial.monic_X_pow k) hk + have hdeg : p.natDegree = k := by + simpa only [hp.natDegree_map, Polynomial.natDegree_X_pow] using congrArg Polynomial.natDegree he + refine ⟨⟨fun {j} hj => ?_⟩, hp⟩ + have hc := congrArg (fun r => Polynomial.coeff r j) he + have hjk : j ≠ k := ne_of_lt (hdeg ▸ hj) + have hz : π (p.coeff j) = 0 := by + simpa only [Polynomial.coeff_map, Polynomial.coeff_X_pow, ite_eq_right hjk] using hc + exact Ideal.Quotient.eq_zero_iff_mem.mp hz + +/-- Factors of a distinguished polynomial become distinguished after multiplying by reciprocal +coefficient units (Lemma 1.8.2). Normalize leading coefficients and use that monic divisors +remain distinguished after reduction modulo the maximal ideal. -/ +theorem exists_distinguished_factors (p q : Polynomial (AnalyticGerm ℂ (0 : E))) + (h : (p * q).IsDistinguishedAt (IsLocalRing.maximalIdeal _)) : + ∃ u : (AnalyticGerm ℂ (0 : E))ˣ, + (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p).IsDistinguishedAt + (IsLocalRing.maximalIdeal _) ∧ + (Polynomial.C (↑(u⁻¹) : AnalyticGerm ℂ (0 : E)) * q).IsDistinguishedAt + (IsLocalRing.maximalIdeal _) := by + have hlc : p.leadingCoeff * q.leadingCoeff = 1 := by + rw [← Polynomial.leadingCoeff_mul] + exact h.monic + let u : (AnalyticGerm ℂ (0 : E))ˣ := + ⟨q.leadingCoeff, p.leadingCoeff, by simpa only [mul_comm] using hlc, hlc⟩ + have hp : (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p).Monic := + Polynomial.monic_C_mul_of_mul_leadingCoeff_eq_one u.val_inv + have hq : (Polynomial.C (↑(u⁻¹) : AnalyticGerm ℂ (0 : E)) * q).Monic := + Polynomial.monic_C_mul_of_mul_leadingCoeff_eq_one u.inv_val + have he : (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p) * + (Polynomial.C (↑(u⁻¹) : AnalyticGerm ℂ (0 : E)) * q) = p * q := by + calc + _ = Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * + Polynomial.C (↑(u⁻¹) : AnalyticGerm ℂ (0 : E)) * (p * q) := by ring + _ = _ := by rw [← Polynomial.C_mul]; simp + refine ⟨u, isDistinguishedAt_of_monic_dvd hp h ?_, + isDistinguishedAt_of_monic_dvd hq h ?_⟩ + · rw [← he] + exact dvd_mul_right _ _ + · rw [← he] + exact dvd_mul_left _ _ + +/-- The product of two distinguished polynomials is distinguished, of the sum of their degrees. +Reduction modulo the maximal ideal sends the product to a product of powers of `X`, hence to a +power of `X` of the total degree. -/ +theorem isDistinguishedAt_mul {p q : Polynomial (AnalyticGerm ℂ (0 : E))} + (hp : p.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (hq : q.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) : + (p * q).IsDistinguishedAt (IsLocalRing.maximalIdeal _) := by + have hpq : (p * q).Monic := hp.monic.mul hq.monic + have hdeg : (p * q).natDegree = p.natDegree + q.natDegree := hp.monic.natDegree_mul hq.monic + refine ⟨⟨fun {j} hj => ?_⟩, hpq⟩ + have he : (p * q).map (Ideal.Quotient.mk (IsLocalRing.maximalIdeal (AnalyticGerm ℂ (0 : E)))) = + Polynomial.X ^ (p * q).natDegree := by + rw [Polynomial.map_mul, hp.map_eq_X_pow, hq.map_eq_X_pow, hdeg, pow_add] + have hc := congrArg (fun r => Polynomial.coeff r j) he + have hz : (Ideal.Quotient.mk (IsLocalRing.maximalIdeal (AnalyticGerm ℂ (0 : E)))) + ((p * q).coeff j) + = 0 := by + simpa only [Polynomial.coeff_map, Polynomial.coeff_X_pow, ite_eq_right hj.ne] using hc + exact Ideal.Quotient.eq_zero_iff_mem.mp hz + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/RelativePrimality.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/RelativePrimality.lean new file mode 100644 index 0000000000..141d6deb1c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/RelativePrimality.lean @@ -0,0 +1,187 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination + +/-! +# Persistence of relative primality + +Relative primality is an open condition on the base point for two fixed analytic representatives +in finite dimension. We use `IsRelPrime`, not the stronger Bezout condition `IsCoprime`. A germ +at one point is not evaluated at other points; instead, the statement explicitly takes the germs +of the same representatives nearby. Weierstrass preparation and a resultant identity eliminate +one variable. The resulting nonzero parameter germ is relatively prime to the first germ on +every nearby scalar fiber, which excludes a common nonunit divisor. Analytic coordinate changes +reduce the general case to this argument; openness is its direct consequence. + +## Main results + +* `eventually_isRelPrime_of_orderInLastVariable`: Relative primality persists when the first germ + has finite order on the central fiber. +* `eventually_isRelPrime_of_comp_homeomorph`: Persistence of relative primality transports through + analytic changes of coordinates. +* `eventually_isRelPrime_ofAnalyticAt_prod`: Relative primality persists on a parameter space times + the scalar line. +* `eventually_isRelPrime_ofAnalyticAt`: Relatively prime germs of two analytic representatives + remain relatively prime nearby. +* `isOpen_isRelPrime_locus`: The locus where two functions are analytic and their germs are + relatively prime is open. +-/ + +public section + +open Filter Set +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + +/-- Relative primality persists when the first germ has finite order on the central fiber. -/ +theorem eventually_isRelPrime_of_orderInLastVariable {f g : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) {d : ℕ} + (hd : orderInLastVariable (ofAnalyticAt f hf) = d) + (hrel : IsRelPrime (ofAnalyticAt f hf) (ofAnalyticAt g hg)) : + ∀ᶠ y in 𝓝 (0 : E × ℂ), ∃ (hfy : AnalyticAt ℂ f y) (hgy : AnalyticAt ℂ g y), + IsRelPrime (ofAnalyticAt f hfy) (ofAnalyticAt g hgy) := by + obtain ⟨h, hne, a, b, hab⟩ := exists_base_combination_of_isRelPrime hd hrel + obtain ⟨h, hh, rfl⟩ := exists_rep h + obtain ⟨a, ha, rfl⟩ := exists_rep a + obtain ⟨b, hb, rfl⟩ := exists_rep b + change ofAnalyticAt (fun y : E × ℂ => h y.1) (hh.comp_of_eq analyticAt_fst rfl) = + ofAnalyticAt (fun y => a y * f y + b y * g y) ((ha.mul hf).add (hb.mul hg)) at hab + have heq : (fun y : E × ℂ => h y.1) =ᶠ[𝓝 0] + (fun y => a y * f y + b y * g y) := ofAnalyticAt_eq_iff.mp hab + have hfiber : ¬ (fun w : ℂ => f (0, w)) =ᶠ[𝓝 0] 0 := by + intro hz + have ht := analyticOrderAt_eq_top.mpr hz + rw [← orderInLastVariable_ofAnalyticAt f hf, hd] at ht + exact ENat.natCast_ne_top d ht + have hbase : ∀ᶠ y : E × ℂ in 𝓝 0, + ∃ hy : AnalyticAt ℂ h y.1, ofAnalyticAt h hy ≠ 0 := + (continuous_fst.continuousAt : Tendsto (Prod.fst : E × ℂ → E) (𝓝 0) (𝓝 0)).eventually + (eventually_ne_zero_ofAnalyticAt hh hne) + filter_upwards [heq.eventually_nhds, hbase, + eventually_fiber_ne_zero_ofAnalyticAt hf hfiber, hg.eventually_analyticAt, + ha.eventually_analyticAt, hb.eventually_analyticAt] with y he hyh hyf hyg hya hyb + obtain ⟨hyh, hyhne⟩ := hyh + obtain ⟨hyf, hyfiber⟩ := hyf + refine ⟨hyf, hyg, ?_⟩ + have hcomb : basePullback y (ofAnalyticAt h hyh) = + ofAnalyticAt a hya * ofAnalyticAt f hyf + ofAnalyticAt b hyb * ofAnalyticAt g hyg := by + change ofAnalyticAt (fun z : E × ℂ => h z.1) (hyh.comp_of_eq analyticAt_fst rfl) = + ofAnalyticAt (fun z => a z * f z + b z * g z) ((hya.mul hyf).add (hyb.mul hyg)) + exact ofAnalyticAt_eq_iff.mpr he + have hp := isRelPrime_basePullback_of_fiber_ne_zero y hyhne hyfiber + intro c hcf hcg + apply hp _ hcf + rw [hcomb] + exact dvd_add (dvd_mul_of_dvd_right hcf _) (dvd_mul_of_dvd_right hcg _) + +omit [FiniteDimensional ℂ E] in +/-- Persistence of relative primality transports through analytic changes of coordinates. -/ +theorem eventually_isRelPrime_of_comp_homeomorph + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + (e : E ≃ₜ F) (he : ∀ z, AnalyticAt ℂ e z) (hi : ∀ y, AnalyticAt ℂ e.symm y) + {f g : F → ℂ} {x : E} + (h : ∀ᶠ z in 𝓝 x, ∃ (hf : AnalyticAt ℂ (f ∘ e) z) + (hg : AnalyticAt ℂ (g ∘ e) z), IsRelPrime (ofAnalyticAt (f ∘ e) hf) + (ofAnalyticAt (g ∘ e) hg)) : + ∀ᶠ y in 𝓝 (e x), ∃ (hf : AnalyticAt ℂ f y) (hg : AnalyticAt ℂ g y), + IsRelPrime (ofAnalyticAt f hf) (ofAnalyticAt g hg) := by + have ht : Tendsto e.symm (𝓝 (e x)) (𝓝 x) := by + simpa only [e.symm_apply_apply] using e.symm.continuous.tendsto (e x) + filter_upwards [ht.eventually h] with y hy + obtain ⟨hf, hg, hrel⟩ := hy + have hfy : AnalyticAt ℂ f y := by + simpa only [Function.comp_def, e.apply_symm_apply] using + hf.comp_of_eq (hi y) rfl + have hgy : AnalyticAt ℂ g y := by + simpa only [Function.comp_def, e.apply_symm_apply] using + hg.comp_of_eq (hi y) rfl + let q := pullbackEquivOfEq e (e.symm y) (he _) (hi _) (e.apply_symm_apply y) + refine ⟨hfy, hgy, IsRelPrime.of_map q ?_⟩ + simpa only [q, pullbackEquivOfEq_ofAnalyticAt] using hrel + +/-- Relative primality persists on a parameter space times the scalar line. -/ +theorem eventually_isRelPrime_ofAnalyticAt_prod {f g : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) + (h : IsRelPrime (ofAnalyticAt f hf) (ofAnalyticAt g hg)) : + ∀ᶠ y in 𝓝 (0 : E × ℂ), ∃ (hfy : AnalyticAt ℂ f y) (hgy : AnalyticAt ℂ g y), + IsRelPrime (ofAnalyticAt f hfy) (ofAnalyticAt g hgy) := by + by_cases hzero : ofAnalyticAt f hf = 0 + · have hunit : g 0 ≠ 0 := by + simpa only [hzero, isRelPrime_zero_left, isUnit_iff, eval_ofAnalyticAt] using h + filter_upwards [hf.eventually_analyticAt, hg.eventually_analyticAt, + hg.continuousAt.eventually_ne hunit] with y hfy hgy hy + exact ⟨hfy, hgy, ((isUnit_iff (ofAnalyticAt g hgy)).mpr hy).isRelPrime_right⟩ + obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change hf + ((ofAnalyticAt_ne_zero_iff hf).mp hzero) + have hfL : AnalyticAt ℂ (f ∘ L) 0 := hf.comp_of_eq (L.analyticAt 0) L.map_zero + have hgL : AnalyticAt ℂ (g ∘ L) 0 := hg.comp_of_eq (L.analyticAt 0) L.map_zero + let q := pullbackEquivOfEq L.toHomeomorph 0 (L.analyticAt 0) + (L.symm.analyticAt (L 0)) L.map_zero + have hq : IsRelPrime (q (ofAnalyticAt f hf)) (q (ofAnalyticAt g hg)) := + IsRelPrime.of_map q.symm (by simpa only [AlgEquiv.symm_apply_apply] using h) + have hL : IsRelPrime (ofAnalyticAt (f ∘ L) hfL) (ofAnalyticAt (g ∘ L) hgL) := by + have hqf : q (ofAnalyticAt f hf) = ofAnalyticAt (f ∘ L) hfL := + pullbackEquivOfEq_ofAnalyticAt L.toHomeomorph 0 (L.analyticAt 0) + (L.symm.analyticAt (L 0)) L.map_zero f hf + have hqg : q (ofAnalyticAt g hg) = ofAnalyticAt (g ∘ L) hgL := + pullbackEquivOfEq_ofAnalyticAt L.toHomeomorph 0 (L.analyticAt 0) + (L.symm.analyticAt (L 0)) L.map_zero g hg + rwa [hqf, hqg] at hq + have hp := eventually_isRelPrime_of_orderInLastVariable hfL hgL hd hL + simpa only [ContinuousLinearEquiv.coe_toHomeomorph, map_zero] using + eventually_isRelPrime_of_comp_homeomorph L.toHomeomorph L.analyticAt L.symm.analyticAt hp + +/-- Relatively prime germs of two analytic representatives remain relatively prime nearby. Neither +germ is required to be nonzero: the relatively prime zero case forces a unit. -/ +theorem eventually_isRelPrime_ofAnalyticAt {f g : E → ℂ} {x : E} + (hf : AnalyticAt ℂ f x) (hg : AnalyticAt ℂ g x) + (h : IsRelPrime (ofAnalyticAt f hf) (ofAnalyticAt g hg)) : + ∀ᶠ y in 𝓝 x, ∃ (hfy : AnalyticAt ℂ f y) (hgy : AnalyticAt ℂ g y), + IsRelPrime (ofAnalyticAt f hfy) (ofAnalyticAt g hgy) := by + classical + rcases hdim : Module.finrank ℂ E with _ | n + · have : Subsingleton E := Module.finrank_zero_iff.mp hdim + exact Filter.Eventually.of_forall (fun y => by + obtain rfl := Subsingleton.elim y x + exact ⟨hf, hg, h⟩) + · let en : E ≃L[ℂ] (Fin (n + 1) → ℂ) := by + rw [← hdim] + exact (Module.finBasis ℂ E).equivFunL + let ep : (Fin (n + 1) → ℂ) ≃ₗ[ℂ] (Fin n → ℂ) × ℂ := + (LinearEquiv.piCongrLeft ℂ (fun _ => ℂ) (finSuccEquiv n)).trans + ((LinearEquiv.piOptionEquivProd ℂ).trans (LinearEquiv.prodComm ℂ _ _)) + let e := en.trans ep.toContinuousLinearEquiv + let H := e.symm.toHomeomorph.trans (Homeomorph.addRight x) + have hH : ∀ z, AnalyticAt ℂ H z := fun z => (e.symm.analyticAt z).add analyticAt_const + have hHi : ∀ y, AnalyticAt ℂ H.symm y := fun y => + (e.analyticAt (y + -x)).comp_of_eq (analyticAt_id.add analyticAt_const) rfl + have hH0 : H 0 = x := by simp [H] + have hfH : AnalyticAt ℂ (f ∘ H) 0 := hf.comp_of_eq (hH 0) hH0 + have hgH : AnalyticAt ℂ (g ∘ H) 0 := hg.comp_of_eq (hH 0) hH0 + let q := pullbackEquivOfEq H 0 (hH 0) (hHi _) hH0 + have hq : IsRelPrime (q (ofAnalyticAt f hf)) (q (ofAnalyticAt g hg)) := + IsRelPrime.of_map q.symm (by simpa only [AlgEquiv.symm_apply_apply] using h) + have hHrel : IsRelPrime (ofAnalyticAt (f ∘ H) hfH) (ofAnalyticAt (g ∘ H) hgH) := by + simpa only [q, pullbackEquivOfEq_ofAnalyticAt] using hq + have hp := eventually_isRelPrime_ofAnalyticAt_prod hfH hgH hHrel + simpa only [hH0] using eventually_isRelPrime_of_comp_homeomorph H hH hHi hp + +/-- The locus where two functions are analytic and their germs are relatively prime is open. -/ +theorem isOpen_isRelPrime_locus (f g : E → ℂ) : + IsOpen {x | ∃ (hf : AnalyticAt ℂ f x) (hg : AnalyticAt ℂ g x), + IsRelPrime (ofAnalyticAt f hf) (ofAnalyticAt g hg)} := by + apply isOpen_iff_mem_nhds.mpr + rintro x ⟨hf, hg, h⟩ + exact eventually_isRelPrime_ofAnalyticAt hf hg h + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Units.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Units.lean new file mode 100644 index 0000000000..6d49d6a938 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Units.lean @@ -0,0 +1,65 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.SpecialFunctions.Complex.Analytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm + +/-! +# Roots of unit germs + +Every scalar analytic unit germ has an analytic root of each positive integral degree. We +normalize the value to one before using Mathlib's analytic complex power function; no global +choice of logarithm on the domain is required. These elementary local facts are used, for +example, when absorbing units into irreducible factorizations. + +## Main results + +`exists_isUnit_pow_eq` produces an analytic unit root of each positive integral degree. +`exists_analyticAt_pow_eq` is the corresponding statement for representatives. +-/ + +public noncomputable section + +open Filter +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] {x : E} + +/-- A nonvanishing analytic function has a local analytic root of every positive degree. -/ +theorem exists_analyticAt_pow_eq {f : E → ℂ} (hf : AnalyticAt ℂ f x) + (hx : f x ≠ 0) {n : ℕ} (hn : n ≠ 0) : + ∃ g : E → ℂ, AnalyticAt ℂ g x ∧ (fun y => g y ^ n) =ᶠ[𝓝 x] f := by + let g : E → ℂ := fun y => (f x ^ ((n : ℂ)⁻¹)) * ((f y / f x) ^ ((n : ℂ)⁻¹)) + refine ⟨g, ?_, .of_forall fun y => ?_⟩ + · apply AnalyticAt.mul analyticAt_const + apply hf.div_const.cpow analyticAt_const + simp [hx] + · dsimp [g] + rw [mul_pow, Complex.cpow_nat_inv_pow _ hn, Complex.cpow_nat_inv_pow _ hn] + exact mul_div_cancel₀ _ hx + +/-- Every unit germ has an `n`-th root which is itself a unit, for `n ≠ 0`. -/ +theorem exists_isUnit_pow_eq (u : AnalyticGerm ℂ x) (hu : IsUnit u) + {n : ℕ} (hn : n ≠ 0) : ∃ v : AnalyticGerm ℂ x, IsUnit v ∧ v ^ n = u := by + obtain ⟨f, hf, rfl⟩ := exists_rep u + obtain ⟨g, hg, he⟩ := exists_analyticAt_pow_eq hf ((isUnit_iff _).mp hu) hn + have hp : ofAnalyticAt g hg ^ n = ofAnalyticAt f hf := by + apply Subtype.ext + exact Germ.coe_eq.mpr he + refine ⟨ofAnalyticAt g hg, ?_, hp⟩ + apply (isUnit_iff _).mpr + intro hz + have hval := congrArg (eval x) hp + have hnonzero := (isUnit_iff _).mp hu + rw [map_pow, hz, zero_pow hn] at hval + exact hnonzero hval.symm + +end SeveralComplexVariables.AnalyticGerm + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean new file mode 100644 index 0000000000..5900d50670 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean @@ -0,0 +1,424 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial + +/-! +# Weierstrass theorems in the germ ring + +These interfaces express division and preparation directly in the analytic germ ring, using +ordinary polynomials over parameter germs and Mathlib's distinguished-polynomial predicate. +Polynomial degree (rather than natural degree) handles the zero remainder and degree-zero +divisors uniformly. Units are represented by the existing units group. + +Existence and uniqueness of both division and preparation are proved by choosing analytic +representatives, applying the analytic Weierstrass theorems on any finite-dimensional parameter +space, and reassembling the polynomial coefficients using the bookkeeping in +`CoefficientPolynomial.lean`. Polynomial preservation under division (Lemma 1.8.1(a)) follows by +comparing ordinary Euclidean division of polynomials with germ division uniqueness. The +irreducibility equivalence is proved. Finite simultaneous preparation follows from the proved +finite normalization theorem and the existing analytic preparation theorem. + +## Main results + +* `existsUnique_division`: Division by a distinguished polynomial has a unique germ quotient and + polynomial remainder of smaller degree. +* `existsUnique_preparation`: Preparation has a unique unit and distinguished polynomial of the + prescribed order. +* `irreducible_polynomialHom_iff`: A distinguished polynomial is irreducible exactly when its + analytic germ is. +* `prime_polynomialHom_of_isDistinguishedAt`: The image of a prime distinguished polynomial is + itself prime. +* `exists_equiv_forall_isWeierstrassPreparationAt`: One coordinate system permits preparation of all + members of a finite family. +-/ + +public noncomputable section + +open Filter +open scoped Topology + +namespace SeveralComplexVariables.AnalyticGerm + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Division by a distinguished polynomial has a unique germ quotient and polynomial remainder of +smaller degree. Choose representatives and apply analytic Weierstrass division, then identify +the germ quotient and coefficient germs by uniqueness. -/ +theorem existsUnique_division [FiniteDimensional ℂ E] + (w : Polynomial (AnalyticGerm ℂ (0 : E))) + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) (f : AnalyticGerm ℂ (0 : E × ℂ)) : + ∃! qr : AnalyticGerm ℂ (0 : E × ℂ) × Polynomial (AnalyticGerm ℂ (0 : E)), + qr.2.degree < (w.natDegree : WithBot ℕ) ∧ + f = qr.1 * polynomialHom w + polynomialHom qr.2 := by + set d := w.natDegree with hd_def + obtain ⟨hwmon, hwcoeff0⟩ := (isDistinguishedAt_iff w).mp hw + have hweq : w = ofCoefficients (fun j : Fin d => w.coeff (j : ℕ)) := + eq_ofCoefficients_of_monic hwmon hd_def + choose a0 ha0 haeq using fun j : Fin d => exists_rep (w.coeff (j : ℕ)) + have ha00 : ∀ j : Fin d, a0 j 0 = 0 := by + intro j + have h0 := hwcoeff0 (j : ℕ) (hd_def ▸ j.isLt) + rw [← haeq j, eval_ofAnalyticAt] at h0 + exact h0 + have hweq2 : w = ofCoefficients (fun j : Fin d => ofAnalyticAt (a0 j) (ha0 j)) := by + rw [hweq]; congr 1; funext j; exact (haeq j).symm + have hwhom : polynomialHom w = ofAnalyticAt (weierstrassPolynomial a0) + (analyticAt_weierstrassPolynomial ha0) := by + rw [hweq2]; exact polynomialHom_ofCoefficients a0 ha0 + have horder : analyticOrderAt (fun t : ℂ => weierstrassPolynomial a0 (0, t)) 0 = d := by + have hcentral : (fun t : ℂ => weierstrassPolynomial a0 (0, t)) = fun t : ℂ => t ^ d := + funext (weierstrassPolynomial_central ha00) + rw [hcentral] + show analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d + rw [analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ)) d, analyticOrderAt_id]; simp + obtain ⟨f0, hf0, rfl⟩ := exists_rep f + obtain ⟨q, a, Hdiv, huniqdiv⟩ := + exists_isWeierstrassDivisionAt_of_finiteDimensional + (analyticAt_weierstrassPolynomial ha0) hf0 horder + set r : Polynomial (AnalyticGerm ℂ (0 : E)) := + remainderOfCoefficients (fun j => ofAnalyticAt (a j) (Hdiv.analyticAt_coeff j)) with hr_def + have hrdeg : r.degree < (d : WithBot ℕ) := degree_remainderOfCoefficients_lt _ + have hrhom : polynomialHom r = ofAnalyticAt (weierstrassRemainder a) + (analyticAt_weierstrassRemainder Hdiv.analyticAt_coeff) := + polynomialHom_remainderOfCoefficients a Hdiv.analyticAt_coeff + refine ⟨(ofAnalyticAt q Hdiv.analyticAt_quotient, r), ⟨hrdeg, ?_⟩, ?_⟩ + · have hgerm : ofAnalyticAt f0 hf0 = ofAnalyticAt q Hdiv.analyticAt_quotient * + ofAnalyticAt (weierstrassPolynomial a0) (analyticAt_weierstrassPolynomial ha0) + + ofAnalyticAt (weierstrassRemainder a) + (analyticAt_weierstrassRemainder Hdiv.analyticAt_coeff) := by + rw [← ofAnalyticAt_mul, ← ofAnalyticAt_add] + exact ofAnalyticAt_eq_iff.mpr Hdiv.eq + simp only + rw [hgerm, hwhom, hrhom] + · rintro ⟨q', r'⟩ ⟨hr'deg, hfeq⟩ + simp only at hr'deg hfeq ⊢ + have hr'eq : r' = remainderOfCoefficients (fun j : Fin d => r'.coeff (j : ℕ)) := + eq_remainderOfCoefficients_of_degree_lt hr'deg + choose a' ha' haeq' using fun j : Fin d => exists_rep (r'.coeff (j : ℕ)) + have hr'eq2 : r' = remainderOfCoefficients (fun j : Fin d => ofAnalyticAt (a' j) (ha' j)) := by + rw [hr'eq]; congr 1; funext j; exact (haeq' j).symm + have hr'hom : polynomialHom r' = ofAnalyticAt (weierstrassRemainder a') + (analyticAt_weierstrassRemainder ha') := by + rw [hr'eq2]; exact polynomialHom_remainderOfCoefficients a' ha' + obtain ⟨q0', hq0', hq0'eq⟩ := exists_rep q' + have Hdiv' : IsWeierstrassDivisionAt (weierstrassPolynomial a0) f0 q0' a' := by + refine ⟨hq0', ha', ?_⟩ + have hgerm : ofAnalyticAt f0 hf0 = ofAnalyticAt q0' hq0' * + ofAnalyticAt (weierstrassPolynomial a0) (analyticAt_weierstrassPolynomial ha0) + + ofAnalyticAt (weierstrassRemainder a') (analyticAt_weierstrassRemainder ha') := by + rw [hq0'eq, ← hwhom, ← hr'hom]; exact hfeq + exact (ofAnalyticAt_eq_iff (hg := (hq0'.mul (analyticAt_weierstrassPolynomial ha0)).add + (analyticAt_weierstrassRemainder ha'))).mp hgerm + obtain ⟨hqeqq0', haeqa'⟩ := huniqdiv q0' a' Hdiv' + have hqeq : ofAnalyticAt q Hdiv.analyticAt_quotient = q' := by + rw [(ofAnalyticAt_eq_iff (hg := hq0')).mpr hqeqq0', hq0'eq] + have hreq : r = r' := by + rw [hr_def, hr'eq2] + congr 1 + funext j + exact ofAnalyticAt_eq_iff.mpr (haeqa' j) + rw [Prod.mk.injEq] + exact ⟨hqeq.symm, hreq.symm⟩ + +/-- Preparation has a unique unit and distinguished polynomial of the prescribed order. Order zero +gives polynomial one. The proof converts the analytic preparation and uniqueness theorems into +polynomial and unit equalities in the germ ring. -/ +theorem existsUnique_preparation [FiniteDimensional ℂ E] + (f : AnalyticGerm ℂ (0 : E × ℂ)) {d : ℕ} (hd : orderInLastVariable f = d) : + ∃! up : (AnalyticGerm ℂ (0 : E × ℂ))ˣ × Polynomial (AnalyticGerm ℂ (0 : E)), + up.2.IsDistinguishedAt (IsLocalRing.maximalIdeal _) ∧ up.2.natDegree = d ∧ + f = ↑up.1 * polynomialHom up.2 := by + obtain ⟨f0, hf0, rfl⟩ := exists_rep f + rw [orderInLastVariable_ofAnalyticAt] at hd + obtain ⟨u, a, H, huniq⟩ := exists_isWeierstrassPreparationAt_of_finiteDimensional hf0 hd + obtain ⟨hunit, hfact⟩ := H.germ_factorization hf0 + set w : Polynomial (AnalyticGerm ℂ (0 : E)) := + ofCoefficients (fun j => ofAnalyticAt (a j) (H.analyticAt_coeff j)) with hw_def + have hwdist : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _) := + isDistinguishedAt_ofCoefficients _ (fun j => by + rw [eval_ofAnalyticAt]; exact H.coeff_zero j) + have hwdeg : w.natDegree = d := natDegree_ofCoefficients _ + have hwhom : polynomialHom w = ofAnalyticAt (weierstrassPolynomial a) + (analyticAt_weierstrassPolynomial H.analyticAt_coeff) := + polynomialHom_ofCoefficients a H.analyticAt_coeff + refine ⟨(hunit.unit, w), ⟨hwdist, hwdeg, ?_⟩, ?_⟩ + · rw [hunit.unit_spec, hwhom]; exact hfact + · rintro ⟨u', w'⟩ ⟨hw'dist, hw'deg, hfeq⟩ + simp only at hw'dist hw'deg hfeq ⊢ + obtain ⟨hw'mon, hw'coeff0⟩ := (isDistinguishedAt_iff w').mp hw'dist + have hw'eq : w' = ofCoefficients (fun j : Fin d => w'.coeff (j : ℕ)) := + eq_ofCoefficients_of_monic hw'mon hw'deg + choose a' ha' haeq using fun j : Fin d => exists_rep (w'.coeff (j : ℕ)) + obtain ⟨v0, hv0, hveq⟩ := exists_rep (↑u' : AnalyticGerm ℂ (0 : E × ℂ)) + have hv0ne : v0 0 ≠ 0 := by + have hu' := (isUnit_iff (↑u' : AnalyticGerm ℂ (0 : E × ℂ))).mp u'.isUnit + rwa [← hveq, eval_ofAnalyticAt] at hu' + have ha'0 : ∀ j : Fin d, a' j 0 = 0 := by + intro j + have hlt : (j : ℕ) < w'.natDegree := by rw [hw'deg]; exact j.isLt + have h0 := hw'coeff0 (j : ℕ) hlt + rw [← haeq j, eval_ofAnalyticAt] at h0 + exact h0 + have hw'eq2 : w' = ofCoefficients (fun j : Fin d => ofAnalyticAt (a' j) (ha' j)) := by + rw [hw'eq]; congr 1; funext j; exact (haeq j).symm + have Hprep' : IsWeierstrassPreparationAt f0 v0 a' := by + refine ⟨hv0, hv0ne, ha', ha'0, ?_⟩ + have hgerm : ofAnalyticAt f0 hf0 = ofAnalyticAt (v0 * weierstrassPolynomial a') + (hv0.mul (analyticAt_weierstrassPolynomial ha')) := by + rw [hfeq, ← hveq, hw'eq2, polynomialHom_ofCoefficients, ← ofAnalyticAt_mul] + exact ofAnalyticAt_eq_iff.mp hgerm + obtain ⟨hueqv0, haeqa'⟩ := huniq v0 a' Hprep' + have hueq : hunit.unit = u' := Units.ext (by + rw [hunit.unit_spec, (ofAnalyticAt_eq_iff (hg := hv0)).mpr hueqv0, hveq]) + have hweq : w = w' := by + rw [hw_def, hw'eq2] + congr 1 + funext j + exact ofAnalyticAt_eq_iff.mpr (haeqa' j) + rw [Prod.mk.injEq] + exact ⟨hueq.symm, hweq.symm⟩ + +/-- Division by a distinguished polynomial preserves polynomial germs (Lemma 1.8.1(a)). The +Euclidean remainder of ordinary polynomial division by the monic divisor gives a second +decomposition; germ division uniqueness identifies it with the hypothesised one. -/ +theorem exists_polynomial_quotient [FiniteDimensional ℂ E] + (p w : Polynomial (AnalyticGerm ℂ (0 : E))) + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (g : AnalyticGerm ℂ (0 : E × ℂ)) (h : polynomialHom p = g * polynomialHom w) : + ∃ q : Polynomial (AnalyticGerm ℂ (0 : E)), polynomialHom q = g := by + have hwne : w ≠ 0 := hw.monic.ne_zero + have hrdeg : (p %ₘ w).degree < (w.natDegree : WithBot ℕ) := by + rw [← Polynomial.degree_eq_natDegree hwne] + exact Polynomial.degree_modByMonic_lt p hw.monic + have hpeq : polynomialHom p = polynomialHom (p /ₘ w) * polynomialHom w + + polynomialHom (p %ₘ w) := by + conv_lhs => rw [← Polynomial.modByMonic_add_div p w] + rw [map_add, map_mul] + ring + have hveq : polynomialHom p = g * polynomialHom w + + polynomialHom (0 : Polynomial (AnalyticGerm ℂ (0 : E))) := by simp [h] + have hzerodeg : (0 : Polynomial (AnalyticGerm ℂ (0 : E))).degree < (w.natDegree : WithBot ℕ) := by + rw [Polynomial.degree_zero]; exact WithBot.bot_lt_coe w.natDegree + have hp1 : (p %ₘ w).degree < (w.natDegree : WithBot ℕ) ∧ + polynomialHom p = polynomialHom (p /ₘ w) * polynomialHom w + polynomialHom (p %ₘ w) := + ⟨hrdeg, hpeq⟩ + have hp2 : (0 : Polynomial (AnalyticGerm ℂ (0 : E))).degree < (w.natDegree : WithBot ℕ) ∧ + polynomialHom p = g * polynomialHom w + + polynomialHom (0 : Polynomial (AnalyticGerm ℂ (0 : E))) := + ⟨hzerodeg, hveq⟩ + obtain ⟨y, _, huniq⟩ := existsUnique_division w hw (polynomialHom p) + have h1 := huniq (polynomialHom (p /ₘ w), p %ₘ w) hp1 + have h2 := huniq (g, 0) hp2 + exact ⟨p /ₘ w, (Prod.mk.injEq ..).mp (h1.trans h2.symm) |>.1⟩ + +/-- If the numerator in a distinguished division is polynomial, so is the quotient. This applies +with a nonzero remainder as well as to exact divisibility. -/ +theorem exists_polynomial_division_quotient [FiniteDimensional ℂ E] + (p w r : Polynomial (AnalyticGerm ℂ (0 : E))) + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) + (q : AnalyticGerm ℂ (0 : E × ℂ)) + (h : polynomialHom p = q * polynomialHom w + polynomialHom r) : + ∃ s : Polynomial (AnalyticGerm ℂ (0 : E)), polynomialHom s = q := by + apply exists_polynomial_quotient (p - r) w hw q + rw [map_sub, h, add_sub_cancel_right] + +/-- A distinguished polynomial of positive degree that is irreducible has irreducible image. Any +factorization of the image has orders adding to the degree; a factor of positive order would +prepare to a nonunit distinguished polynomial, and comparing the resulting polynomial +factorization of `w` with irreducibility of `w` forces the other factor to be a unit, +contradicting positivity of both orders. -/ +theorem irreducible_polynomialHom_of_isDistinguishedAt [FiniteDimensional ℂ E] + {w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) (hd : w.natDegree ≠ 0) + (hirr : Irreducible w) : Irreducible (polynomialHom w) := by + have hworder : orderInLastVariable (polynomialHom w) = (w.natDegree : ℕ∞) := + orderInLastVariable_polynomialHom_of_isDistinguishedAt hw + constructor + · rw [isUnit_iff_orderInLastVariable_eq_zero, hworder] + exact_mod_cast hd + · intro A B hAB + have horder : orderInLastVariable A + orderInLastVariable B = (w.natDegree : ℕ∞) := by + rw [← orderInLastVariable_mul, ← hAB, hworder] + rcases eq_or_ne (orderInLastVariable A) 0 with hA0 | hA0 + · exact Or.inl ((isUnit_iff_orderInLastVariable_eq_zero A).mpr hA0) + rcases eq_or_ne (orderInLastVariable B) 0 with hB0 | hB0 + · exact Or.inr ((isUnit_iff_orderInLastVariable_eq_zero B).mpr hB0) + exfalso + have hAfin : orderInLastVariable A ≠ ⊤ := by + intro h; rw [h] at horder; simp at horder + have hBfin : orderInLastVariable B ≠ ⊤ := by + intro h; rw [h] at horder; simp at horder + lift orderInLastVariable A to ℕ using hAfin with dA hdA + lift orderInLastVariable B to ℕ using hBfin with dB hdB + have hdA0 : dA ≠ 0 := by exact_mod_cast hA0 + have hdB0 : dB ≠ 0 := by exact_mod_cast hB0 + obtain ⟨⟨uA, wA⟩, ⟨hwAdist, hwAdeg, hAeq⟩, -⟩ := existsUnique_preparation A hdA.symm + obtain ⟨⟨uB, wB⟩, ⟨hwBdist, hwBdeg, hBeq⟩, -⟩ := existsUnique_preparation B hdB.symm + simp only at hwAdist hwAdeg hAeq hwBdist hwBdeg hBeq + have heq2 : polynomialHom w = ((uA : AnalyticGerm ℂ (0 : E × ℂ)) * uB) * + polynomialHom (wA * wB) := by + rw [hAB, hAeq, hBeq, map_mul]; ring + obtain ⟨q, hq⟩ := exists_polynomial_quotient w (wA * wB) (isDistinguishedAt_mul hwAdist hwBdist) + ((uA : AnalyticGerm ℂ (0 : E × ℂ)) * uB) heq2 + have heq3 : w = (q * wA) * wB := by + apply polynomialHom_injective + rw [heq2, ← hq] + simp only [map_mul] + ring + have hwAnu : ¬ IsUnit wA := fun h => + hdA0 (by rw [← hwAdeg]; exact Polynomial.natDegree_eq_zero_of_isUnit h) + have hwBnu : ¬ IsUnit wB := fun h => + hdB0 (by rw [← hwBdeg]; exact Polynomial.natDegree_eq_zero_of_isUnit h) + rcases hirr.isUnit_or_isUnit heq3 with hqwA | hwBu + · exact hwAnu (isUnit_of_mul_isUnit_right hqwA) + · exact hwBnu hwBu + +/-- A distinguished polynomial is irreducible exactly when its analytic germ is. Degree zero is +allowed: `w = 1` and both sides are then false. Positive degree splits into the forward +direction above and, for the converse, comparing a germ factorization against a distinguished +normalization (Lemma 1.8.2) of any polynomial factorization. -/ +theorem irreducible_polynomialHom_iff [FiniteDimensional ℂ E] + (w : Polynomial (AnalyticGerm ℂ (0 : E))) + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) : + Irreducible (polynomialHom w) ↔ Irreducible w := by + rcases eq_or_ne w.natDegree 0 with hd0 | hd0 + · have hw1 : w = 1 := Polynomial.eq_one_of_monic_natDegree_zero hw.monic hd0 + subst hw1 + simp only [map_one] + exact ⟨fun h => absurd isUnit_one h.not_isUnit, fun h => absurd isUnit_one h.not_isUnit⟩ + · refine ⟨fun hirrHom => ⟨fun hu => hirrHom.not_isUnit (hu.map (polynomialHom (E := E))), + fun p q hpq => ?_⟩, fun hirr => irreducible_polynomialHom_of_isDistinguishedAt hw hd0 hirr⟩ + obtain ⟨u, hup, huq⟩ := exists_distinguished_factors p q (hpq ▸ hw) + have hp'q' : Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p * + (Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * q) = w := by + rw [hpq] + calc + _ = Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * + Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * (p * q) := by ring + _ = _ := by rw [← Polynomial.C_mul]; simp + have hhom : polynomialHom w = polynomialHom (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p) * + polynomialHom (Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * q) := by + rw [← map_mul, hp'q'] + rcases hirrHom.isUnit_or_isUnit hhom with h1 | h2 + · left + have hord : orderInLastVariable + (polynomialHom (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p)) = 0 := + (isUnit_iff_orderInLastVariable_eq_zero _).mp h1 + rw [orderInLastVariable_polynomialHom_of_isDistinguishedAt hup] at hord + have hdeg0 : (Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p).natDegree = 0 := by + exact_mod_cast hord + have h1' : Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * p = 1 := + Polynomial.eq_one_of_monic_natDegree_zero hup.monic hdeg0 + have hp1 : p = Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) := by + have hc := congrArg (fun r => Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * r) h1' + simpa [← mul_assoc, ← Polynomial.C_mul] using hc + rw [hp1] + exact Polynomial.isUnit_C.mpr u⁻¹.isUnit + · right + have hord : orderInLastVariable + (polynomialHom (Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * q)) = 0 := + (isUnit_iff_orderInLastVariable_eq_zero _).mp h2 + rw [orderInLastVariable_polynomialHom_of_isDistinguishedAt huq] at hord + have hdeg0 : (Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * q).natDegree = 0 := by + exact_mod_cast hord + have h2' : Polynomial.C (↑u⁻¹ : AnalyticGerm ℂ (0 : E)) * q = 1 := + Polynomial.eq_one_of_monic_natDegree_zero huq.monic hdeg0 + have hq1 : q = Polynomial.C (u : AnalyticGerm ℂ (0 : E)) := by + have hc := congrArg (fun r => Polynomial.C (u : AnalyticGerm ℂ (0 : E)) * r) h2' + simpa [← mul_assoc, ← Polynomial.C_mul] using hc + rw [hq1] + exact Polynomial.isUnit_C.mpr u.isUnit + +/-- A common factor of two germs that is the image of a prime distinguished polynomial divides one +of them: Weierstrass-divide each factor, reduce the product of the two polynomial remainders by +ordinary division against the distinguishing polynomial, and match the resulting decomposition +of the germ product against germ division uniqueness to reduce to primality of the +distinguishing polynomial itself. -/ +theorem dvd_or_dvd_of_isDistinguishedAt [FiniteDimensional ℂ E] + {w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) (hwp : Prime w) + {f g : AnalyticGerm ℂ (0 : E × ℂ)} (hfg : polynomialHom w ∣ f * g) : + polynomialHom w ∣ f ∨ polynomialHom w ∣ g := by + obtain ⟨⟨qf, rf⟩, ⟨hrfdeg, hfeq⟩, -⟩ := existsUnique_division w hw f + obtain ⟨⟨qg, rg⟩, ⟨hrgdeg, hgeq⟩, -⟩ := existsUnique_division w hw g + simp only at hrfdeg hfeq hrgdeg hgeq + have hr0eq : rf * rg = (rf * rg) %ₘ w + w * ((rf * rg) /ₘ w) := + (Polynomial.modByMonic_add_div (rf * rg) w).symm + have hr0deg : ((rf * rg) %ₘ w).degree < (w.natDegree : WithBot ℕ) := by + rw [← Polynomial.degree_eq_natDegree hw.monic.ne_zero] + exact Polynomial.degree_modByMonic_lt (rf * rg) hw.monic + set bigC : AnalyticGerm ℂ (0 : E × ℂ) := + qf * qg * polynomialHom w + qf * polynomialHom rg + qg * polynomialHom rf + + polynomialHom ((rf * rg) /ₘ w) with hbigC_def + have hfg2 : f * g = bigC * polynomialHom w + polynomialHom ((rf * rg) %ₘ w) := by + have hmul : polynomialHom rf * polynomialHom rg = polynomialHom (rf * rg) := + (map_mul polynomialHom rf rg).symm + have hM : polynomialHom (rf * rg) = polynomialHom ((rf * rg) %ₘ w) + + polynomialHom w * polynomialHom ((rf * rg) /ₘ w) := by + conv_lhs => rw [hr0eq] + rw [map_add, map_mul] + rw [hbigC_def, hfeq, hgeq] + rw [show (qf * polynomialHom w + polynomialHom rf) * (qg * polynomialHom w + + polynomialHom rg) = qf * qg * polynomialHom w * polynomialHom w + + qf * polynomialHom w * polynomialHom rg + polynomialHom rf * qg * polynomialHom w + + polynomialHom rf * polynomialHom rg from by ring] + rw [hmul, hM]; ring + obtain ⟨c, hc⟩ := hfg + obtain ⟨⟨qfg, rfg⟩, ⟨hrfgdeg, hfgeq⟩, huniqfg⟩ := existsUnique_division w hw (f * g) + simp only at hrfgdeg hfgeq huniqfg + have hzerodeg : (0 : Polynomial (AnalyticGerm ℂ (0 : E))).degree < (w.natDegree : WithBot ℕ) := by + rw [Polynomial.degree_zero]; exact WithBot.bot_lt_coe w.natDegree + have hceq : f * g = c * polynomialHom w + polynomialHom (0 : Polynomial (AnalyticGerm ℂ (0 : E))) + := by + rw [hc, map_zero, add_zero]; ring + have heq1 := huniqfg (bigC, (rf * rg) %ₘ w) ⟨hr0deg, hfg2⟩ + have heq2 := huniqfg (c, 0) ⟨hzerodeg, hceq⟩ + have hr0 : (rf * rg) %ₘ w = 0 := ((Prod.mk.injEq ..).mp (heq1.trans heq2.symm)).2 + have hwdvd : w ∣ rf * rg := ⟨(rf * rg) /ₘ w, hr0eq.trans (by rw [hr0, zero_add])⟩ + rcases hwp.2.2 rf rg hwdvd with hwrf | hwrg + · obtain ⟨c0, hc0⟩ := hwrf + refine Or.inl ⟨qf + polynomialHom c0, ?_⟩ + rw [hfeq, hc0, map_mul]; ring + · obtain ⟨c0, hc0⟩ := hwrg + refine Or.inr ⟨qg + polynomialHom c0, ?_⟩ + rw [hgeq, hc0, map_mul]; ring + +/-- The image of a prime distinguished polynomial is itself prime. Non-vanishing and +non-invertibility come from irreducibility of the image; the dividing property comes from +`dvd_or_dvd_of_isDistinguishedAt`. -/ +theorem prime_polynomialHom_of_isDistinguishedAt [FiniteDimensional ℂ E] + {w : Polynomial (AnalyticGerm ℂ (0 : E))} + (hw : w.IsDistinguishedAt (IsLocalRing.maximalIdeal _)) (hwp : Prime w) : + Prime (polynomialHom w) := by + have hd0 : w.natDegree ≠ 0 := fun h0 => + hwp.not_isUnit (Polynomial.eq_one_of_monic_natDegree_zero hw.monic h0 ▸ isUnit_one) + have hpolyirr : Irreducible (polynomialHom w) := + irreducible_polynomialHom_of_isDistinguishedAt hw hd0 hwp.irreducible + exact ⟨hpolyirr.ne_zero, hpolyirr.not_isUnit, fun f g => dvd_or_dvd_of_isDistinguishedAt hw hwp⟩ + +end AnalyticGerm + +/-- One coordinate system permits preparation of all members of a finite family. This depends on the +preparation theorem and hence on analytic division. Empty parameter types, empty families, and +unit germs are all included. -/ +theorem exists_equiv_forall_isWeierstrassPreparationAt {ι κ : Type*} [Fintype ι] [Fintype κ] + {f : κ → (ι → ℂ) × ℂ → ℂ} (hf : ∀ i, AnalyticAt ℂ (f i) 0) + (hne : ∀ i, ¬ f i =ᶠ[𝓝 0] 0) : + ∃ (L : ((ι → ℂ) × ℂ) ≃L[ℂ] ((ι → ℂ) × ℂ)) (d : κ → ℕ), ∀ i, + ∃ (u : (ι → ℂ) × ℂ → ℂ) (a : Fin (d i) → (ι → ℂ) → ℂ), + IsWeierstrassPreparationAt (fun z => f i (L z)) u a := by + obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change_finite hf hne + refine ⟨L, d, fun i => ?_⟩ + have ha : AnalyticAt ℂ (fun z => f i (L z)) 0 := + (hf i).comp_of_eq (L.toContinuousLinearMap.analyticAt 0) L.map_zero + obtain ⟨u, a, h, _⟩ := exists_isWeierstrassPreparationAt ha (hd i) + exact ⟨u, a, h⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean new file mode 100644 index 0000000000..b10f717d11 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean @@ -0,0 +1,16 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Basic.lean new file mode 100644 index 0000000000..7e116bfcae --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Basic.lean @@ -0,0 +1,249 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Constructions +public import Mathlib.Analysis.Complex.Basic + +/-! +# Analytic subsets of open complex domains + +An analytic subset is locally the common zero set of finitely many scalar analytic functions. +Equations are required near every point of the ambient set, so relative closedness follows. The +local neighborhood requirement also implies that the ambient domain is open. No connectedness, +nonemptiness, or positive dimension is built in. Empty families define the whole domain. + +Holomorphic defining equations and biholomorphic transport are treated separately in +`SeveralComplexVariables.AnalyticSet.Holomorphic`. This file uses analytic predicates directly +and does not depend on the SCV holomorphy–analyticity equivalence. + +References: [Range][Range1986] I §3.2; [Fritzsche–Grauert][FritzscheGrauert2002] I §8; +[Scheidemann][Scheidemann2005] §4.1. No abstract analytic spaces or sheaf structures are +introduced. + +## Main definitions + +* `IsAnalyticSet`: `A` is an analytic subset of `U` if it is contained in `U` and is locally cut out + by finitely many scalar analytic equations. + +## Main results + +* `isAnalyticSet_zeroSet`: A scalar analytic zero set, restricted to its domain, is analytic. +* `IsAnalyticSet.isOpen_sdiff`: Analytic subsets are relatively closed, expressed by their open + complement in `U`. +* `IsAnalyticSet.inter`: Finite intersections of analytic subsets are analytic. +* `IsAnalyticSet.union`: Finite unions are defined by pairwise products of the local equations. +* `IsAnalyticSet.preimage`: Holomorphic preimages preserve analytic subsets. +* `IsAnalyticSet.prod`: Products of analytic subsets are analytic. +* `isAnalyticSet_of_local`: Analyticity of a subset can be checked on an open cover of its ambient + domain. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- `A` is an analytic subset of `U` if it is contained in `U` and is locally cut out by finitely +many scalar analytic equations. The equations need not extend throughout `U`. -/ +@[expose] def IsAnalyticSet (U A : Set E) : Prop := + A ⊆ U ∧ ∀ a ∈ U, ∃ V : Set E, IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + ∃ s : Finset (E → ℂ), (∀ f ∈ s, AnalyticOnNhd ℂ f V) ∧ + ∀ z ∈ V, z ∈ A ↔ ∀ f ∈ s, f z = 0 + +/-- An analytic subset is contained in its ambient domain. -/ +theorem IsAnalyticSet.subset {U A : Set E} (h : IsAnalyticSet U A) : A ⊆ U := h.1 + +/-- The local open neighborhoods in the definition cover the ambient domain. -/ +theorem IsAnalyticSet.isOpen_domain {U A : Set E} (h : IsAnalyticSet U A) : IsOpen U := by + rw [isOpen_iff_mem_nhds] + intro a ha + obtain ⟨V, hV, haV, hVU, _⟩ := h.2 a ha + exact mem_of_superset (hV.mem_nhds haV) hVU + +/-- A finite family of analytic equations defines an analytic subset. -/ +theorem isAnalyticSet_commonZeroSet {U : Set E} (hU : IsOpen U) + (s : Finset (E → ℂ)) (hs : ∀ f ∈ s, AnalyticOnNhd ℂ f U) : + IsAnalyticSet U {z | z ∈ U ∧ ∀ f ∈ s, f z = 0} := by + refine ⟨fun _ hz => hz.1, fun a ha => ⟨U, hU, ha, Subset.rfl, s, hs, ?_⟩⟩ + intro z hz + exact and_iff_right hz + +/-- A scalar analytic zero set, restricted to its domain, is analytic. -/ +theorem isAnalyticSet_zeroSet {U : Set E} (hU : IsOpen U) {f : E → ℂ} + (hf : AnalyticOnNhd ℂ f U) : IsAnalyticSet U (U ∩ f ⁻¹' {0}) := by + classical + change IsAnalyticSet U {z | z ∈ U ∧ f z = 0} + simpa using isAnalyticSet_commonZeroSet hU {f} (by simpa using hf) + +/-- The zero set of a finite-coordinate analytic map is analytic, including an empty coordinate +index type, when the zero set is the whole domain. -/ +theorem isAnalyticSet_zeroSet_pi {ι : Type*} [Fintype ι] {U : Set E} (hU : IsOpen U) + {f : E → (ι → ℂ)} (hf : AnalyticOnNhd ℂ f U) : + IsAnalyticSet U (U ∩ f ⁻¹' {0}) := by + classical + let s : Finset (E → ℂ) := Finset.univ.image (fun i z => f z i) + have hs : ∀ g ∈ s, AnalyticOnNhd ℂ g U := by + intro g hg + obtain ⟨i, _, rfl⟩ := Finset.mem_image.mp hg + exact analyticOnNhd_pi_iff.mp hf i + have h := isAnalyticSet_commonZeroSet hU s hs + convert h using 1 + ext z + constructor + · rintro ⟨hzU, hfz⟩ + refine ⟨hzU, ?_⟩ + intro g hg + obtain ⟨i, _, rfl⟩ := Finset.mem_image.mp hg + exact congrFun hfz i + · rintro ⟨hzU, hsz⟩ + refine ⟨hzU, ?_⟩ + funext i + exact hsz (fun z => f z i) (Finset.mem_image.mpr ⟨i, Finset.mem_univ i, rfl⟩) + +/-- The whole open domain is analytic, using no equations. -/ +theorem isAnalyticSet_self {U : Set E} (hU : IsOpen U) : IsAnalyticSet U U := by + simpa using isAnalyticSet_commonZeroSet hU ∅ (by simp) + +/-- The empty set is analytic, using the constant equation `1 = 0`. -/ +theorem isAnalyticSet_empty {U : Set E} (hU : IsOpen U) : IsAnalyticSet U ∅ := by + simpa using isAnalyticSet_zeroSet hU (f := fun _ => 1) analyticOnNhd_const + +/-- Analytic subsets restrict to smaller open domains. -/ +theorem IsAnalyticSet.restrict {U A W : Set E} (h : IsAnalyticSet U A) + (hW : IsOpen W) (hWU : W ⊆ U) : IsAnalyticSet W (W ∩ A) := by + refine ⟨inter_subset_left, ?_⟩ + intro a ha + obtain ⟨V, hV, haV, hVU, s, hs, he⟩ := h.2 a (hWU ha) + refine ⟨W ∩ V, hW.inter hV, ⟨ha, haV⟩, inter_subset_left, s, + fun f hf => (hs f hf).mono inter_subset_right, ?_⟩ + intro z hz + exact (and_iff_right hz.1).trans (he z hz.2) + +/-- Analyticity of a subset can be checked on an open cover of its ambient domain. -/ +theorem isAnalyticSet_of_local {U A : Set E} (hAU : A ⊆ U) + (h : ∀ a ∈ U, ∃ V, IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ IsAnalyticSet V (V ∩ A)) : + IsAnalyticSet U A := by + refine ⟨hAU, ?_⟩ + intro a ha + obtain ⟨V, _, haV, hVU, hAV⟩ := h a ha + obtain ⟨W, hW, haW, hWV, s, hs, he⟩ := hAV.2 a haV + refine ⟨W, hW, haW, hWV.trans hVU, s, hs, ?_⟩ + intro z hz + exact (and_iff_right (hWV hz)).symm.trans (he z hz) + +/-- Analytic subsets are relatively closed, expressed by their open complement in `U`. -/ +theorem IsAnalyticSet.isOpen_sdiff {U A : Set E} (h : IsAnalyticSet U A) : + IsOpen (U \ A) := by + classical + rw [isOpen_iff_mem_nhds] + rintro a ⟨haU, haA⟩ + obtain ⟨V, hV, haV, hVU, s, hs, he⟩ := h.2 a haU + have hn : ¬ ∀ f ∈ s, f a = 0 := fun hall => haA ((he a haV).mpr hall) + push Not at hn + obtain ⟨f, hfs, hfa⟩ := hn + filter_upwards [hV.mem_nhds haV, (hs f hfs a haV).continuousAt.eventually_ne hfa] with z hz hnz + exact ⟨hVU hz, fun hzA => hnz ((he z hz).mp hzA f hfs)⟩ + +/-- Finite intersections of analytic subsets are analytic. -/ +theorem IsAnalyticSet.inter {U A B : Set E} (hA : IsAnalyticSet U A) + (hB : IsAnalyticSet U B) : IsAnalyticSet U (A ∩ B) := by + classical + refine ⟨inter_subset_left.trans hA.subset, ?_⟩ + intro a ha + obtain ⟨V, hV, haV, hVU, s, hs, he⟩ := hA.2 a ha + obtain ⟨W, hW, haW, _, t, ht, hk⟩ := hB.2 a ha + refine ⟨V ∩ W, hV.inter hW, ⟨haV, haW⟩, inter_subset_left.trans hVU, + s ∪ t, ?_, ?_⟩ + · intro f hf + rcases Finset.mem_union.mp hf with hf | hf + · exact (hs f hf).mono inter_subset_left + · exact (ht f hf).mono inter_subset_right + · intro z hz + simp only [mem_inter_iff, he z hz.1, hk z hz.2, Finset.mem_union] + exact ⟨fun h f hf => hf.elim (h.1 f) (h.2 f), + fun h => ⟨fun f hf => h f (Or.inl hf), fun f hf => h f (Or.inr hf)⟩⟩ + +/-- Finite unions are defined by pairwise products of the local equations. -/ +theorem IsAnalyticSet.union {U A B : Set E} (hA : IsAnalyticSet U A) + (hB : IsAnalyticSet U B) : IsAnalyticSet U (A ∪ B) := by + classical + refine ⟨union_subset hA.subset hB.subset, ?_⟩ + intro a ha + obtain ⟨V, hV, haV, hVU, s, hs, he⟩ := hA.2 a ha + obtain ⟨W, hW, haW, _, t, ht, hk⟩ := hB.2 a ha + refine ⟨V ∩ W, hV.inter hW, ⟨haV, haW⟩, inter_subset_left.trans hVU, + (s ×ˢ t).image (fun p => p.1 * p.2), ?_, ?_⟩ + · intro f hf + obtain ⟨⟨g, k⟩, hp, rfl⟩ := Finset.mem_image.mp hf + exact ((hs g (Finset.mem_product.mp hp).1).mono inter_subset_left).mul + ((ht k (Finset.mem_product.mp hp).2).mono inter_subset_right) + · intro z hz + constructor + · intro hzAB f hf + obtain ⟨⟨g, k⟩, hp, rfl⟩ := Finset.mem_image.mp hf + rcases hzAB with hzA | hzB + · exact mul_eq_zero.mpr (Or.inl ((he z hz.1).mp hzA g (Finset.mem_product.mp hp).1)) + · exact mul_eq_zero.mpr (Or.inr ((hk z hz.2).mp hzB k (Finset.mem_product.mp hp).2)) + · intro h + by_cases hzA : z ∈ A + · exact Or.inl hzA + · right + apply (hk z hz.2).mpr + have hn : ¬ ∀ g ∈ s, g z = 0 := fun hall => hzA ((he z hz.1).mpr hall) + push Not at hn + obtain ⟨g, hg, hgz⟩ := hn + intro k hkt + exact (mul_eq_zero.mp (h (g * k) + (Finset.mem_image.mpr ⟨(g, k), Finset.mem_product.mpr ⟨hg, hkt⟩, rfl⟩))).resolve_left hgz + +/-- Holomorphic preimages preserve analytic subsets. -/ +theorem IsAnalyticSet.preimage {U : Set E} {V B : Set F} (hB : IsAnalyticSet V B) + (hU : IsOpen U) {f : E → F} (hf : AnalyticOnNhd ℂ f U) (hm : MapsTo f U V) : + IsAnalyticSet U (U ∩ f ⁻¹' B) := by + classical + refine ⟨inter_subset_left, ?_⟩ + intro a ha + obtain ⟨W, hW, hfaW, hWV, s, hs, he⟩ := hB.2 (f a) (hm ha) + refine ⟨U ∩ f ⁻¹' W, hf.continuousOn.isOpen_inter_preimage hU hW, + ⟨ha, hfaW⟩, inter_subset_left, s.image (fun g => g ∘ f), ?_, ?_⟩ + · intro g hg + obtain ⟨k, hk, rfl⟩ := Finset.mem_image.mp hg + exact (hs k hk).comp (hf.mono inter_subset_left) (fun _ hz => hz.2) + · intro z hz + simpa [hz.1] using he (f z) hz.2 + +/-- Products of analytic subsets are analytic. -/ +theorem IsAnalyticSet.prod {U A : Set E} {V B : Set F} (hA : IsAnalyticSet U A) + (hB : IsAnalyticSet V B) : IsAnalyticSet (U ×ˢ V) (A ×ˢ B) := by + have ho := hA.isOpen_domain.prod hB.isOpen_domain + have h₁ := hA.preimage ho (f := Prod.fst) (fun _ _ => analyticAt_fst) (fun _ hz => hz.1) + have h₂ := hB.preimage ho (f := Prod.snd) (fun _ _ => analyticAt_snd) (fun _ hz => hz.2) + convert h₁.inter h₂ using 1 + ext z + constructor + · rintro ⟨hzA, hzB⟩ + exact ⟨⟨⟨hA.subset hzA, hB.subset hzB⟩, hzA⟩, + ⟨⟨hA.subset hzA, hB.subset hzB⟩, hzB⟩⟩ + · rintro ⟨⟨_, hzA⟩, ⟨_, hzB⟩⟩ + exact ⟨hzA, hzB⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Codimension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Codimension.lean new file mode 100644 index 0000000000..0e8d02af75 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Codimension.lean @@ -0,0 +1,175 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs + +/-! +# Complex slices and removal in codimension at least two + +Following [Scheidemann][Scheidemann2005] §4.1, codimension at least `q` is expressed by an +injective complex linear `q`-plane on which each point of the subset is an isolated +intersection. We retain the pointwise slice witness instead of introducing a general dimension +theory. The empty set satisfies every bound; at a point the bound cannot exceed ambient +dimension. + +Hartogs figures around isolated two-dimensional slices give local holomorphic extensions, and +hence automatic local boundedness across the analytic set. The first Riemann extension theorem +then gives the global second Riemann extension theorem. Reference: +[Scheidemann][Scheidemann2005] 4.1.4 and 4.2.3. + +## Main definitions + +* `HasIsolatedComplexSlice`: An affine complex `q`-plane through `a` meets `A` only at `a` near that + point. +* `HasComplexSliceCodimensionAtLeast`: The slice formulation of complex codimension at least `q`, at + every point of `A`. + +## Main results + +* `IsAnalyticSet.locally_bounded_of_codimension_two`: **Automatic local boundedness in codimension + at least two.** Hartogs continuation around isolated two-dimensional slices gives a local + holomorphic extension, whose continuity supplies the bound. +* `IsAnalyticSet.exists_extension_of_codimension_two`: **Second Riemann extension theorem.** No + boundedness or connectedness assumption is imposed. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- An affine complex `q`-plane through `a` meets `A` only at `a` near that point. Membership of `a` +in `A` is separate, so this predicate also applies outside `A`. -/ +@[expose] def HasIsolatedComplexSlice (A : Set E) (a : E) (q : ℕ) : Prop := + ∃ L : (Fin q → ℂ) →L[ℂ] E, Function.Injective L ∧ + ∀ᶠ z in 𝓝 (0 : Fin q → ℂ), a + L z ∈ A → z = 0 + +/-- The slice formulation of complex codimension at least `q`, at every point of `A`. Analyticity is +a separate assumption. -/ +@[expose] def HasComplexSliceCodimensionAtLeast (A : Set E) (q : ℕ) : Prop := + ∀ a ∈ A, HasIsolatedComplexSlice A a q + +/-- The empty set satisfies every slice-codimension bound. -/ +theorem hasComplexSliceCodimensionAtLeast_empty (q : ℕ) : + HasComplexSliceCodimensionAtLeast (∅ : Set E) q := by + simp [HasComplexSliceCodimensionAtLeast] + +/-- Every subset has slice codimension at least zero; the zero-dimensional slice is a point. -/ +theorem hasComplexSliceCodimensionAtLeast_zero (A : Set E) : + HasComplexSliceCodimensionAtLeast A 0 := by + intro a _ + exact ⟨0, fun _ _ _ => Subsingleton.elim _ _, + Filter.Eventually.of_forall (fun _ _ => Subsingleton.elim _ _)⟩ + +/-- Isolated slice intersections are preserved on subsets. -/ +theorem HasIsolatedComplexSlice.mono {A B : Set E} {a : E} {q : ℕ} + (h : HasIsolatedComplexSlice A a q) (hBA : B ⊆ A) : HasIsolatedComplexSlice B a q := by + obtain ⟨L, hi, he⟩ := h + exact ⟨L, hi, he.mono (fun _ hz hb => hz (hBA hb))⟩ + +/-- Slice-codimension bounds pass to subsets, in particular to restrictions to open sets. -/ +theorem HasComplexSliceCodimensionAtLeast.mono {A B : Set E} {q : ℕ} + (h : HasComplexSliceCodimensionAtLeast A q) (hBA : B ⊆ A) : + HasComplexSliceCodimensionAtLeast B q := fun a ha => (h a (hBA ha)).mono hBA + +/-- A slice cannot have larger dimension than the ambient finite-dimensional space. -/ +theorem HasIsolatedComplexSlice.le_finrank [FiniteDimensional ℂ E] + {A : Set E} {a : E} {q : ℕ} (h : HasIsolatedComplexSlice A a q) : + q ≤ Module.finrank ℂ E := by + obtain ⟨L, hi, _⟩ := h + simpa using LinearMap.finrank_le_finrank_of_injective (f := L.toLinearMap) hi + +/-- A codimension bound exceeding ambient dimension forces the set to be empty. -/ +theorem HasComplexSliceCodimensionAtLeast.eq_empty_of_finrank_lt [FiniteDimensional ℂ E] + {A : Set E} {q : ℕ} (h : HasComplexSliceCodimensionAtLeast A q) + (hq : Module.finrank ℂ E < q) : A = ∅ := by + apply Set.eq_empty_iff_forall_notMem.mpr + intro a ha + exact (not_le_of_gt hq) (h a ha).le_finrank + +/-- A positive-dimensional isolated slice excludes an interior point. -/ +theorem HasIsolatedComplexSlice.notMem_interior {A : Set E} {a : E} {q : ℕ} + (h : HasIsolatedComplexSlice A a q) (hq : 0 < q) : a ∉ interior A := by + let : Nonempty (Fin q) := ⟨⟨0, hq⟩⟩ + obtain ⟨L, _, he⟩ := h + intro ha + have hc : ContinuousAt (fun z => a + L z) (0 : Fin q → ℂ) := + continuousAt_const.add L.continuous.continuousAt + have hn : ∀ᶠ z in 𝓝 (0 : Fin q → ℂ), a + L z ∈ A := + hc.preimage_mem_nhds (by simpa using mem_interior_iff_mem_nhds.mp ha) + have hz : ({0} : Set (Fin q → ℂ)) ∈ 𝓝 0 := by + filter_upwards [he, hn] with z hze hza + exact hze hza + have hzero : (0 : Fin q → ℂ) ∈ interior ({0} : Set (Fin q → ℂ)) := + mem_interior_iff_mem_nhds.mpr hz + simp at hzero + +/-- Positive slice codimension implies empty interior, also on disconnected domains. -/ +theorem HasComplexSliceCodimensionAtLeast.interior_eq_empty {A : Set E} {q : ℕ} + (h : HasComplexSliceCodimensionAtLeast A q) (hq : 0 < q) : interior A = ∅ := by + apply Set.eq_empty_iff_forall_notMem.mpr + intro a ha + exact (h a (interior_subset ha)).notMem_interior hq ha + +/-- **Automatic local boundedness in codimension at least two.** Hartogs continuation +around isolated two-dimensional slices gives a local holomorphic extension, whose +continuity supplies the bound. This allows arbitrary complex Banach targets. -/ +theorem IsAnalyticSet.locally_bounded_of_codimension_two [FiniteDimensional ℂ E] + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {U A : Set E} (hA : IsAnalyticSet U A) (hcodim : HasComplexSliceCodimensionAtLeast A 2) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ A)) : + ∀ a ∈ A, ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ A), ‖f z‖ ≤ C := by + intro a ha + obtain ⟨L, _, hisol⟩ := hcodim a ha + let e := (ContinuousLinearEquiv.finTwoArrow ℂ ℂ).symm + have hisol' : ∀ᶠ p in 𝓝 (0 : ℂ × ℂ), a + (L.comp e.toContinuousLinearMap) p ∈ A → p = 0 := by + have ht : Tendsto e (𝓝 (0 : ℂ × ℂ)) (𝓝 0) := by + simpa using e.continuous.tendsto (0 : ℂ × ℂ) + filter_upwards [ht.eventually hisol] with p hp hpA + apply e.injective + simpa using hp hpA + obtain ⟨r, hr, g, hg, heq⟩ := hA.exists_local_extension_of_isolated_two_slice + (hA.subset ha) (L.comp e.toContinuousLinearMap) hisol' hf + have hb : ∀ᶠ z in 𝓝 a, ‖g z‖ < ‖g a‖ + 1 := + ((hg a (mem_ball_self hr)).continuousAt.norm).eventually_lt_const (by linarith) + obtain ⟨δ, hδ, hδsub⟩ := Metric.mem_nhds_iff.mp (inter_mem (ball_mem_nhds a hr) hb) + refine ⟨δ, hδ, ‖g a‖ + 1, fun z hz => ?_⟩ + have hz' := hδsub hz.1 + rw [← heq ⟨hz'.1, hz.2.2⟩] + exact hz'.2.le + +/-- **Second Riemann extension theorem.** No boundedness or connectedness assumption +is imposed. The proof depends on automatic local boundedness in codimension two. -/ +theorem IsAnalyticSet.exists_extension_of_codimension_two [FiniteDimensional ℂ E] + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {U A : Set E} (hA : IsAnalyticSet U A) (hcodim : HasComplexSliceCodimensionAtLeast A 2) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ A)) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ A) := + hA.exists_extension_of_locally_bounded (hcodim.interior_eq_empty (by decide)) hf + (hA.locally_bounded_of_codimension_two hcodim hf) + +/-- Extensions in the second Riemann theorem are unique on the ambient domain. This uniqueness proof +uses density and does not require the existence argument. -/ +theorem IsAnalyticSet.extension_unique_of_codimension_two + {F : Type*} [TopologicalSpace F] [T2Space F] {U A : Set E} + (hA : IsAnalyticSet U A) (hcodim : HasComplexSliceCodimensionAtLeast A 2) + {f g h : E → F} (hg : ContinuousOn g U) (hh : ContinuousOn h U) + (hgf : EqOn g f (U \ A)) (hhf : EqOn h f (U \ A)) : EqOn g h U := + hA.extension_unique (hcodim.interior_eq_empty (by decide)) hg hh hgf hhf + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/CoordinatePlane.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/CoordinatePlane.lean new file mode 100644 index 0000000000..7d65a80019 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/CoordinatePlane.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation + +/-! +# Removal across a coordinate subspace of codimension two + +The model subspace has two final coordinates equal to zero and arbitrary remaining parameters. +Hartogs continuation on cylinders proves removal on any open domain, with Banach-valued targets, +independently of the general analytic-set theorem. The parameter space may have dimension zero, +recovering isolated-point removal in `ℂ²`. + +## Main definitions + +* `complexCoordinatePlane`: The coordinate subspace obtained by setting the last two complex + coordinates to zero. + +## Main results + +* `exists_extension_across_coordinatePlane`: **Coordinate-subspace removal.** The proof uses the + already proved Hartogs cylinder theorem and gluing, with no dependence on general codimension-two + removal or local algebra. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {P : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] + +/-- The coordinate subspace obtained by setting the last two complex coordinates to zero. -/ +@[expose] def complexCoordinatePlane : Set ((P × ℂ) × ℂ) := {z | z.1.2 = 0 ∧ z.2 = 0} + +/-- The model coordinate subspace is analytic on every open domain. -/ +theorem isAnalyticSet_coordinatePlane {U : Set ((P × ℂ) × ℂ)} (hU : IsOpen U) : + IsAnalyticSet U (U ∩ complexCoordinatePlane) := by + have h₁ := isAnalyticSet_zeroSet hU + (f := fun z : (P × ℂ) × ℂ => z.1.2) + (fun _ _ => analyticAt_snd.comp analyticAt_fst) + have h₂ := isAnalyticSet_zeroSet hU + (f := fun z : (P × ℂ) × ℂ => z.2) (fun _ _ => analyticAt_snd) + convert h₁.inter h₂ using 1 + ext z + simp only [mem_inter_iff, mem_preimage, mem_singleton_iff, complexCoordinatePlane, mem_ofPred_eq] + tauto + +/-- The last two coordinate directions provide the isolated two-plane slice. -/ +theorem hasComplexSliceCodimensionAtLeast_coordinatePlane : + HasComplexSliceCodimensionAtLeast (complexCoordinatePlane (P := P)) 2 := by + intro a ha + let L : (Fin 2 → ℂ) →L[ℂ] ((P × ℂ) × ℂ) := + ((0 : (Fin 2 → ℂ) →L[ℂ] P).prod (ContinuousLinearMap.proj 0)).prod + (ContinuousLinearMap.proj 1) + have hL (z : Fin 2 → ℂ) : L z = ((0, z 0), z 1) := rfl + refine ⟨L, ?_, Filter.Eventually.of_forall ?_⟩ + · intro x y he + have h₀ := congrArg (fun z : (P × ℂ) × ℂ => z.1.2) he + have h₁ := congrArg (fun z : (P × ℂ) × ℂ => z.2) he + funext i + fin_cases i + · exact h₀ + · exact h₁ + · intro z hz + have hz₀ : z 0 = 0 := by simpa [complexCoordinatePlane, hL, ha.1] using hz.1 + have hz₁ : z 1 = 0 := by simpa [complexCoordinatePlane, hL, ha.2] using hz.2 + funext i + fin_cases i + · exact hz₀ + · exact hz₁ + +/-- **Coordinate-subspace removal.** The proof uses the already proved Hartogs cylinder +theorem and gluing, with no dependence on general codimension-two removal or local algebra. -/ +theorem exists_extension_across_coordinatePlane [FiniteDimensional ℂ P] + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {U : Set ((P × ℂ) × ℂ)} (hU : IsOpen U) {f : ((P × ℂ) × ℂ) → F} + (hf : AnalyticOnNhd ℂ f (U \ complexCoordinatePlane)) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ complexCoordinatePlane) := by + let : NormedSpace ℝ P := NormedSpace.restrictScalars ℝ ℂ P + have hA := isAnalyticSet_coordinatePlane hU + have hcodim := hasComplexSliceCodimensionAtLeast_coordinatePlane (P := P) + have hi := (hcodim.mono (inter_subset_right (s := U))).interior_eq_empty (by decide) + have hdiff : U \ (U ∩ complexCoordinatePlane) = U \ complexCoordinatePlane := by + ext z + simp only [Set.mem_sdiff, mem_inter_iff] + tauto + have hdense : U ⊆ closure (U \ complexCoordinatePlane) := by + simpa only [hdiff] using hA.subset_closure_sdiff hi + have hopen : IsOpen (U \ complexCoordinatePlane) := by + simpa only [hdiff] using hA.isOpen_sdiff + apply exists_analyticOnNhd_extension_of_local sdiff_subset hdense + intro a ha + by_cases haA : a ∈ complexCoordinatePlane + · obtain ⟨r, hr, hrU⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + let D : Set (P × ℂ) := ball a.1.1 r ×ˢ ball 0 r + let D₀ : Set (P × ℂ) := ball a.1.1 r ×ˢ (ball 0 r \ {0}) + let V : Set ((P × ℂ) × ℂ) := D ×ˢ ball 0 r + have haeq : a = ((a.1.1, 0), 0) := by + ext <;> simp_all [complexCoordinatePlane] + have hVU : V ⊆ U := by + apply Subset.trans _ hrU + rw [haeq] + simp only [← ball_prod_same, V, D] + exact Subset.rfl + have hne : D₀.Nonempty := by + have hz : (0 : ℂ) ∈ closure ({0}ᶜ : Set ℂ) := by simp + obtain ⟨z, hzne, hzr⟩ := Metric.mem_closure_iff.mp hz r hr + exact ⟨(a.1.1, z), mem_ball_self hr, by simpa [dist_comm] using hzr, hzne⟩ + have hcyl : hartogsCylinder D D₀ 0 r = V \ complexCoordinatePlane := by + ext z + simp only [hartogsCylinder, D, D₀, V, complexCoordinatePlane, + mem_union, mem_prod, Set.mem_sdiff, mem_ofPred_eq, closedBall_zero, + mem_singleton_iff] + tauto + obtain ⟨g, hg, he⟩ := exists_extension_hartogsCylinder (D := D) (D₀ := D₀) (ρ := 0) (R := r) + (isOpen_ball.prod isOpen_ball) (isPreconnected_ball.prod isPreconnected_ball) + (isOpen_ball.prod (isOpen_ball.sdiff isClosed_singleton)) hne + (fun _ hz => ⟨hz.1, hz.2.1⟩) le_rfl hr + (hf.mono (by rw [hcyl]; exact sdiff_subset_sdiff_left hVU)) + refine ⟨V, g, (isOpen_ball.prod isOpen_ball).prod isOpen_ball, ?_, hVU, hg, ?_⟩ + · exact ⟨⟨mem_ball_self hr, haA.1 ▸ mem_ball_self hr⟩, haA.2 ▸ mem_ball_self hr⟩ + · intro z hz + exact he (hcyl.symm ▸ ⟨hz.1, hz.2.2⟩) + · exact ⟨U \ complexCoordinatePlane, f, hopen, ⟨ha, haA⟩, sdiff_subset, hf, + fun _ _ => rfl⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/FunctionSpace.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/FunctionSpace.lean new file mode 100644 index 0000000000..1ece960725 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/FunctionSpace.lean @@ -0,0 +1,77 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension + +/-! +# Restriction across analytic sets of codimension at least two + +[Scheidemann][Scheidemann2005]'s second Riemann theorem is stated as an isomorphism of +holomorphic algebras. The forward map below is restriction. Injectivity uses density; +surjectivity uses the proved second Riemann extension theorem. Disconnected and empty domains +are allowed. No assertion about continuity of the inverse is needed for this algebraic +formulation. + +## Main results + +`analyticSetRestrictionAlgEquiv` is [Scheidemann][Scheidemann2005]'s second Riemann theorem as +an isomorphism of holomorphic algebras across an analytic set of slice codimension at least two. +`analyticSetRestrictionAlgEquiv_apply` is restriction of representatives. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set + +namespace SeveralComplexVariables + +/-- **Second Riemann extension theorem, algebraic form.** Restriction across an analytic +subset of slice codimension at least two is an isomorphism of complex algebras. +Surjectivity follows from automatic local boundedness and the first Riemann theorem. -/ +def analyticSetRestrictionAlgEquiv {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] + {U V : TopologicalSpace.Opens E} {A : Set E} + (hA : IsAnalyticSet U A) (hcodim : HasComplexSliceCodimensionAtLeast A 2) + (hV : (V : Set E) = (U : Set E) \ A) : + HolomorphicAlgebra U ≃ₐ[ℂ] HolomorphicAlgebra V := by + have hVU : V ≤ U := by + change (V : Set E) ⊆ (U : Set E) + rw [hV] + exact sdiff_subset + have hd : (U : Set E) ⊆ closure (V : Set E) := by + rw [hV] + exact hA.subset_closure_sdiff (hcodim.interior_eq_empty (by decide)) + have hi := holomorphicRestrict_injective_of_subset_closure (F := ℂ) hVU hd + have hs : Function.Surjective (holomorphicRestrict (F := ℂ) hVU) := by + apply holomorphicRestrict_surjective hVU + intro f hf + obtain ⟨g, hg, he⟩ := hA.exists_extension_of_codimension_two hcodim (hV ▸ hf) + exact ⟨g, hg, hV ▸ he⟩ + exact AlgEquiv.ofBijective (holomorphicRestrictAlgHom hVU) + (by simpa only [holomorphicRestrictAlgHom_coe, Function.Bijective] using And.intro hi hs) + +/-- The forward algebra equivalence is exactly restriction to the complement. -/ +@[simp] theorem analyticSetRestrictionAlgEquiv_apply {E : Type*} [NormedAddCommGroup E] + [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U V : TopologicalSpace.Opens E} {A : Set E} + (hA : IsAnalyticSet U A) (hcodim : HasComplexSliceCodimensionAtLeast A 2) + (hV : (V : Set E) = (U : Set E) \ A) (f : HolomorphicAlgebra U) : + analyticSetRestrictionAlgEquiv hA hcodim hV f = + holomorphicRestrict (show V ≤ U from by + change (V : Set E) ⊆ (U : Set E) + rw [hV] + exact sdiff_subset) f := by + simp [analyticSetRestrictionAlgEquiv] + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Hartogs.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Hartogs.lean new file mode 100644 index 0000000000..0ce886a008 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Hartogs.lean @@ -0,0 +1,200 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation + +/-! +# Hartogs extension across analytic subsets + +A Hartogs figure avoiding an analytic exceptional set determines an extension on the whole +cylinder. The complement of a proper analytic subset is connected, so the identity principle +identifies this extension with the original function. Isolated two-dimensional slices supply +such figures near the exceptional set. + +## Main results + +`IsAnalyticSet.exists_extension_of_hartogsCylinder_subset` extends across a Hartogs figure that +avoids the analytic set. `exists_hartogs_neighborhood` produces such a figure near an isolated +two-dimensional slice. `IsAnalyticSet.exists_local_extension_of_isolated_two_slice` is local +extension from that figure. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- A Hartogs cylinder avoiding an analytic subset gives an extension across that subset. +Connectedness of its complement ensures agreement everywhere it is defined. -/ +theorem IsAnalyticSet.exists_extension_of_hartogsCylinder_subset + {D D₀ : Set E} {ρ R : ℝ} {A : Set (E × ℂ)} + (hA : IsAnalyticSet (D ×ˢ ball 0 R) A) + (hD : IsOpen D) (hc : IsPreconnected D) (hD₀ : IsOpen D₀) (hne : D₀.Nonempty) + (hsub : D₀ ⊆ D) (hρ : 0 ≤ ρ) (hρR : ρ < R) + (hHA : hartogsCylinder D D₀ ρ R ⊆ (D ×ˢ ball 0 R) \ A) + {f : E × ℂ → F} (hf : AnalyticOnNhd ℂ f ((D ×ˢ ball 0 R) \ A)) : + ∃ g, AnalyticOnNhd ℂ g (D ×ˢ ball 0 R) ∧ EqOn g f ((D ×ˢ ball 0 R) \ A) := by + obtain ⟨g, hg, heq⟩ := exists_extension_hartogsCylinder hD hc hD₀ hne hsub hρ hρR + (hf.mono hHA) + obtain ⟨b, hb⟩ := hne + have hbH : (b, (0 : ℂ)) ∈ hartogsCylinder D D₀ ρ R := + Or.inr ⟨hb, mem_ball_self (hρ.trans_lt hρR)⟩ + have hproper : A ≠ D ×ˢ ball 0 R := by + intro h + exact (hHA hbH).2 (h.symm ▸ (hHA hbH).1) + have hconn := hA.isConnected_sdiff + ⟨⟨(b, 0), (hHA hbH).1⟩, hc.prod isPreconnected_ball⟩ hproper + have hH : IsOpen (hartogsCylinder D D₀ ρ R) := + (hD.prod (isOpen_ball.sdiff isClosed_closedBall)).union (hD₀.prod isOpen_ball) + exact ⟨g, hg, (hg.mono sdiff_subset).eqOn_of_preconnected_of_eventuallyEq hf + hconn.isPreconnected (hHA hbH) ((hH.eventually_mem hbH).mono (fun _ hz => heq hz))⟩ + +/-- The small base disc of an off-center Hartogs figure lies in the large base disc. -/ +private theorem offCenter_ball_subset {R : ℝ} (hR : 0 < R) : + ball ((R / 2 : ℝ) : ℂ) (R / 4) ⊆ ball 0 R := by + apply ball_subset_ball' + simp only [dist_zero_right, Complex.norm_real, Real.norm_eq_abs, abs_of_pos (half_pos hR)] + linarith + +/-- An off-center Hartogs figure fits inside a compact shell avoiding the origin. -/ +private theorem offCenter_hartogsCylinder_subset_shell {R : ℝ} (hR : 0 < R) : + hartogsCylinder (ball (0 : ℂ) R) (ball ((R / 2 : ℝ) : ℂ) (R / 4)) (R / 2) R ⊆ + closedBall (0 : ℂ × ℂ) R \ ball 0 (R / 4) := by + intro p hp + have hpR : p ∈ ball (0 : ℂ × ℂ) R := by + rw [← ball_prod_same] + rcases hp with hp | hp + · exact ⟨hp.1, hp.2.1⟩ + · exact ⟨offCenter_ball_subset hR hp.1, hp.2⟩ + refine ⟨ball_subset_closedBall hpR, ?_⟩ + intro hp0 + have hsmall : p ∈ ball (0 : ℂ) (R / 4) ×ˢ ball 0 (R / 4) := by + rwa [ball_prod_same] + rcases hp with hp | hp + · exact hp.2.2 (ball_subset_closedBall ((ball_subset_ball (by linarith)) hsmall.2)) + · have hd := dist_triangle ((R / 2 : ℝ) : ℂ) p.1 0 + have h₁ := mem_ball.mp hp.1 + have h₂ := mem_ball.mp hsmall.1 + rw [dist_comm p.1 ((R / 2 : ℝ) : ℂ)] at h₁ + simp only [dist_zero_right] at h₂ + simp only [dist_zero_right, Complex.norm_real, Real.norm_eq_abs, + abs_of_pos (half_pos hR)] at hd + linarith + +omit [FiniteDimensional ℂ E] in +/-- Compact subsets of an open set remain in it under small translations of a fixed continuous +linear image. -/ +private theorem eventually_add_image_subset {P : Type*} [NormedAddCommGroup P] + [NormedSpace ℂ P] {K : Set P} (hK : IsCompact K) {V : Set E} (hV : IsOpen V) + {a : E} (L : P →L[ℂ] E) (hsub : ∀ p ∈ K, a + L p ∈ V) : + ∀ᶠ z in 𝓝 a, ∀ p ∈ K, z + L p ∈ V := by + apply hK.eventually_forall_of_forall_eventually + intro p hp + exact (continuous_fst.add (L.continuous.comp continuous_snd)).continuousAt.preimage_mem_nhds + (hV.mem_nhds (hsub p hp)) + +omit [FiniteDimensional ℂ E] in +/-- An isolated two-dimensional slice supplies a Hartogs figure, together with nearby parallel +translates, that avoids the exceptional set. -/ +private theorem exists_hartogs_neighborhood {U A : Set E} + (hU : IsOpen U) (hUA : IsOpen (U \ A)) {a : E} (ha : a ∈ U) + (L : (ℂ × ℂ) →L[ℂ] E) + (hisol : ∀ᶠ p in 𝓝 (0 : ℂ × ℂ), a + L p ∈ A → p = 0) : + ∃ δ R : ℝ, 0 < δ ∧ 0 < R ∧ + (∀ q ∈ (ball a δ ×ˢ ball (0 : ℂ) R) ×ˢ ball (0 : ℂ) R, + q.1.1 + L (q.1.2, q.2) ∈ U) ∧ + (∀ q ∈ hartogsCylinder (ball a δ ×ˢ ball (0 : ℂ) R) + (ball a δ ×ˢ ball ((R / 2 : ℝ) : ℂ) (R / 4)) (R / 2) R, + q.1.1 + L (q.1.2, q.2) ∈ U \ A) := by + have hstay : ∀ᶠ p in 𝓝 (0 : ℂ × ℂ), a + L p ∈ U := + (continuous_const.add L.continuous).continuousAt.preimage_mem_nhds + (by simpa using hU.mem_nhds ha) + obtain ⟨ε, hε, hεsub⟩ := Metric.mem_nhds_iff.mp (hstay.and hisol) + let R := ε / 2 + have hR : 0 < R := half_pos hε + have hcentral (p : ℂ × ℂ) (hp : p ∈ closedBall 0 R) : + a + L p ∈ U ∧ (a + L p ∈ A → p = 0) := + hεsub (closedBall_subset_ball (half_lt_self hε) hp) + let K := closedBall (0 : ℂ × ℂ) R \ ball 0 (R / 4) + have hK : IsCompact K := (isCompact_closedBall _ _).diff isOpen_ball + have hcentralK (p : ℂ × ℂ) (hp : p ∈ K) : a + L p ∈ U \ A := by + refine ⟨(hcentral p hp.1).1, fun hpA => ?_⟩ + have hp0 := (hcentral p hp.1).2 hpA + exact hp.2 (hp0 ▸ mem_ball_self (by dsimp [R]; positivity)) + have hfull := eventually_add_image_subset (isCompact_closedBall (0 : ℂ × ℂ) R) + hU L (fun p hp => (hcentral p hp).1) + have hshell := eventually_add_image_subset hK hUA L hcentralK + obtain ⟨δ, hδ, hδsub⟩ := Metric.mem_nhds_iff.mp (hfull.and hshell) + refine ⟨δ, R, hδ, hR, ?_, ?_⟩ + · intro q hq + apply (hδsub hq.1.1).1 (q.1.2, q.2) + rw [← closedBall_prod_same] + exact ⟨ball_subset_closedBall hq.1.2, ball_subset_closedBall hq.2⟩ + · intro q hq + have hz : q.1.1 ∈ ball a δ := by rcases hq with hq | hq <;> exact hq.1.1 + apply (hδsub hz).2 (q.1.2, q.2) + apply offCenter_hartogsCylinder_subset_shell hR + rcases hq with hq | hq + · exact Or.inl ⟨hq.1.2, hq.2⟩ + · exact Or.inr ⟨hq.1.2, hq.2⟩ + +/-- An analytic subset with an isolated two-dimensional slice admits local extension of every +holomorphic function on its complement. No boundedness is assumed. -/ +theorem IsAnalyticSet.exists_local_extension_of_isolated_two_slice + {U A : Set E} (hA : IsAnalyticSet U A) {a : E} (ha : a ∈ U) + (L : (ℂ × ℂ) →L[ℂ] E) + (hisol : ∀ᶠ p in 𝓝 (0 : ℂ × ℂ), a + L p ∈ A → p = 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ A)) : + ∃ r : ℝ, 0 < r ∧ ∃ g : E → F, + AnalyticOnNhd ℂ g (ball a r) ∧ EqOn g f (ball a r \ A) := by + obtain ⟨δ, R, hδ, hR, hfull, hshell⟩ := + exists_hartogs_neighborhood hA.isOpen_domain hA.isOpen_sdiff ha L hisol + let D := ball a δ ×ˢ ball (0 : ℂ) R + let D₀ := ball a δ ×ˢ ball ((R / 2 : ℝ) : ℂ) (R / 4) + let B := D ×ˢ ball (0 : ℂ) R + let T : (E × ℂ) × ℂ → E := fun q => q.1.1 + L (q.1.2, q.2) + have hT : AnalyticOnNhd ℂ T B := fun q _ => + (analyticAt_fst.comp analyticAt_fst).add ((L.analyticAt _).comp + ((analyticAt_snd.comp analyticAt_fst).prod analyticAt_snd)) + have hD : IsOpen D := isOpen_ball.prod isOpen_ball + have hB : IsOpen B := hD.prod isOpen_ball + have hpre : IsAnalyticSet B (B ∩ T ⁻¹' A) := hA.preimage hB hT hfull + have hfT : AnalyticOnNhd ℂ (f ∘ T) (B \ (B ∩ T ⁻¹' A)) := by + intro q hq + exact (hf (T q) ⟨hfull q hq.1, fun hqA => hq.2 ⟨hq.1, hqA⟩⟩).comp (hT q hq.1) + have hH : hartogsCylinder D D₀ (R / 2) R ⊆ B \ (B ∩ T ⁻¹' A) := by + intro q hq + have hqB : q ∈ B := by + rcases hq with hq | hq + · exact ⟨hq.1, hq.2.1⟩ + · exact ⟨⟨hq.1.1, offCenter_ball_subset hR hq.1.2⟩, hq.2⟩ + exact ⟨hqB, fun hqA => (hshell q hq).2 hqA.2⟩ + obtain ⟨G, hG, hGF⟩ := hpre.exists_extension_of_hartogsCylinder_subset hD + (isPreconnected_ball.prod isPreconnected_ball) (isOpen_ball.prod isOpen_ball) + ⟨(a, ((R / 2 : ℝ) : ℂ)), mem_ball_self hδ, mem_ball_self (by positivity)⟩ + (prod_mono_right (offCenter_ball_subset hR)) (half_pos hR).le (half_lt_self hR) hH hfT + refine ⟨δ, hδ, fun z => G ((z, 0), 0), ?_, ?_⟩ + · intro z hz + exact (hG ((z, 0), 0) ⟨⟨hz, mem_ball_self hR⟩, mem_ball_self hR⟩).comp + (f := fun z : E => ((z, (0 : ℂ)), (0 : ℂ))) + ((analyticAt_id.prod analyticAt_const).prod analyticAt_const) + · intro z hz + have hzB : ((z, (0 : ℂ)), (0 : ℂ)) ∈ B := + ⟨⟨hz.1, mem_ball_self hR⟩, mem_ball_self hR⟩ + have hL0 : L ((0 : ℂ), (0 : ℂ)) = 0 := L.map_zero + have heq := hGF ⟨hzB, fun hp => hz.2 (by simpa [T, hL0] using hp.2)⟩ + simpa [T, hL0] using heq + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean new file mode 100644 index 0000000000..6b5c572bd0 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean @@ -0,0 +1,74 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic + +/-! +# Holomorphic equations and biholomorphic transport of analytic sets + +On open finite-dimensional complex domains, holomorphic finite-coordinate equations define +analytic subsets. Biholomorphic changes of ambient coordinates preserve analytic subsets. These +results use the holomorphy–analyticity equivalence and are separated from `AnalyticSet.Basic` so +that the definition and elementary analytic-set operations do not import holomorphic mapping +theory. + +References: [Range][Range1986] I §3.2; [Fritzsche–Grauert][FritzscheGrauert2002] I §8; +[Scheidemann][Scheidemann2005] §4.1. + +## Main results + +* `isAnalyticSet_zeroSet_pi_of_differentiableOn`: Holomorphic finite-coordinate equations on an open + finite-dimensional domain define an analytic subset, using Mathlib's equivalence of holomorphy and + analyticity. +* `IsAnalyticSet.image_biholomorphic`: Biholomorphic changes of ambient coordinates preserve + analytic subsets. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Holomorphic finite-coordinate equations on an open finite-dimensional domain define an analytic +subset, using Mathlib's equivalence of holomorphy and analyticity. -/ +theorem isAnalyticSet_zeroSet_pi_of_differentiableOn [FiniteDimensional ℂ E] + {ι : Type*} [Fintype ι] {U : Set E} (hU : IsOpen U) + {f : E → (ι → ℂ)} (hf : DifferentiableOn ℂ f U) : + IsAnalyticSet U (U ∩ f ⁻¹' {0}) := + isAnalyticSet_zeroSet_pi hU (hf.analyticOnNhd_of_finiteDimensional hU) + +/-- Biholomorphic changes of ambient coordinates preserve analytic subsets. -/ +theorem IsAnalyticSet.image_biholomorphic [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + {e : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) + {A : Set E} (hA : IsAnalyticSet e.source A) : IsAnalyticSet e.target (e '' A) := by + let := FiniteDimensional.complete ℂ E + have h := hA.preimage e.open_target + (he.2.analyticOnNhd_of_finiteDimensional e.open_target) e.symm.mapsTo + convert h using 1 + ext y + constructor + · rintro ⟨x, hx, rfl⟩ + exact ⟨e.map_source (hA.subset hx), by simpa [e.left_inv (hA.subset hx)] using hx⟩ + · rintro ⟨hy, hx⟩ + exact ⟨e.symm y, hx, e.right_inv hy⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Regular.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Regular.lean new file mode 100644 index 0000000000..efaf3f50b9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Regular.lean @@ -0,0 +1,297 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local + +/-! +# Regular points of analytic subsets + +Regularity means that local biholomorphic ambient coordinates identify the subset with the +kernel of a surjective complex linear map. This is intrinsic to the subset: `z₁² = 0` and `z₁ = +0` define the same regular hyperplane. No manifold structure is used. The full-rank-equations +criterion is proved by a linear right inverse and the holomorphic inverse mapping theorem. A +minimal nonvanishing derivative and persistence of zeros prove existence of regular hypersurface +points. Relative openness of the regular locus and relative closedness of the singular locus +follow from the definition. + +Reference: [Fritzsche–Grauert][FritzscheGrauert2002] I, 8.3–8.4; [Range][Range1986] I §3.2. + +## Main definitions + +* `IsRegularAnalyticSetAt`: Intrinsic regularity of codimension `q`: local biholomorphic coordinates + flatten `A` to the kernel of a surjective map to `ℂ^q`. +* `analyticRegularLocus`: The regular locus includes all local codimensions, including codimension + zero. +* `analyticSingularLocus`: Singular points are the points of the subset that are not regular. + +## Main results + +* `isRegularAnalyticSetAt_iff_exists_equations`: **Local coordinate characterization.** Regularity + is equivalent to the existence of full-rank defining equations, not a rank condition on an + arbitrary presentation. +* `exists_regularPoint_zeroSet`: **Regular points of a hypersurface.** A nonempty proper scalar zero + set in a preconnected domain contains a regular point of codimension one. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Intrinsic regularity of codimension `q`: local biholomorphic coordinates flatten `A` to the +kernel of a surjective map to `ℂ^q`. Membership in `A` is included. -/ +@[expose] def IsRegularAnalyticSetAt (A : Set E) (a : E) (q : ℕ) : Prop := + a ∈ A ∧ ∃ (e : OpenPartialHomeomorph E E) (L : E →L[ℂ] (Fin q → ℂ)), + IsBiholomorphic e ∧ a ∈ e.source ∧ Function.Surjective L ∧ + ∀ z ∈ e.source, z ∈ A ↔ L (e z) = 0 + +/-- The regular locus includes all local codimensions, including codimension zero. -/ +@[expose] def analyticRegularLocus (A : Set E) : Set E := {a | ∃ q, IsRegularAnalyticSetAt A a q} + +/-- Singular points are the points of the subset that are not regular. -/ +@[expose] def analyticSingularLocus (A : Set E) : Set E := A \ analyticRegularLocus A + +/-- Every regular point belongs to the subset. -/ +theorem analyticRegularLocus_subset (A : Set E) : analyticRegularLocus A ⊆ A := by + rintro a ⟨q, h⟩ + exact h.1 + +/-- The local codimension of a regular point is bounded by the ambient dimension. -/ +theorem IsRegularAnalyticSetAt.le_finrank [FiniteDimensional ℂ E] + {A : Set E} {a : E} {q : ℕ} (h : IsRegularAnalyticSetAt A a q) : + q ≤ Module.finrank ℂ E := by + obtain ⟨_, _, L, _, _, hL, _⟩ := h + simpa using LinearMap.finrank_le_finrank_of_surjective (f := L.toLinearMap) hL + +/-- A flattening chart witnesses the same codimension at every nearby point of the set. -/ +theorem IsRegularAnalyticSetAt.exists_open {A : Set E} {a : E} {q : ℕ} + (h : IsRegularAnalyticSetAt A a q) : + ∃ V, IsOpen V ∧ a ∈ V ∧ ∀ b ∈ V ∩ A, IsRegularAnalyticSetAt A b q := by + obtain ⟨_, e, L, he, ha, hL, hEq⟩ := h + exact ⟨e.source, e.open_source, ha, fun b hb => ⟨hb.2, e, L, he, hb.1, hL, hEq⟩⟩ + +/-- The regular locus is relatively open in the subset, without any global analyticity +assumption. -/ +theorem isOpen_relative_analyticRegularLocus (A : Set E) : + IsOpen {a : A | a.val ∈ analyticRegularLocus A} := by + rw [isOpen_iff_mem_nhds] + rintro a ⟨q, hq⟩ + obtain ⟨V, hV, haV, hreg⟩ := hq.exists_open + apply Filter.mem_of_superset ((hV.preimage continuous_subtype_val).mem_nhds haV) + intro b hb + exact ⟨q, hreg b ⟨hb, b.property⟩⟩ + +/-- The singular locus is relatively closed in the subset. This does not assert that it is +analytic. -/ +theorem isClosed_relative_analyticSingularLocus (A : Set E) : + IsClosed {a : A | a.val ∈ analyticSingularLocus A} := by + have he : {a : A | a.val ∈ analyticSingularLocus A} = + {a : A | a.val ∈ analyticRegularLocus A}ᶜ := by + ext a + simp [analyticSingularLocus] + rw [he] + exact (isOpen_relative_analyticRegularLocus A).isClosed_compl + +/-- On an analytic subset of `U`, the singular locus is relatively closed also in `U`. -/ +theorem IsAnalyticSet.isOpen_sdiff_singularLocus {U A : Set E} (hA : IsAnalyticSet U A) : + IsOpen (U \ analyticSingularLocus A) := by + classical + rw [isOpen_iff_mem_nhds] + rintro a ⟨haU, has⟩ + by_cases haA : a ∈ A + · have har : a ∈ analyticRegularLocus A := by + by_contra hn + exact has ⟨haA, hn⟩ + obtain ⟨q, hq⟩ := har + obtain ⟨V, hV, haV, hreg⟩ := hq.exists_open + apply Filter.mem_of_superset ((hA.isOpen_domain.inter hV).mem_nhds ⟨haU, haV⟩) + intro b hb + exact ⟨hb.1, fun hbs => hbs.2 ⟨q, hreg b ⟨hb.2, hbs.1⟩⟩⟩ + · exact Filter.mem_of_superset (hA.isOpen_sdiff.mem_nhds ⟨haU, haA⟩) + (fun b hb => ⟨hb.1, fun hbs => hb.2 hbs.1⟩) + +/-- Flattening coordinates supply local defining equations with surjective derivative. -/ +theorem IsRegularAnalyticSetAt.exists_equations [FiniteDimensional ℂ E] + {A : Set E} {a : E} {q : ℕ} (h : IsRegularAnalyticSetAt A a q) : + ∃ (V : Set E) (f : E → (Fin q → ℂ)), IsOpen V ∧ a ∈ V ∧ + AnalyticOnNhd ℂ f V ∧ (∀ z ∈ V, z ∈ A ↔ f z = 0) ∧ + Function.Surjective (fderiv ℂ f a) := by + let := FiniteDimensional.complete ℂ E + obtain ⟨_, e, L, he, ha, hL, hEq⟩ := h + refine ⟨e.source, L ∘ e, e.open_source, ha, ?_, hEq, ?_⟩ + · intro z hz + exact (L.analyticAt (e z)).comp + ((he.1.analyticOnNhd_of_finiteDimensional e.open_source) z hz) + · rw [fderiv_comp a L.differentiableAt (he.differentiableAt ha), L.fderiv] + obtain ⟨M, hM⟩ := he.isInvertible_fderiv ha + rw [← hM] + exact hL.comp M.surjective + +/-- Full-rank local defining equations admit flattening biholomorphic coordinates. A linear right +inverse corrects the defining map to have identity derivative, so the holomorphic inverse +mapping theorem supplies the required coordinates. -/ +theorem isRegularAnalyticSetAt_of_equations [FiniteDimensional ℂ E] + {A V : Set E} {a : E} {q : ℕ} (haA : a ∈ A) (hV : IsOpen V) (haV : a ∈ V) + {f : E → (Fin q → ℂ)} (hf : AnalyticOnNhd ℂ f V) + (hEq : ∀ z ∈ V, z ∈ A ↔ f z = 0) (hs : Function.Surjective (fderiv ℂ f a)) : + IsRegularAnalyticSetAt A a q := by + let L := fderiv ℂ f a + obtain ⟨R, hR⟩ := L.toLinearMap.exists_rightInverse_of_surjective + (LinearMap.range_eq_top.mpr hs) + let B : (Fin q → ℂ) →L[ℂ] E := R.toContinuousLinearMap + have hLB (y : Fin q → ℂ) : L (B y) = y := DFunLike.congr_fun hR y + let g : E → E := fun x => x + B (f x - L x) + have hg : DifferentiableOn ℂ g V := + differentiableOn_id.add (B.differentiable.comp_differentiableOn + (hf.differentiableOn.sub L.differentiable.differentiableOn)) + have hd : HasFDerivAt g (ContinuousLinearMap.id ℂ E) a := by + simpa only [g, L, Pi.add_def, Pi.sub_def, Function.comp_def, id_eq, + sub_self, ContinuousLinearMap.comp_zero, add_zero] using + (hasFDerivAt_id a).add (B.hasFDerivAt.comp a + ((hf a haV).differentiableAt.hasFDerivAt.sub L.hasFDerivAt)) + have hinv : (fderiv ℂ g a).IsInvertible := by + rw [hd.fderiv] + exact ⟨ContinuousLinearEquiv.refl ℂ E, rfl⟩ + obtain ⟨e, he, hae, heV, heq⟩ := exists_biholomorphic_of_isInvertible_fderiv hV hg haV hinv + refine ⟨haA, e, L, he, hae, hs, ?_⟩ + intro z hz + rw [hEq z (heV hz), heq] + have hLg : L (g z) = f z := by + dsimp [g] + rw [map_add, hLB] + abel + rw [hLg] + +/-- **Local coordinate characterization.** Regularity is equivalent to the existence +of full-rank defining equations, not a rank condition on an arbitrary presentation. +Both directions follow from the holomorphic inverse mapping theorem and the chain rule. -/ +theorem isRegularAnalyticSetAt_iff_exists_equations [FiniteDimensional ℂ E] + {A : Set E} {a : E} {q : ℕ} : + IsRegularAnalyticSetAt A a q ↔ a ∈ A ∧ + ∃ (V : Set E) (f : E → (Fin q → ℂ)), IsOpen V ∧ a ∈ V ∧ + AnalyticOnNhd ℂ f V ∧ (∀ z ∈ V, z ∈ A ↔ f z = 0) ∧ + Function.Surjective (fderiv ℂ f a) := by + refine ⟨fun h => ⟨h.1, h.exists_equations⟩, ?_⟩ + rintro ⟨haA, V, f, hV, haV, hf, hEq, hs⟩ + exact isRegularAnalyticSetAt_of_equations haA hV haV hf hEq hs + +/-- A surjective linear equation defines a regular linear subspace of the expected codimension. -/ +theorem isRegularAnalyticSetAt_linear_zeroSet (q : ℕ) (L : E →L[ℂ] (Fin q → ℂ)) + (hL : Function.Surjective L) {a : E} (ha : L a = 0) : + IsRegularAnalyticSetAt (L ⁻¹' {0}) a q := by + exact ⟨ha, OpenPartialHomeomorph.refl E, L, isBiholomorphic_refl, + Set.mem_univ a, hL, fun _ _ => Iff.rfl⟩ + +/-- A scalar defining equation with nonzero derivative defines a regular hypersurface. -/ +theorem isRegularAnalyticSetAt_of_scalar_equation [FiniteDimensional ℂ E] + {A V : Set E} {a : E} (haA : a ∈ A) (hV : IsOpen V) (haV : a ∈ V) + {f : E → ℂ} (hf : AnalyticOnNhd ℂ f V) + (hEq : ∀ z ∈ V, z ∈ A ↔ f z = 0) (hd : fderiv ℂ f a ≠ 0) : + IsRegularAnalyticSetAt A a 1 := by + have hs : Function.Surjective (fderiv ℂ f a) := by + apply LinearMap.surjective (f := (fderiv ℂ f a).toLinearMap) + intro h + apply hd + ext z + exact congrArg (fun L : E →ₗ[ℂ] ℂ => L z) h + apply isRegularAnalyticSetAt_of_equations (f := fun z (_ : Fin 1) => f z) + haA hV haV (AnalyticOnNhd.pi (fun _ => hf)) + · intro z hz + simpa [funext_iff] using hEq z hz + · rw [fderiv_pi (fun _ => (hf a haV).differentiableAt)] + intro y + obtain ⟨z, hz⟩ := hs (y 0) + refine ⟨z, ?_⟩ + ext i + fin_cases i + exact hz + +/-- A scalar zero set contained in a regular hypersurface is itself regular at each of its points on +that hypersurface. Persistence of zeros gives local equality. -/ +theorem IsRegularAnalyticSetAt.of_zeroSet_subset [FiniteDimensional ℂ E] + {A U : Set E} {a : E} (hA : IsRegularAnalyticSetAt A a 1) + (hU : IsOpen U) (haU : a ∈ U) {f : E → ℂ} (hf : AnalyticOnNhd ℂ f U) + (hfa : f a = 0) (hsub : ∀ z ∈ U, f z = 0 → z ∈ A) : + IsRegularAnalyticSetAt (U ∩ f ⁻¹' {0}) a 1 := by + obtain ⟨haA, e, L, he, hae, hL, hEq⟩ := hA + let l : E →L[ℂ] ℂ := (ContinuousLinearMap.proj (0 : Fin 1)).comp L + have hl (z : E) : l z = 0 ↔ L z = 0 := by + constructor + · intro hz + ext i + fin_cases i + exact hz + · intro hz + simp [l, hz] + have hls : Function.Surjective l := by + intro c + obtain ⟨z, hz⟩ := hL (fun _ => c) + exact ⟨z, by simp [l, hz]⟩ + let V := e.target ∩ e.symm ⁻¹' U + have hV : IsOpen V := e.isOpen_inter_preimage_symm hU + have hea : e a ∈ V := ⟨e.map_source hae, by simpa [e.left_inv hae] using haU⟩ + have hF : AnalyticOnNhd ℂ (f ∘ e.symm) V := by + intro y hy + exact (hf (e.symm y) hy.2).comp + ((he.2.analyticOnNhd_of_finiteDimensional e.open_target) y hy.1) + have hlocal := eventually_zeroSet_eq_linear_zeroSet hV hF hls hea + (by simpa [Function.comp_def, e.left_inv hae] using hfa) + ((hl (e a)).2 ((hEq a hae).1 haA)) (by + intro y hy hfy + apply (hl y).2 + have hAy := hsub (e.symm y) hy.2 hfy + simpa [e.right_inv hy.1] using (hEq (e.symm y) (e.map_target hy.1)).1 hAy) + have hnear : ∀ᶠ z in 𝓝 a, z ∈ U ∧ z ∈ e.source ∧ (f z = 0 ↔ L (e z) = 0) := by + filter_upwards [hU.eventually_mem haU, e.open_source.eventually_mem hae, + (e.continuousAt hae).eventually hlocal] with z hz hze heq + have heq' : f z = 0 ↔ l (e z) = 0 := by + simpa only [Function.comp_apply, e.left_inv hze] using heq + exact ⟨hz, hze, heq'.trans (hl (e z))⟩ + obtain ⟨T, hTsub, hT, haT⟩ := mem_nhds_iff.mp hnear + refine ⟨⟨haU, hfa⟩, e.restr T, L, he.restr T, ?_, hL, ?_⟩ + · rw [e.restr_source' T hT] + exact ⟨hae, haT⟩ + · intro z hz + rw [e.restr_source' T hT] at hz + have hzT := hTsub hz.2 + change (z ∈ U ∧ f z = 0) ↔ L (e z) = 0 + exact (and_iff_right hzT.1).trans hzT.2.2 + +/-- **Regular points of a hypersurface.** A nonempty proper scalar zero set in a +preconnected domain contains a regular point of codimension one. The nonempty zero-set +hypothesis repairs its omission in the printed [Fritzsche–Grauert][FritzscheGrauert2002] I, +Proposition 8.4. +Choose a minimal nonvanishing derivative, straighten its preceding derivative, +and use persistence of zeros to identify the two hypersurfaces locally. -/ +theorem exists_regularPoint_zeroSet [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) (hc : IsPreconnected U) {f : E → ℂ} + (hf : AnalyticOnNhd ℂ f U) (hne : ∃ b ∈ U, f b ≠ 0) (hz : ∃ a ∈ U, f a = 0) : + ∃ a, IsRegularAnalyticSetAt (U ∩ f ⁻¹' {0}) a 1 := by + obtain ⟨a, g, ha, hfa, hg, hsub, hd⟩ := + exists_analytic_zeroSet_superset_fderiv_ne_zero hU hc hf hne hz + have hreg : IsRegularAnalyticSetAt (U ∩ g ⁻¹' {0}) a 1 := + isRegularAnalyticSetAt_of_scalar_equation ⟨ha, hsub a ha hfa⟩ hU ha hg + (fun z hz => and_iff_right hz) hd + exact ⟨a, hreg.of_zeroSet_subset hU ha hf hfa (fun z hz hfz => ⟨hz, hsub z hz hfz⟩)⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Removable.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Removable.lean new file mode 100644 index 0000000000..aa263ee677 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Removable.lean @@ -0,0 +1,138 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected + +/-! +# Proper analytic subsets and the first Riemann extension theorem + +An analytic subset with empty interior is locally contained in proper scalar zero sets. In a +preconnected domain, properness suffices. This connects local finite equations with the existing +Banach-valued removability and connected-complement theory. For disconnected domains we retain +the empty-interior condition explicitly. + +References: [Range][Range1986] I, Theorem 3.8; [Fritzsche–Grauert][FritzscheGrauert2002] I, +8.1–8.2; [Scheidemann][Scheidemann2005] 4.1.6, 4.2.1–4.2.2. + +## Main results + +`IsAnalyticSet.interior_eq_empty` is emptiness of the interior of a proper analytic subset of a +preconnected domain. `IsAnalyticSet.locallyContainedInAnalyticZeroSet` places a proper analytic +subset in proper scalar zero sets. `IsAnalyticSet.exists_extension_of_locally_bounded` is the +first Riemann extension theorem for locally bounded Banach-valued maps. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- An analytic subset with interior in a preconnected ambient domain is the whole domain. -/ +theorem IsAnalyticSet.eq_domain_of_interior_nonempty {U A : Set E} + (hA : IsAnalyticSet U A) (hc : IsPreconnected U) (hne : (interior A).Nonempty) : + A = U := by + let : NormedSpace ℝ E := NormedSpace.restrictScalars ℝ ℂ E + apply Subset.antisymm hA.subset + apply Subset.trans _ interior_subset + apply hc.subset_of_closure_inter_subset isOpen_interior + · obtain ⟨a, ha⟩ := hne + exact ⟨a, hA.subset (interior_subset ha), ha⟩ + · rintro a ⟨haC, haU⟩ + obtain ⟨V, hV, haV, _, s, hs, he⟩ := hA.2 a haU + obtain ⟨r, hr, hBV⟩ := Metric.mem_nhds_iff.mp (hV.mem_nhds haV) + obtain ⟨b, hbI, hbr⟩ := Metric.mem_closure_iff.mp haC r hr + have hbB : b ∈ ball a r := by simpa [dist_comm] using hbr + have hzero : ∀ f ∈ s, EqOn f 0 (ball a r) := by + intro f hfs + apply ((hs f hfs).mono hBV).eqOn_zero_of_preconnected_of_eventuallyEq_zero + isPreconnected_ball hbB + filter_upwards [isOpen_interior.mem_nhds hbI, isOpen_ball.mem_nhds hbB] with z hzI hzB + exact (he z (hBV hzB)).mp (interior_subset hzI) f hfs + apply mem_interior_iff_mem_nhds.mpr + filter_upwards [ball_mem_nhds a hr] with z hz + exact (he z (hBV hz)).mpr (fun f hf => hzero f hf hz) + +/-- A proper analytic subset of a preconnected domain has empty interior. -/ +theorem IsAnalyticSet.interior_eq_empty {U A : Set E} (hA : IsAnalyticSet U A) + (hc : IsPreconnected U) (hp : A ≠ U) : interior A = ∅ := by + by_contra hn + exact hp (hA.eq_domain_of_interior_nonempty hc (Set.nonempty_iff_ne_empty.mpr hn)) + +/-- An analytic subset with empty interior is locally contained in a proper scalar zero set. -/ +theorem IsAnalyticSet.locallyContainedInAnalyticZeroSet {U A : Set E} + (hA : IsAnalyticSet U A) (hi : interior A = ∅) : LocallyContainedInAnalyticZeroSet U A := by + classical + unfold LocallyContainedInAnalyticZeroSet + intro a ha + obtain ⟨V, hV, haV, hVU, s, hs, he⟩ := hA.2 a ha + have hn : ∃ f ∈ s, ¬ f =ᶠ[𝓝 a] 0 := by + by_contra! hall + have hz : ∀ᶠ z in 𝓝 a, ∀ f ∈ s, f z = 0 := (eventually_all_finset s).mpr hall + have haI : a ∈ interior A := by + apply mem_interior_iff_mem_nhds.mpr + filter_upwards [hV.mem_nhds haV, hz] with z hzV hzall + exact (he z hzV).mpr hzall + simp [hi] at haI + obtain ⟨f, hfs, hfn⟩ := hn + exact ⟨V, f, hV, haV, hVU, hs f hfs, hfn, + fun z hz => (he z hz.1).mp hz.2 f hfs⟩ + +/-- The complement of an analytic subset with empty interior is dense in the ambient domain. -/ +theorem IsAnalyticSet.subset_closure_sdiff {U A : Set E} (hA : IsAnalyticSet U A) + (hi : interior A = ∅) : U ⊆ closure (U \ A) := + (hA.locallyContainedInAnalyticZeroSet hi).subset_closure + +/-- Continuous extensions across a proper analytic exceptional set are unique on the domain. -/ +theorem IsAnalyticSet.extension_unique {F : Type*} [TopologicalSpace F] [T2Space F] + {U A : Set E} (hA : IsAnalyticSet U A) (hi : interior A = ∅) + {f g h : E → F} (hg : ContinuousOn g U) (hh : ContinuousOn h U) + (hgf : EqOn g f (U \ A)) (hhf : EqOn h f (U \ A)) : EqOn g h U := + (hA.locallyContainedInAnalyticZeroSet hi).extension_unique hg hh hgf hhf + +/-- A proper analytic subset cannot disconnect a connected open domain. -/ +theorem IsAnalyticSet.isConnected_sdiff [FiniteDimensional ℂ E] + {U A : Set E} (hA : IsAnalyticSet U A) (hc : IsConnected U) (hp : A ≠ U) : + IsConnected (U \ A) := + isConnected_sdiff_of_locallyContainedInAnalyticZeroSet hc hA.isOpen_sdiff + (hA.locallyContainedInAnalyticZeroSet (hA.interior_eq_empty hc.isPreconnected hp)) + +/-- **First Riemann extension theorem.** Local boundedness is required only near the +exceptional set. Empty interior replaces componentwise properness on a disconnected domain. +The extension is unique on `U` by `IsAnalyticSet.extension_unique`. -/ +theorem IsAnalyticSet.exists_extension_of_locally_bounded [FiniteDimensional ℂ E] + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {U A : Set E} (hA : IsAnalyticSet U A) (hi : interior A = ∅) {f : E → F} + (hf : AnalyticOnNhd ℂ f (U \ A)) + (hb : ∀ a ∈ A, ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ A), ‖f z‖ ≤ C) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ A) := by + apply exists_analyticOnNhd_extension_across_locallyContainedZeroSet hA.isOpen_sdiff + (hA.locallyContainedInAnalyticZeroSet hi) hf + intro a ha + by_cases haA : a ∈ A + · exact hb a haA + · have hn : ∀ᶠ z in 𝓝 a, ‖f z‖ < ‖f a‖ + 1 := + ((hf a ⟨ha, haA⟩).continuousAt.norm).eventually_lt_const (by linarith) + obtain ⟨r, hr, hbound⟩ := Metric.mem_nhds_iff.mp hn + exact ⟨r, hr, ‖f a‖ + 1, fun z hz => (hbound hz.1).le⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analyticity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analyticity.lean new file mode 100644 index 0000000000..a8b5d086cc --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analyticity.lean @@ -0,0 +1,106 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Constructions +public import Mathlib.Analysis.Calculus.Deriv.Pi +public import Mathlib.Analysis.Complex.CauchyIntegral +public import Mathlib.Analysis.Normed.Module.FiniteDimension +public import Mathlib.LinearAlgebra.FiniteDimensional.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood + +/-! +# Analyticity of holomorphic maps in finite dimension + +This file proves the several-complex-variables theorem that a complex Fréchet-differentiable map on +an open subset of a finite-dimensional complex normed space is analytic. The general theorem uses +coordinates only inside its proof. The file is a temporary project home for material ultimately +intended for a Mathlib location such as `Mathlib.Analysis.Complex.SeveralVariables.Analyticity`. It +builds on the polydisc Cauchy-series and Osgood theorems; the underlying predicates are Mathlib +definitions. + +## Main results + +`DifferentiableOn.analyticOnNhd_of_finiteDimensional` and +`differentiableOn_iff_analyticOnNhd_of_finiteDimensional` give the coordinate-free interface for +arbitrary finite-dimensional complex normed domains and complete complex normed codomains. + +`DifferentiableOn.analyticOnNhd_pi` and `differentiableOn_iff_analyticOnNhd_pi` give the +corresponding interface for finite coordinate spaces `ι → ℂ`. Such spaces are natural for +separate holomorphy, coordinate derivatives, and polydisc expansions. The coordinate theorem is +proved first and then transported along a linear equivalence; this proof order imposes no choice +of coordinates on the general statements. +-/ + +public section + +open Set + +section Coordinates + +variable {ι F : Type*} [Fintype ι] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- A complex Fréchet-differentiable map on an open subset of a finite complex coordinate space is +analytic there. -/ +theorem DifferentiableOn.analyticOnNhd_pi {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : DifferentiableOn ℂ f U) (hU : IsOpen U) : AnalyticOnNhd ℂ f U := by + classical + apply SeveralComplexVariables.analyticOnNhd_pi_of_analyticOnNhd_update hU hf.continuousOn + intro z hz i + let V : Set ℂ := {w | Function.update z i w ∈ U} + have hupdate : Continuous (fun w : ℂ ↦ Function.update z i w) := by fun_prop + have hupdate_diff : Differentiable ℂ (fun w : ℂ ↦ Function.update z i w) := + fun w => (hasDerivAt_update z i w).differentiableAt + have hV : IsOpen V := hU.preimage hupdate + have hd : DifferentiableOn ℂ (fun w ↦ f (Function.update z i w)) V := by + intro w hw + exact (((hf _ hw).differentiableAt (hU.mem_nhds hw)).comp w + hupdate_diff.differentiableAt).differentiableWithinAt + exact hd.analyticAt (hV.mem_nhds (by simpa [V] using hz)) + +/-- On an open subset of a finite complex coordinate space, complex Fréchet differentiability and +analyticity are equivalent. -/ +theorem differentiableOn_iff_analyticOnNhd_pi {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hU : IsOpen U) : DifferentiableOn ℂ f U ↔ AnalyticOnNhd ℂ f U := + ⟨fun hf ↦ hf.analyticOnNhd_pi hU, fun hf ↦ hf.differentiableOn⟩ + +end Coordinates + +section FiniteDimensional + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Complex differentiability on an open finite-dimensional domain implies analyticity. No choice of +coordinates occurs in the statement. -/ +theorem DifferentiableOn.analyticOnNhd_of_finiteDimensional {U : Set E} {f : E → F} + (hf : DifferentiableOn ℂ f U) (hU : IsOpen U) : AnalyticOnNhd ℂ f U := by + let e := (Module.finBasis ℂ E).equivFunL + have hg : DifferentiableOn ℂ (f ∘ e.symm) (e.symm ⁻¹' U) := + hf.comp e.symm.differentiable.differentiableOn (fun _ hx => hx) + have ha := hg.analyticOnNhd_pi (hU.preimage e.symm.continuous) + intro x hx + have hmem : e x ∈ e.symm ⁻¹' U := by simpa using hx + simpa [Function.comp_def] using + (ha (e x) hmem).comp_of_eq (e.toContinuousLinearMap.analyticAt x) rfl + +/-- On an open finite-dimensional domain, holomorphy may be expressed using either complex Fréchet +differentiability or Mathlib's analytic predicate. -/ +theorem differentiableOn_iff_analyticOnNhd_of_finiteDimensional {U : Set E} {f : E → F} + (hU : IsOpen U) : DifferentiableOn ℂ f U ↔ AnalyticOnNhd ℂ f U := + ⟨fun hf => hf.analyticOnNhd_of_finiteDimensional hU, fun hf => hf.differentiableOn⟩ + +/-- An everywhere complex-differentiable map on a finite-dimensional space is entire. -/ +theorem Differentiable.analyticOnNhd_of_finiteDimensional {f : E → F} + (hf : Differentiable ℂ f) : AnalyticOnNhd ℂ f Set.univ := + hf.differentiableOn.analyticOnNhd_of_finiteDimensional isOpen_univ + +end FiniteDimensional + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BallAutomorphisms.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BallAutomorphisms.lean new file mode 100644 index 0000000000..a5688fe619 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BallAutomorphisms.lean @@ -0,0 +1,385 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Schwarz +public import Mathlib.Analysis.InnerProductSpace.PiL2 +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity + +import Mathlib.Tactic.Module + +/-! +# Automorphisms of the Euclidean ball and the ball–polydisc distinction + +The explicit involution exchanges an interior point with zero. Holomorphy, a nonvanishing +denominator, the metric identity, preservation of the ball, and involutivity are proved. +Packaging as a biholomorphism and transitivity are proved consequences, independent of Cartan +uniqueness and circular-domain rigidity. The ball–polydisc inequivalence follows independently +from Schwarz bounds on derivatives and the parallelogram identity in dimension at least two. The +source uses the supremum norm and the target uses `EuclideanSpace`, explicitly. References: +[Scheidemann][Scheidemann2005] (2005), Theorem 3.2.1 and Exercise 3.3.4. + +## Main definitions + +* `ballParallelComponent`: Projection onto the complex line through `a`, with value zero when `a = + 0`. +* `ballMobius`: The standard ball involution. +* `ballMobiusOpenPartialHomeomorph`: The standard involution as an equivalence of open unit balls, + with an explicit formula. + +## Main results + +* `ballMobius_norm_identity`: The metric identity for the standard ball map, expressed without + division. +* `mapsTo_ballMobius`: The standard ball map preserves the unit ball, by its metric identity. +* `ballMobius_ballMobius`: The ball automorphism is an involution of the unit ball, using the + parallel and perpendicular components. +* `isBiholomorphic_ballMobius`: Both directions of the explicit ball equivalence are holomorphic. +* `exists_ball_automorphism`: The unit ball is homogeneous under biholomorphic automorphisms: any + interior point can be sent to any other, by composing two explicit ball involutions. +* `not_exists_isBiholomorphic_polydisc_ball`: The Euclidean unit ball and the unit polydisc are not + biholomorphic in dimension at least two. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Metric +open scoped InnerProductSpace + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℂ E] + +/-- Projection onto the complex line through `a`, with value zero when `a = 0`. -/ +@[expose] def ballParallelComponent (a z : E) : E := + (⟪a, z⟫_ℂ / (‖a‖ : ℂ) ^ 2) • a + +/-- The standard ball involution. Mathlib's inner product is linear in its second argument; the +scalar in the perpendicular component is `sqrt (1 - ‖a‖²)`. -/ +@[expose] def ballMobius (a z : E) : E := + (1 - ⟪a, z⟫_ℂ)⁻¹ • + (a - ballParallelComponent a z - + (Real.sqrt (1 - ‖a‖ ^ 2) : ℂ) • (z - ballParallelComponent a z)) + +/-- At the origin, the standard involution is negation, including dimension zero. -/ +theorem ballMobius_zero (z : E) : ballMobius 0 z = -z := by + simp [ballMobius, ballParallelComponent] + +/-- The ball involution exchanges zero with its parameter. -/ +theorem ballMobius_apply_zero (a : E) : ballMobius a 0 = a := by + simp [ballMobius, ballParallelComponent] + +/-- The ball involution sends its parameter to zero. -/ +theorem ballMobius_apply_self (a : E) : ballMobius a a = 0 := by + by_cases ha : a = 0 + · simp [ha, ballMobius_zero] + · have hn : (‖a‖ : ℂ) ^ 2 ≠ 0 := pow_ne_zero 2 (by exact_mod_cast (norm_ne_zero_iff.mpr ha)) + simp [ballMobius, ballParallelComponent, inner_self_eq_norm_sq_to_K, div_self hn] + +/-- The denominator in the ball involution is nonzero on the unit ball. -/ +theorem ballMobius_denominator_ne_zero {a z : E} (ha : a ∈ ball 0 1) (hz : z ∈ ball 0 1) : + 1 - ⟪a, z⟫_ℂ ≠ 0 := by + have ha' : ‖a‖ < 1 := by simpa only [mem_ball, dist_zero_right] using ha + have hz' : ‖z‖ < 1 := by simpa only [mem_ball, dist_zero_right] using hz + have hi : ‖⟪a, z⟫_ℂ‖ < 1 := calc + ‖⟪a, z⟫_ℂ‖ ≤ ‖a‖ * ‖z‖ := norm_inner_le_norm _ _ + _ ≤ 1 * ‖z‖ := mul_le_mul_of_nonneg_right ha'.le (norm_nonneg _) + _ < 1 := by simpa using hz' + intro h + have he := (sub_eq_zero.mp h).symm + simp [he] at hi + +/-- The projection formula is complex differentiable even for the zero parameter. -/ +theorem differentiable_ballParallelComponent (a : E) : Differentiable ℂ (ballParallelComponent a) + := by + unfold ballParallelComponent + simpa only [innerSL_apply_apply, div_eq_mul_inv] using + ((innerSL ℂ a).differentiable.mul_const (((‖a‖ : ℂ) ^ 2)⁻¹)).smul_const a + +/-- The explicit ball involution is holomorphic on the unit ball. -/ +theorem differentiableOn_ballMobius {a : E} (ha : a ∈ ball 0 1) : + DifferentiableOn ℂ (ballMobius a) (ball 0 1) := by + intro z hz + have hi : DifferentiableAt ℂ (fun w => ⟪a, w⟫_ℂ) z := (innerSL ℂ a).differentiableAt + have hp := differentiable_ballParallelComponent a z + exact ((((differentiableAt_const (1 : ℂ)).sub hi).inv + (ballMobius_denominator_ne_zero ha hz)).smul + (((differentiableAt_const a).sub hp).sub + ((differentiableAt_const (Real.sqrt (1 - ‖a‖ ^ 2) : ℂ)).smul + (differentiableAt_id.sub hp)))).differentiableWithinAt + +/-- Orthogonal projection onto the parameter line preserves its inner product with the parameter. -/ +theorem inner_ballParallelComponent (a z : E) : + ⟪a, ballParallelComponent a z⟫_ℂ = ⟪a, z⟫_ℂ := by + by_cases ha : a = 0 + · simp [ha] + · have hn : (‖a‖ : ℂ) ^ 2 ≠ 0 := by exact_mod_cast pow_ne_zero 2 (norm_ne_zero_iff.mpr ha) + simp [ballParallelComponent, inner_smul_right, inner_self_eq_norm_sq_to_K, hn] + +/-- The squared norm of the parallel component, in a form valid also for a zero parameter. -/ +theorem norm_ballParallelComponent_sq_mul (a z : E) : + ‖ballParallelComponent a z‖ ^ 2 * ‖a‖ ^ 2 = ‖⟪a, z⟫_ℂ‖ ^ 2 := by + by_cases ha : a = 0 + · simp [ha] + · have hn := norm_ne_zero_iff.mpr ha + simp only [ballParallelComponent, norm_smul, norm_div, norm_pow, + Complex.norm_real, Real.norm_eq_abs, abs_norm] + field_simp + +/-- The metric identity for the standard ball map, expressed without division. -/ +theorem ballMobius_norm_identity {a z : E} (ha : a ∈ ball 0 1) (hz : z ∈ ball 0 1) : + (1 - ‖ballMobius a z‖ ^ 2) * ‖1 - ⟪a, z⟫_ℂ‖ ^ 2 = + (1 - ‖a‖ ^ 2) * (1 - ‖z‖ ^ 2) := by + let p := ballParallelComponent a z + let q := z - p + let s := Real.sqrt (1 - ‖a‖ ^ 2) + have ha' : ‖a‖ < 1 := by simpa using ha + have hs : s ^ 2 = 1 - ‖a‖ ^ 2 := Real.sq_sqrt (by nlinarith [norm_nonneg a]) + have haq : ⟪a, q⟫_ℂ = 0 := by + simp [q, p, inner_sub_right, inner_ballParallelComponent] + have hpq : ⟪p, q⟫_ℂ = 0 := by + simp only [p, ballParallelComponent, inner_smul_left, haq, mul_zero] + have horth : ⟪a - p, (s : ℂ) • q⟫_ℂ = 0 := by + simp only [inner_smul_right, inner_sub_left, haq, hpq, sub_self, mul_zero] + have hq : ‖z‖ ^ 2 = ‖p‖ ^ 2 + ‖q‖ ^ 2 := by + have h := norm_add_sq (𝕜 := ℂ) p q + simpa only [q, add_sub_cancel, hpq, map_zero, mul_zero, add_zero] using h + have hp : ‖a - p‖ ^ 2 = ‖a‖ ^ 2 - 2 * (⟪a, z⟫_ℂ).re + ‖p‖ ^ 2 := by + simpa only [p, inner_ballParallelComponent, RCLike.re_to_complex] using + (norm_sub_sq (𝕜 := ℂ) a p) + have hN : ‖a - p - (s : ℂ) • q‖ ^ 2 = + ‖a‖ ^ 2 - 2 * (⟪a, z⟫_ℂ).re + ‖⟪a, z⟫_ℂ‖ ^ 2 + + (1 - ‖a‖ ^ 2) * ‖z‖ ^ 2 := by + have h := norm_sub_sq (𝕜 := ℂ) (a - p) ((s : ℂ) • q) + simp only [horth, map_zero, mul_zero, sub_zero, norm_smul, Complex.norm_real, + Real.norm_eq_abs, mul_pow, sq_abs] at h + have hpp := norm_ballParallelComponent_sq_mul a z + change ‖p‖ ^ 2 * ‖a‖ ^ 2 = _ at hpp + rw [hs, hp] at h + nlinarith [hq] + have hd : ‖1 - ⟪a, z⟫_ℂ‖ ≠ 0 := norm_ne_zero_iff.mpr (ballMobius_denominator_ne_zero ha hz) + have hscale : ‖ballMobius a z‖ ^ 2 * ‖1 - ⟪a, z⟫_ℂ‖ ^ 2 = + ‖a - p - (s : ℂ) • q‖ ^ 2 := by + simp only [ballMobius, norm_smul, norm_inv, mul_pow, p, q, s] + field_simp + have hden : ‖1 - ⟪a, z⟫_ℂ‖ ^ 2 = 1 - 2 * (⟪a, z⟫_ℂ).re + ‖⟪a, z⟫_ℂ‖ ^ 2 := by + simp only [Complex.sq_norm, Complex.normSq_apply, Complex.sub_re, Complex.one_re, + Complex.sub_im, Complex.one_im] + ring + rw [hN] at hscale + nlinarith + +/-- The standard ball map preserves the unit ball, by its metric identity. -/ +theorem mapsTo_ballMobius {a : E} (ha : a ∈ ball 0 1) : + MapsTo (ballMobius a) (ball 0 1) (ball 0 1) := by + intro z hz + have ha' : ‖a‖ < 1 := by simpa using ha + have hz' : ‖z‖ < 1 := by simpa using hz + have hpos : 0 < (1 - ‖a‖ ^ 2) * (1 - ‖z‖ ^ 2) := + mul_pos (by nlinarith [norm_nonneg a]) (by nlinarith [norm_nonneg z]) + rw [← ballMobius_norm_identity ha hz] at hpos + have hn : 0 < 1 - ‖ballMobius a z‖ ^ 2 := + pos_of_mul_pos_left hpos (sq_nonneg _) + simpa only [mem_ball, dist_zero_right] using + (show ‖ballMobius a z‖ < 1 by nlinarith [norm_nonneg (ballMobius a z)]) + +/-- The ball automorphism is an involution of the unit ball, using the parallel and perpendicular +components. -/ +theorem ballMobius_ballMobius {a : E} (ha : a ∈ ball 0 1) : + ∀ z ∈ ball 0 1, ballMobius a (ballMobius a z) = z := by + intro z hz + let s : ℂ := (Real.sqrt (1 - ‖a‖ ^ 2) : ℂ) + let A : ℂ := (‖a‖ : ℂ) ^ 2 + let P : E →ₗ[ℂ] E := A⁻¹ • (innerSL ℂ a).toLinearMap.smulRight a + let T : E →ₗ[ℂ] E := P + s • (LinearMap.id - P) + have hP (w : E) : P w = ballParallelComponent a w := by + simp only [P, A, LinearMap.smul_apply, LinearMap.smulRight_apply, + ContinuousLinearMap.coe_coe, innerSL_apply_apply, ballParallelComponent, div_eq_mul_inv] + module + have hT (w : E) : T w = P w + s • (w - P w) := rfl + have hiP (w : E) : ⟪a, P w⟫_ℂ = ⟪a, w⟫_ℂ := by + rw [hP, inner_ballParallelComponent] + have hiT (w : E) : ⟪a, T w⟫_ℂ = ⟪a, w⟫_ℂ := by + simp only [hT, inner_add_right, inner_smul_right, inner_sub_right, hiP, + sub_self, mul_zero, add_zero] + have hPa : P a = a := by + by_cases h : a = 0 + · simp [h] + · have hn : A ≠ 0 := by dsimp [A]; exact_mod_cast pow_ne_zero 2 (norm_ne_zero_iff.mpr h) + simp [hP, ballParallelComponent, inner_self_eq_norm_sq_to_K, A, hn] + have hTa : T a = a := by rw [hT, hPa]; simp + have hAP (w : E) : A • P w = ⟪a, w⟫_ℂ • a := by + by_cases h : a = 0 + · simp [A, h] + · have hn : A ≠ 0 := by dsimp [A]; exact_mod_cast pow_ne_zero 2 (norm_ne_zero_iff.mpr h) + simp [P, smul_smul, hn] + have hs : s ^ 2 = 1 - A := by + have ha' : ‖a‖ < 1 := by simpa using ha + have h := Real.sq_sqrt (show 0 ≤ 1 - ‖a‖ ^ 2 by nlinarith [norm_nonneg a]) + dsimp [s, A] + exact_mod_cast h + have hPT (w : E) : P (T w) = P w := by + simp only [hP, ballParallelComponent, hiT] + have hTT (w : E) : T (T w) = (1 - A) • w + ⟪a, w⟫_ℂ • a := by + calc + T (T w) = P w + s ^ 2 • (w - P w) := by rw [hT, hPT, hT]; module + _ = (1 - A) • w + A • P w := by rw [hs]; module + _ = _ := by rw [hAP] + have hmob (w : E) : ballMobius a w = (1 - ⟪a, w⟫_ℂ)⁻¹ • (a - T w) := by + rw [ballMobius, hT, hP] + dsimp [s] + module + let c := ⟪a, z⟫_ℂ + let d := 1 - c + have hd : d ≠ 0 := ballMobius_denominator_ne_zero ha hz + have hd' : 1 - ⟪a, ballMobius a z⟫_ℂ ≠ 0 := + ballMobius_denominator_ne_zero ha (mapsTo_ballMobius ha hz) + have hden : d * (1 - ⟪a, ballMobius a z⟫_ℂ) = 1 - A := by + rw [hmob] + simp only [inner_smul_right, inner_sub_right, inner_self_eq_norm_sq_to_K, hiT] + change d * (1 - d⁻¹ * (A - c)) = 1 - A + field_simp + dsimp [d] + ring + rw [hmob, inv_smul_eq_iff₀ hd'] + apply smul_right_injective E hd + change d • (a - T (ballMobius a z)) = d • ((1 - ⟪a, ballMobius a z⟫_ℂ) • z) + rw [smul_sub] + conv_lhs => rw [hmob, map_smul, map_sub, hTa, hTT] + change d • a - d • (d⁻¹ • (a - ((1 - A) • z + c • a))) = + d • ((1 - ⟪a, ballMobius a z⟫_ℂ) • z) + rw [smul_inv_smul₀ hd, smul_smul, hden] + dsimp [d] + module + +/-- The standard involution as an equivalence of open unit balls, with an explicit formula. -/ +@[expose] def ballMobiusOpenPartialHomeomorph (a : E) (ha : a ∈ ball 0 1) : + OpenPartialHomeomorph E E where + toFun := ballMobius a + invFun := ballMobius a + source := ball 0 1 + target := ball 0 1 + map_source' := mapsTo_ballMobius ha + map_target' := mapsTo_ballMobius ha + left_inv' := ballMobius_ballMobius ha + right_inv' := ballMobius_ballMobius ha + continuousOn_toFun := (differentiableOn_ballMobius ha).continuousOn + continuousOn_invFun := (differentiableOn_ballMobius ha).continuousOn + open_source := isOpen_ball + open_target := isOpen_ball + +/-- Both directions of the explicit ball equivalence are holomorphic. -/ +theorem isBiholomorphic_ballMobius (a : E) (ha : a ∈ ball 0 1) : + IsBiholomorphic (ballMobiusOpenPartialHomeomorph a ha) := + ⟨differentiableOn_ballMobius ha, differentiableOn_ballMobius ha⟩ + +/-- The unit ball is homogeneous under biholomorphic automorphisms: any interior point can be sent +to any other, by composing two explicit ball involutions. -/ +theorem exists_ball_automorphism {a b : E} + (ha : a ∈ ball 0 1) (hb : b ∈ ball 0 1) : + ∃ e : OpenPartialHomeomorph E E, IsBiholomorphic e ∧ + e.source = ball 0 1 ∧ e.target = ball 0 1 ∧ e a = b := by + let A := ballMobiusOpenPartialHomeomorph a ha + let B := ballMobiusOpenPartialHomeomorph b hb + refine ⟨A.trans B, (isBiholomorphic_ballMobius a ha).trans (isBiholomorphic_ballMobius b hb), + ?_, ?_, ?_⟩ + · rw [OpenPartialHomeomorph.trans_source] + exact inter_eq_left.mpr (mapsTo_ballMobius ha) + · rw [OpenPartialHomeomorph.trans_target] + exact inter_eq_left.mpr (mapsTo_ballMobius hb) + · change ballMobius b (ballMobius a a) = b + rw [ballMobius_apply_self a, ballMobius_apply_zero] + +/-- The derivative at zero of an origin-preserving biholomorphism between unit balls preserves +norms. Schwarz bounds for the map and its inverse prove both inequalities, without Cartan +uniqueness or finite-dimensional assumptions. -/ +theorem IsBiholomorphic.norm_fderiv_apply_eq_of_unit_ball + {A B : Type*} [NormedAddCommGroup A] [NormedSpace ℂ A] + [NormedAddCommGroup B] [NormedSpace ℂ B] + {e : OpenPartialHomeomorph A B} (he : IsBiholomorphic e) + (hs : e.source = ball 0 1) (ht : e.target = ball 0 1) (hfix : e 0 = 0) + (x : A) : ‖fderiv ℂ e 0 x‖ = ‖x‖ := by + have hzero : (0 : A) ∈ e.source := by rw [hs]; exact mem_ball_self zero_lt_one + have hinv : e.symm 0 = 0 := by simpa [hfix] using e.left_inv hzero + have hd : ‖fderiv ℂ e 0‖ ≤ 1 := + Complex.norm_fderiv_le_one_of_mapsTo_ball (hs ▸ he.1) + (fun z hz => by + rw [hfix] + exact ball_subset_closedBall (ht ▸ e.map_source (hs ▸ hz))) zero_lt_one + have hi : ‖fderiv ℂ e.symm 0‖ ≤ 1 := + Complex.norm_fderiv_le_one_of_mapsTo_ball (ht ▸ he.2) + (fun z hz => by + rw [hinv] + exact ball_subset_closedBall (hs ▸ e.map_target (ht ▸ hz))) zero_lt_one + have hleft : fderiv ℂ e.symm 0 (fderiv ℂ e 0 x) = x := by + simpa [hfix] using DFunLike.congr_fun (he.fderiv_symm_comp hzero) x + apply le_antisymm + · simpa using (fderiv ℂ e 0).le_of_opNorm_le_of_le hd (le_refl ‖x‖) + · calc + ‖x‖ = ‖fderiv ℂ e.symm 0 (fderiv ℂ e 0 x)‖ := congrArg norm hleft.symm + _ ≤ ‖fderiv ℂ e 0 x‖ := by + simpa using (fderiv ℂ e.symm 0).le_of_opNorm_le_of_le hi + (le_refl ‖fderiv ℂ e 0 x‖) + +/-- The Euclidean unit ball and the unit polydisc are not biholomorphic in dimension at least two. +Normalize at zero using a ball automorphism; Schwarz's lemma makes the derivative +norm-preserving, contradicting the parallelogram identity. This proof is independent of Cartan +uniqueness. The dimension hypothesis excludes the singleton and one-variable cases. -/ +theorem not_exists_isBiholomorphic_polydisc_ball {ι : Type*} [Fintype ι] + (hdim : 2 ≤ Fintype.card ι) : + ¬ ∃ e : OpenPartialHomeomorph (ι → ℂ) (EuclideanSpace ℂ ι), + IsBiholomorphic e ∧ e.source = ball 0 1 ∧ e.target = ball 0 1 := by + classical + rintro ⟨e, he, hs, ht⟩ + have hzero : (0 : ι → ℂ) ∈ e.source := by rw [hs]; exact mem_ball_self zero_lt_one + have ha : e 0 ∈ ball 0 1 := ht ▸ e.map_source hzero + let M := ballMobiusOpenPartialHomeomorph (e 0) ha + let g := e.trans M + have hg : IsBiholomorphic g := he.trans (isBiholomorphic_ballMobius (e 0) ha) + have hgs : g.source = ball 0 1 := by + rw [OpenPartialHomeomorph.trans_source] + change e.source ∩ e ⁻¹' ball 0 1 = ball 0 1 + rw [← ht] + exact (inter_eq_left.mpr (fun z hz => e.map_source hz)).trans hs + have hgt : g.target = ball 0 1 := by + rw [OpenPartialHomeomorph.trans_target] + change ball 0 1 ∩ (ballMobius (e 0)) ⁻¹' e.target = ball 0 1 + rw [ht] + exact inter_eq_left.mpr (mapsTo_ballMobius ha) + have hg0 : g 0 = 0 := ballMobius_apply_self (e 0) + let L := fderiv ℂ g 0 + have hL (x : ι → ℂ) : ‖L x‖ = ‖x‖ := + hg.norm_fderiv_apply_eq_of_unit_ball hgs hgt hg0 x + obtain ⟨i, j, hij⟩ := Fintype.one_lt_card_iff.mp (by omega : 1 < Fintype.card ι) + let u : ι → ℂ := Pi.single i 1 + let v : ι → ℂ := Pi.single j 1 + have hu : ‖u‖ = 1 := by simp [u, Pi.norm_single] + have hv : ‖v‖ = 1 := by simp [v, Pi.norm_single] + have hnorm (c : ℂ) (hc : ‖c‖ = 1) : ‖u + c • v‖ = 1 := by + apply le_antisymm + · apply (pi_norm_le_iff_of_nonneg zero_le_one).mpr + intro k + by_cases hki : k = i + · subst k + simp [u, v, hij] + · by_cases hkj : k = j + · subst k + simp [u, v, hij.symm, hc] + · simp [u, v, hki, hkj] + · simpa [u, v, Pi.single_apply, hij] using norm_le_pi_norm (u + c • v) i + have hadd : ‖u + v‖ = 1 := by simpa using hnorm 1 (by simp) + have hsub : ‖u - v‖ = 1 := by simpa [sub_eq_add_neg] using hnorm (-1) (by simp) + have hp := parallelogram_law_with_norm ℂ (L u) (L v) + rw [← map_add, ← map_sub, hL, hL, hL, hL, hu, hv, hadd, hsub] at hp + norm_num at hp + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Biholomorphic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Biholomorphic.lean new file mode 100644 index 0000000000..6abcf9d9b9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Biholomorphic.lean @@ -0,0 +1,297 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.InverseFunctionTheorem.ContDiff +public import Mathlib.Topology.OpenPartialHomeomorph.Composition +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Biholomorphic maps between open sets + +`IsBiholomorphic` adds holomorphy of both maps to Mathlib's `OpenPartialHomeomorph`. The source +and target are already open; connectedness and nonemptiness are not required. The derivative +identities work in complex normed spaces. Equality of dimensions requires a nonempty source. +Local inverse results use finite-dimensional spaces and the existing holomorphic–analytic +equivalence and Mathlib's inverse function theorem. + +Reference: [Range][Range1986] (1986), I §2.4, Theorem 2.5 and Corollary 2.6. The chain rule and +coordinate Jacobian are in `Derivatives`. + +## Main definitions + +* `IsBiholomorphic`: An equivalence between open sets is biholomorphic when both maps are + holomorphic on their respective open domains. +* `affineOpenPartialHomeomorph`: An invertible complex linear map followed by a translation, as an + equivalence of the whole spaces. +* `shearOpenPartialHomeomorph`: A continuous shear has an explicit inverse obtained by subtracting + the same function. + +## Main results + +* `exists_biholomorphic_of_isInvertible_fderiv`: **Holomorphic inverse mapping theorem.** An + invertible complex derivative gives a biholomorphic restriction to an open neighborhood inside the + given open set. +* `exists_open_injOn_of_injective_fderiv`: **[Range][Range1986] I, Corollary 2.6.** An injective + complex derivative gives local injectivity, also when the target has larger dimension. + +## References + +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology ContDiff + +namespace SeveralComplexVariables + +variable {E F G : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [NormedAddCommGroup G] [NormedSpace ℂ G] + +/-- An equivalence between open sets is biholomorphic when both maps are holomorphic on their +respective open domains. No connectedness or nonemptiness is imposed. -/ +@[expose] def IsBiholomorphic (e : OpenPartialHomeomorph E F) : Prop := + DifferentiableOn ℂ e e.source ∧ DifferentiableOn ℂ e.symm e.target + +/-- The inverse of a biholomorphic map is biholomorphic. -/ +theorem IsBiholomorphic.symm {e : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) : + IsBiholomorphic e.symm := ⟨he.2, he.1⟩ + +/-- The identity map of the whole space is biholomorphic. -/ +theorem isBiholomorphic_refl : IsBiholomorphic (OpenPartialHomeomorph.refl E) := + ⟨differentiable_id.differentiableOn, differentiable_id.differentiableOn⟩ + +/-- Compositions of biholomorphic maps are biholomorphic on their natural open source. -/ +theorem IsBiholomorphic.trans {e : OpenPartialHomeomorph E F} + {e' : OpenPartialHomeomorph F G} (he : IsBiholomorphic e) (he' : IsBiholomorphic e') : + IsBiholomorphic (e.trans e') := by + constructor + · exact he'.1.comp (he.1.mono inter_subset_left) (fun _ hx => hx.2) + · exact he.2.comp (he'.2.mono inter_subset_left) (fun _ hx => hx.2) + +/-- Restriction to the intersection of the source with the interior of any set preserves +biholomorphy. For an open set this is ordinary restriction. -/ +theorem IsBiholomorphic.restr {e : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) + (s : Set E) : IsBiholomorphic (e.restr s) := + ⟨he.1.mono inter_subset_left, he.2.mono inter_subset_left⟩ + +/-- A biholomorphic map is complex differentiable at every point of its source. -/ +theorem IsBiholomorphic.differentiableAt {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {a : E} (ha : a ∈ e.source) : DifferentiableAt ℂ e a := + (he.1 a ha).differentiableAt (e.open_source.mem_nhds ha) + +/-- The derivative of the inverse composed with the forward derivative is the identity. -/ +theorem IsBiholomorphic.fderiv_symm_comp {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {a : E} (ha : a ∈ e.source) : + (fderiv ℂ e.symm (e a)).comp (fderiv ℂ e a) = ContinuousLinearMap.id ℂ E := by + rw [← fderiv_comp a (he.symm.differentiableAt (e.map_source ha)) (he.differentiableAt ha)] + have h : (e.symm ∘ e) =ᶠ[𝓝 a] id := e.eventually_left_inverse ha + exact h.fderiv_eq.trans fderiv_id + +/-- The forward derivative composed with the derivative of the inverse is the identity. -/ +theorem IsBiholomorphic.fderiv_comp_symm {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {a : E} (ha : a ∈ e.source) : + (fderiv ℂ e a).comp (fderiv ℂ e.symm (e a)) = ContinuousLinearMap.id ℂ F := by + simpa only [OpenPartialHomeomorph.symm_symm, e.left_inv ha] using + he.symm.fderiv_symm_comp (e.map_source ha) + +/-- The derivative of a biholomorphic map is an invertible continuous complex linear map. -/ +theorem IsBiholomorphic.isInvertible_fderiv {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {a : E} (ha : a ∈ e.source) : + (fderiv ℂ e a).IsInvertible := + .of_inverse (he.fderiv_comp_symm ha) (he.fderiv_symm_comp ha) + +/-- The derivative of the inverse is the inverse of the derivative. -/ +theorem IsBiholomorphic.fderiv_symm {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {a : E} (ha : a ∈ e.source) : + fderiv ℂ e.symm (e a) = (fderiv ℂ e a).inverse := + (ContinuousLinearMap.inverse_eq (he.fderiv_comp_symm ha) (he.fderiv_symm_comp ha)).symm + +/-- Nonempty biholomorphically equivalent open sets have equal ambient complex dimensions. +Nonemptiness is essential: empty sets in different dimensions are equivalent. -/ +theorem IsBiholomorphic.finrank_eq {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) (hne : e.source.Nonempty) : + Module.finrank ℂ E = Module.finrank ℂ F := by + obtain ⟨a, ha⟩ := hne + obtain ⟨L, hL⟩ := he.isInvertible_fderiv ha + exact L.toLinearEquiv.finrank_eq + +/-- Holomorphy of a function on the target is equivalent to holomorphy after a biholomorphic change +of coordinates on the source. -/ +theorem IsBiholomorphic.differentiableOn_comp_iff {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {g : F → G} : + DifferentiableOn ℂ (g ∘ e) e.source ↔ DifferentiableOn ℂ g e.target := by + constructor + · intro h + have hc := h.comp he.2 e.symm.mapsTo + exact hc.congr (fun y hy => congrArg g (e.right_inv hy).symm) + · exact fun h => h.comp he.1 e.mapsTo + +section Inverse + +variable [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +/-- **Holomorphic inverse mapping theorem.** An invertible complex derivative gives +a biholomorphic restriction to an open neighborhood inside the given open set. +The forward representative agrees with the original map everywhere. -/ +theorem exists_biholomorphic_of_isInvertible_fderiv {U : Set E} (hU : IsOpen U) + {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hinv : (fderiv ℂ f a).IsInvertible) : + ∃ e : OpenPartialHomeomorph E F, IsBiholomorphic e ∧ a ∈ e.source ∧ + e.source ⊆ U ∧ (e : E → F) = f := by + let := FiniteDimensional.complete ℂ E + let := FiniteDimensional.complete ℂ F + obtain ⟨L, hL⟩ := hinv + have hfa := hf.analyticOnNhd_of_finiteDimensional hU a ha + have hc : ContDiffAt ℂ ω f a := hfa.contDiffAt + have hd : HasFDerivAt f (L : E →L[ℂ] F) a := by + rw [hL] + exact hfa.differentiableAt.hasFDerivAt + let e := hc.toOpenPartialHomeomorph f hd (by simp) + have hae : a ∈ e.source := hc.mem_toOpenPartialHomeomorph_source hd (by simp) + have hga : AnalyticAt ℂ e.symm (f a) := (hc.to_localInverse hd (by simp)).analyticAt + have hn : U ∩ e ⁻¹' {y | AnalyticAt ℂ e.symm y} ∈ 𝓝 a := + inter_mem (hU.mem_nhds ha) (hfa.continuousAt.preimage_mem_nhds hga.eventually_analyticAt) + obtain ⟨V, hVS, hV, haV⟩ := mem_nhds_iff.mp hn + refine ⟨e.restr V, ?_, ?_, ?_, rfl⟩ + · constructor + · exact hf.mono (fun x hx => (hVS (interior_subset hx.2)).1) + · intro y hy + have h := (hVS (interior_subset hy.2)).2 + change AnalyticAt ℂ e.symm (e (e.symm y)) at h + have hg : AnalyticAt ℂ e.symm y := by simpa only [e.right_inv hy.1] using h + exact hg.differentiableAt.differentiableWithinAt + · exact ⟨hae, hV.interior_eq.symm ▸ haV⟩ + · exact fun x hx => (hVS (interior_subset hx.2)).1 + +/-- A holomorphic map is locally biholomorphic exactly when its derivative is invertible. -/ +theorem isInvertible_fderiv_iff_exists_biholomorphic {U : Set E} (hU : IsOpen U) + {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) : + (fderiv ℂ f a).IsInvertible ↔ + ∃ e : OpenPartialHomeomorph E F, IsBiholomorphic e ∧ a ∈ e.source ∧ + e.source ⊆ U ∧ (e : E → F) = f := by + refine ⟨exists_biholomorphic_of_isInvertible_fderiv hU hf ha, ?_⟩ + rintro ⟨e, he, hae, _, rfl⟩ + exact he.isInvertible_fderiv hae + +/-- **[Range][Range1986] I, Corollary 2.6.** An injective complex derivative gives local +injectivity, +also when the target has larger dimension. No surjectivity assumption is needed. -/ +theorem exists_open_injOn_of_injective_fderiv {U : Set E} (hU : IsOpen U) + {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hi : Function.Injective (fderiv ℂ f a)) : + ∃ V, IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ InjOn f V := by + let A := (fderiv ℂ f a).toLinearMap + obtain ⟨B, hB⟩ := A.exists_leftInverse_of_injective (LinearMap.ker_eq_bot.mpr hi) + let L : F →L[ℂ] E := B.toContinuousLinearMap + have hd : fderiv ℂ (L ∘ f) a = ContinuousLinearMap.id ℂ E := by + rw [fderiv_comp a L.differentiableAt ((hf a ha).differentiableAt (hU.mem_nhds ha)), + L.fderiv] + ext x + exact DFunLike.congr_fun hB x + have hcomp : DifferentiableOn ℂ (L ∘ f) U := L.differentiable.comp_differentiableOn hf + obtain ⟨e, he, hae, hsub, heq⟩ := exists_biholomorphic_of_isInvertible_fderiv hU hcomp ha + (by rw [hd]; exact ⟨ContinuousLinearEquiv.refl ℂ E, rfl⟩) + refine ⟨e.source, e.open_source, hae, hsub, ?_⟩ + intro x hx y hy hxy + apply e.injOn hx hy + rw [heq] + exact congrArg L hxy + +end Inverse + +section Examples + +/-- An invertible complex linear map followed by a translation, as an equivalence of the whole +spaces. -/ +@[expose] def affineOpenPartialHomeomorph (L : E ≃L[ℂ] F) (b : F) : OpenPartialHomeomorph E F := + (L.toHomeomorph.trans (Homeomorph.addRight b)).toOpenPartialHomeomorph + +/-- The forward affine map applies the linear map and then adds the translation. -/ +@[simp] theorem affineOpenPartialHomeomorph_apply (L : E ≃L[ℂ] F) (b : F) (x : E) : + affineOpenPartialHomeomorph L b x = L x + b := rfl + +/-- The inverse affine map first subtracts the translation. -/ +@[simp] theorem affineOpenPartialHomeomorph_symm_apply (L : E ≃L[ℂ] F) (b : F) (y : F) : + (affineOpenPartialHomeomorph L b).symm y = L.symm (y - b) := by + change L.symm (y + -b) = L.symm (y - b) + rw [sub_eq_add_neg] + +/-- Invertible complex affine maps are biholomorphic. -/ +theorem isBiholomorphic_affine (L : E ≃L[ℂ] F) (b : F) : + IsBiholomorphic (affineOpenPartialHomeomorph L b) := by + constructor + · exact (L.differentiable.add_const b).differentiableOn + · exact (L.symm.differentiable.comp (differentiable_id.add_const (-b))).differentiableOn + +/-- A continuous shear has an explicit inverse obtained by subtracting the same function. -/ +@[expose] def shearOpenPartialHomeomorph (h : F → E) (hh : Continuous h) : + OpenPartialHomeomorph (E × F) (E × F) := + ({ toFun := fun p => (p.1 + h p.2, p.2) + invFun := fun p => (p.1 - h p.2, p.2) + left_inv := by intro p; simp + right_inv := by intro p; simp + continuous_toFun := (continuous_fst.add (hh.comp continuous_snd)).prodMk continuous_snd + continuous_invFun := (continuous_fst.sub (hh.comp continuous_snd)).prodMk continuous_snd } : + (E × F) ≃ₜ (E × F)).toOpenPartialHomeomorph + +omit [NormedSpace ℂ E] [NormedSpace ℂ F] in +/-- The forward shear adds a function of the second coordinate to the first. -/ +@[simp] theorem shearOpenPartialHomeomorph_apply (h : F → E) (hh : Continuous h) (p : E × F) : + shearOpenPartialHomeomorph h hh p = (p.1 + h p.2, p.2) := rfl + +omit [NormedSpace ℂ E] [NormedSpace ℂ F] in +/-- The inverse shear subtracts the same function. -/ +@[simp] theorem shearOpenPartialHomeomorph_symm_apply (h : F → E) (hh : Continuous h) + (p : E × F) : (shearOpenPartialHomeomorph h hh).symm p = (p.1 - h p.2, p.2) := rfl + +/-- An entire holomorphic function gives a biholomorphic shear, including nonlinear examples. -/ +theorem isBiholomorphic_shear {h : F → E} (hh : Differentiable ℂ h) : + IsBiholomorphic (shearOpenPartialHomeomorph h hh.continuous) := by + constructor + · exact ((differentiable_fst.add (hh.comp differentiable_snd)).prodMk + differentiable_snd).differentiableOn + · exact ((differentiable_fst.sub (hh.comp differentiable_snd)).prodMk + differentiable_snd).differentiableOn + +end Examples + +section Coordinates + +variable {ι : Type*} [Fintype ι] [DecidableEq ι] + +omit [DecidableEq ι] in +/-- Nonempty biholomorphically equivalent coordinate domains have the same number of complex +coordinates, including the possibility of zero coordinates. -/ +theorem IsBiholomorphic.card_eq {κ : Type*} [Fintype κ] + {e : OpenPartialHomeomorph (ι → ℂ) (κ → ℂ)} (he : IsBiholomorphic e) + (hne : e.source.Nonempty) : Fintype.card ι = Fintype.card κ := by + simpa using he.finrank_eq hne + +/-- The coordinate determinant criterion in [Range][Range1986]'s local inverse theorem. -/ +theorem exists_biholomorphic_of_det_complexJacobian_ne_zero {U : Set (ι → ℂ)} + (hU : IsOpen U) {f : (ι → ℂ) → (ι → ℂ)} (hf : DifferentiableOn ℂ f U) + {a : ι → ℂ} (ha : a ∈ U) (hd : (complexJacobian f a).det ≠ 0) : + ∃ e : OpenPartialHomeomorph (ι → ℂ) (ι → ℂ), IsBiholomorphic e ∧ a ∈ e.source ∧ + e.source ⊆ U ∧ (e : (ι → ℂ) → (ι → ℂ)) = f := + exists_biholomorphic_of_isInvertible_fderiv hU hf ha + ((det_complexJacobian_ne_zero_iff ((hf a ha).differentiableAt (hU.mem_nhds ha))).mp hd) + +/-- A biholomorphic map has nonvanishing complex Jacobian determinant throughout its source. -/ +theorem IsBiholomorphic.det_complexJacobian_ne_zero + {e : OpenPartialHomeomorph (ι → ℂ) (ι → ℂ)} (he : IsBiholomorphic e) + {a : ι → ℂ} (ha : a ∈ e.source) : (complexJacobian e a).det ≠ 0 := + (det_complexJacobian_ne_zero_iff (he.differentiableAt ha)).mpr (he.isInvertible_fderiv ha) + +end Coordinates + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BiholomorphicRigidity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BiholomorphicRigidity.lean new file mode 100644 index 0000000000..6c800f66ff --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/BiholomorphicRigidity.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple + +/-! +# Rigidity of biholomorphic maps + +Equality of first jets and circular-domain linearity follow from Cartan's uniqueness theorem. +The independent analytic step uses Cauchy's derivative formula to show that a +rotation-equivariant holomorphic map is linear. Equality is asserted on the source, not for +arbitrary ambient representatives outside it. Reference: [Scheidemann][Scheidemann2005] (2005), +Section 3.3. + +## Main results + +`IsBiholomorphic.eqOn_of_value_fderiv_eq` is rigidity from equality of 1-jets. +`IsBiholomorphic.exists_linearEquiv_of_circular` is linearity of a biholomorphism of circular +domains fixing the origin. `eqOn_fderiv_of_circle_equivariant` is the analytic step that a +rotation-equivariant holomorphic map is linear. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +omit [FiniteDimensional ℂ F] in +/-- Two biholomorphisms with the same source and target are determined by their value and derivative +at one point of a bounded connected source. Depends on Cartan uniqueness; boundedness of the +target is unnecessary. -/ +theorem IsBiholomorphic.eqOn_of_value_fderiv_eq + {e e' : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) (he' : IsBiholomorphic e') + (hs : e'.source = e.source) (ht : e'.target = e.target) + (hc : IsPreconnected e.source) (hb : Bornology.IsBounded e.source) + {a : E} (ha : a ∈ e.source) (hv : e' a = e a) + (hd : fderiv ℂ e' a = fderiv ℂ e a) : EqOn e' e e.source := by + let := FiniteDimensional.complete ℂ E + have hmem : MapsTo e' e.source e.target := by + intro x hx + rw [← ht] + exact e'.map_source (hs ▸ hx) + have hd' : DifferentiableOn ℂ e' e.source := hs ▸ he'.1 + have hcomp : DifferentiableOn ℂ (e.symm ∘ e') e.source := he.2.comp hd' hmem + have hder : fderiv ℂ (e.symm ∘ e') a = ContinuousLinearMap.id ℂ E := by + rw [fderiv_comp a (he.symm.differentiableAt (hmem ha)) + ((hd' a ha).differentiableAt (e.open_source.mem_nhds ha)), hv, hd] + exact he.fderiv_symm_comp ha + have hid := eqOn_id_of_mapsTo_of_fderiv_eq_id e.open_source hc hb + (hcomp.analyticOnNhd_of_finiteDimensional e.open_source) + (fun x hx => e.symm.map_source (hmem hx)) ha + (by simp [hv, e.left_inv ha]) hder + intro x hx + have h := congrArg e (hid hx) + simpa only [Function.comp_apply, e.right_inv (hmem hx), id_eq] using h + +omit [FiniteDimensional ℂ F] in +/-- A holomorphic map commuting with complex rotations agrees with its derivative at zero on a +preconnected neighborhood of zero. Cauchy's derivative formula on scalar slices proves local +equality, and the identity theorem propagates it. -/ +theorem eqOn_fderiv_of_circle_equivariant [CompleteSpace F] {U : Set E} (ho : IsOpen U) + (hc : IsPreconnected U) (hzero : (0 : E) ∈ U) {f : E → F} + (hf : DifferentiableOn ℂ f U) + (hrot : ∀ z ∈ U, ∀ c : ℂ, ‖c‖ = 1 → f (c • z) = c • f z) : + EqOn f (fderiv ℂ f 0) U := by + obtain ⟨r, hr, hsub⟩ := Metric.mem_nhds_iff.mp (ho.mem_nhds hzero) + apply hf.eqOn_of_preconnected_of_eqOn ho hc (fderiv ℂ f 0).differentiable.differentiableOn + isOpen_ball ⟨0, mem_ball_self hr⟩ hsub + intro z hz + have hcz (c : ℂ) (hc : c ∈ closedBall 0 1) : c • z ∈ U := by + apply hsub + rw [mem_ball, dist_zero_right] at hz ⊢ + rw [mem_closedBall, dist_zero_right] at hc + exact (norm_smul c z).le.trans_lt + ((mul_le_mul_of_nonneg_right hc (norm_nonneg z)).trans_lt (by simpa using hz)) + have hd : DifferentiableOn ℂ (fun c : ℂ => f (c • z)) (closedBall 0 1) := by + intro c hc + exact ((hf (c • z) (hcz c hc)).differentiableAt + (ho.mem_nhds (hcz c hc))).comp c (differentiableAt_id.smul_const z) + |>.differentiableWithinAt + have hd' : DifferentiableOn ℂ (fun c : ℂ => c • f z) (closedBall 0 1) := + (differentiable_id.smul_const (f z)).differentiableOn + have heq := circleIntegral.integral_congr (c := 0) (show (0 : ℝ) ≤ 1 by norm_num) + (f := fun c : ℂ => (1 / (c - 0) ^ 2) • f (c • z)) + (g := fun c : ℂ => (1 / (c - 0) ^ 2) • (c • f z)) + (fun c hc => by dsimp only; rw [hrot z (hsub hz) c (by simpa using hc)]) + rw [hd.deriv_eq_smul_circleIntegral (by norm_num), + hd'.deriv_eq_smul_circleIntegral (by norm_num)] at heq + have hdf : HasDerivAt (fun c : ℂ => f (c • z)) (fderiv ℂ f 0 z) 0 := by + have hpre : HasFDerivAt f (fderiv ℂ f 0) ((0 : ℂ) • z) := by + simpa using ((hf 0 hzero).differentiableAt (ho.mem_nhds hzero)).hasFDerivAt + simpa [Function.comp_def] using hpre.comp_hasDerivAt 0 ((hasDerivAt_id (0 : ℂ)).smul_const z) + have hlin : HasDerivAt (fun c : ℂ => c • f z) (f z) 0 := by + simpa using (hasDerivAt_id (0 : ℂ)).smul_const (f z) + rw [hdf.deriv, hlin.deriv] at heq + exact (smul_right_injective F Complex.two_pi_I_ne_zero heq).symm + +omit [FiniteDimensional ℂ F] in +/-- Origin-preserving biholomorphisms of circular domains commute with rotations. This follows from +Cartan uniqueness on the bounded source; boundedness of the target is unnecessary. -/ +theorem IsBiholomorphic.map_smul_of_circular + {e : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) + (hc : IsPreconnected e.source) (hb : Bornology.IsBounded e.source) + (hrot : IsCircular e.source) (hrot' : IsCircular e.target) + (hzero : (0 : E) ∈ e.source) (hfix : e 0 = 0) + {z : E} (hz : z ∈ e.source) {c : ℂ} (hc1 : ‖c‖ = 1) : + e (c • z) = c • e z := by + let := FiniteDimensional.complete ℂ E + have hcn : c ≠ 0 := norm_ne_zero_iff.mp (by rw [hc1]; norm_num) + have hci : ‖c⁻¹‖ = 1 := by simp [hc1] + have hi0 : e.symm 0 = 0 := by simpa [hfix] using e.left_inv hzero + let g : E → E := fun x => e.symm (c⁻¹ • e (c • x)) + have hmem : MapsTo (fun x => c⁻¹ • e (c • x)) e.source e.target := + fun x hx => hrot'.smul_mem (e.map_source (hrot.smul_mem hx hc1)) hci + have hdiff : DifferentiableOn ℂ g e.source := + he.2.comp ((he.1.comp (differentiable_id.const_smul c).differentiableOn + (fun x hx => hrot.smul_mem hx hc1)).const_smul c⁻¹) hmem + have hinner : HasFDerivAt (fun x => c⁻¹ • e (c • x)) (fderiv ℂ e 0) 0 := by + have hd : HasFDerivAt e (fderiv ℂ e 0) (c • (0 : E)) := by + simpa using (he.differentiableAt hzero).hasFDerivAt + convert (hd.comp 0 ((hasFDerivAt_id (𝕜 := ℂ) (0 : E)).const_smul c)).const_smul c⁻¹ using 1 + · simp only [Function.comp_def, Pi.smul_def] + · ext x + simp [hcn] + have hd : HasFDerivAt g (ContinuousLinearMap.id ℂ E) 0 := by + have hinv : HasFDerivAt e.symm (fderiv ℂ e.symm (e 0)) (c⁻¹ • e (c • (0 : E))) := by + simpa [hfix] using (he.symm.differentiableAt (e.map_source hzero)).hasFDerivAt + simpa [g, Function.comp_def, he.fderiv_symm_comp hzero] using hinv.comp 0 hinner + have hid := eqOn_id_of_mapsTo_of_fderiv_eq_id e.open_source hc hb + (hdiff.analyticOnNhd_of_finiteDimensional e.open_source) + (fun x hx => e.symm.map_source (hmem hx)) hzero + (by simp [g, hfix, hi0]) hd.fderiv + have heq : c⁻¹ • e (c • z) = e z := by + simpa only [g, e.right_inv (hmem hz), id_eq] using congrArg e (hid hz) + simpa [hcn] using congrArg (fun y : F => c • y) heq + +/-- An origin-preserving biholomorphism between circular domains with bounded source agrees with an +invertible complex-linear map. Cartan uniqueness gives rotation equivariance, and Cauchy's +derivative formula eliminates the nonlinear terms. Zero-dimensional spaces are included; +membership of zero supplies nonemptiness. -/ +theorem IsBiholomorphic.exists_linearEquiv_of_circular + {e : OpenPartialHomeomorph E F} (he : IsBiholomorphic e) + (hc : IsPreconnected e.source) (hb : Bornology.IsBounded e.source) + (hrot : IsCircular e.source) + (hrot' : IsCircular e.target) (hzero : (0 : E) ∈ e.source) (hfix : e 0 = 0) : + ∃ L : E ≃L[ℂ] F, EqOn e L e.source := by + let := FiniteDimensional.complete ℂ F + obtain ⟨L, hL⟩ := he.isInvertible_fderiv hzero + refine ⟨L, ?_⟩ + have h := eqOn_fderiv_of_circle_equivariant e.open_source hc hzero he.1 + (fun z hz c hc1 => he.map_smul_of_circular hc hb hrot hrot' hzero hfix hz hc1) + intro x hx + change e x = L.toContinuousLinearMap x + rw [hL] + exact h hx + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanThullen.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanThullen.lean new file mode 100644 index 0000000000..e2ea867aa1 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanThullen.lean @@ -0,0 +1,289 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Connected.LocallyConnected +public import Mathlib.Topology.Sequences +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen + +/-! +# The Cartan–Thullen characterizations + +The core equivalences relate holomorphic convexity, obstruction to common local continuation, a +single function's domain of existence, and hull boundary distance. The function-theoretic +equivalences apply to open subsets of arbitrary finite-dimensional complex normed spaces; the +numerical hull-radius forms use coordinate sup norms. Connectedness is not required. They +include the empty set, the whole space, and dimension zero. + +Thullen's Taylor continuation lemma gives the forward implication. For the converse, a countable +basis of balls and overlap components supplies escaping sequences that detect every local +continuation patch. Baire's theorem gives one holomorphic function unbounded on all these +sequences. This proves the full equivalences, including for disconnected open sets. + +References: [Range][Range1986] II §3.6; [Fritzsche–Grauert][FritzscheGrauert2002] II §§5–6; +[Scheidemann][Scheidemann2005] §7.3; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] §2.7; +[Hörmander][Hormander1973] §2.5. + +## Main results + +`isDomainOfHolomorphy_iff_isHolomorphicallyConvex` is the Cartan–Thullen equivalence. +`isDomainOfHolomorphy_iff_exists_domainOfExistence` produces a single completely nonextendable +function. `isDomainOfHolomorphy_iff_hasHolomorphicHullDistanceProperty` and +`isDomainOfHolomorphy_iff_hasHolomorphicHullRadiusProperty` are the hull-radius forms. +`isHolomorphicallyConvex_of_convex` is the convex example. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +section General +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} + +/-- Finite-dimensional source spaces are proper. -/ +local instance : ProperSpace E := FiniteDimensional.proper ℂ E + +/-- Finite-dimensional source spaces have countable bases. -/ +local instance : SecondCountableTopology E := + (Module.finBasis ℂ E).equivFunL.toHomeomorph.secondCountableTopology + +omit [FiniteDimensional ℂ E] in +/-- A component of the overlap with a connected larger open set approaches the boundary of the +original set inside the larger set. -/ +private theorem exists_boundary_point_of_component (ho : IsOpen U) + {V : Set E} (hV : IsOpen V) (hc : IsPreconnected V) + {x : E} (hx : x ∈ U ∩ V) (hn : ¬ V ⊆ U) : + ∃ a ∈ V, a ∉ U ∧ a ∈ closure (connectedComponentIn (U ∩ V) x) := by + let C := connectedComponentIn (U ∩ V) x + have hC : IsOpen C := (ho.inter hV).connectedComponentIn + have hxC : x ∈ C := mem_connectedComponentIn hx + have hCF : C ⊆ U ∩ V := connectedComponentIn_subset _ _ + have hrel {a : E} (ha : a ∈ closure C) (haF : a ∈ U ∩ V) : a ∈ C := by + have hconn : IsPreconnected (insert a C) := + isPreconnected_connectedComponentIn.subset_closure (subset_insert _ _) + (insert_subset ha subset_closure) + exact (hconn.subset_connectedComponentIn (mem_insert_of_mem _ hxC) + (insert_subset haF hCF)) (mem_insert _ _) + by_contra! h + apply hn + apply subset_trans (hc.subset_of_closure_inter_subset hC ⟨x, hx.2, hxC⟩ ?_) + (hCF.trans inter_subset_left) + rintro a ⟨haC, haV⟩ + exact hrel haC ⟨by by_contra haU; exact h a haV haU haC, haV⟩ + +/-- There is a countable basis of nonempty open balls in a finite coordinate space. -/ +private theorem exists_countable_ball_basis (E : Type*) [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] : + ∃ b : Set (Set E), b.Countable ∧ TopologicalSpace.IsTopologicalBasis b ∧ + ∀ B ∈ b, ∃ c r, 0 < r ∧ B = ball c r := by + let T : Set (Set E) := {B | ∃ c r, 0 < r ∧ B = ball c r} + have hT : TopologicalSpace.IsTopologicalBasis T := by + apply TopologicalSpace.isTopologicalBasis_of_isOpen_of_nhds + · rintro _ ⟨c, r, hr, rfl⟩; exact isOpen_ball + · intro x N hx hN + obtain ⟨r, hr, hsub⟩ := Metric.mem_nhds_iff.mp (hN.mem_nhds hx) + exact ⟨ball x r, ⟨x, r, hr, rfl⟩, mem_ball_self hr, hsub⟩ + obtain ⟨b, hbT, hbc, hb⟩ := hT.exists_countable + exact ⟨b, hbc, hb, hbT⟩ + +/-- One holomorphic function is unbounded on every member of a countable family of escaping +sequences. Baire's theorem combines the individual obstructions. -/ +private theorem exists_unbounded_on_sequences {I : Type*} [Countable I] + (hU : IsHolomorphicallyConvex U) (ho : IsOpen U) + (p : I → ℕ → E) (hp : ∀ i j, p i j ∈ U) + (he : ∀ i, EscapesCompactSubsets U (p i)) : + ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ + ∀ i, ¬ BddAbove (range (fun j => ‖f (p i j)‖)) := by + classical + let V : TopologicalSpace.Opens E := ⟨U, ho⟩ + let : LocallyCompactSpace V := ho.locallyCompactSpace + have : (uniformity C(V, ℂ)).IsCountablyGenerated := inferInstance + have : (uniformity (HolomorphicMap V ℂ)).IsCountablyGenerated := + Filter.comap.isCountablyGenerated _ _ + have : TopologicalSpace.IsCompletelyPseudoMetrizableSpace (HolomorphicMap V ℂ) := + .of_completeSpace_pseudometrizable + let : BaireSpace (HolomorphicMap V ℂ) := BaireSpace.of_completelyPseudoMetrizable + let A (q : I × ℕ) : Set (HolomorphicMap V ℂ) := + {f | ∀ j, ‖f.val ⟨p q.1 j, hp q.1 j⟩‖ ≤ q.2} + have hclosed (q : I × ℕ) : IsClosed (A q) := by + simp only [A, ofPred_forall] + exact isClosed_iInter fun j => isClosed_le + (continuous_holomorphicMap_eval V ⟨p q.1 j, hp q.1 j⟩).norm continuous_const + have hempty (q : I × ℕ) : interior (A q) = ∅ := by + apply eq_empty_iff_forall_notMem.mpr + intro g hg + have hgA := interior_subset hg + obtain ⟨h, hh, hno⟩ := + (isHolomorphicallyConvex_iff_unbounded_on_escaping_sequences ho).mp hU + (p q.1) (hp q.1) (he q.1) + let H : HolomorphicMap V ℂ := ⟨⟨fun z => h z, hh.continuousOn.domRestrict⟩, + hh.congr ho (fun z hz => by rw [openExtension_apply V _ hz]; rfl)⟩ + let c (k : ℕ) : ℂ := 1 / ((k : ℂ) + 1) + have hlim : Tendsto (fun k => g + c k • H) atTop (𝓝 g) := by + simpa [c] using (tendsto_const_nhds (x := g)).add + ((tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℂ)).smul_const H) + obtain ⟨k, hk⟩ := (hlim.eventually (mem_interior_iff_mem_nhds.mp hg)).exists + have hc : 0 < ‖c k‖ := by + apply norm_pos_iff.mpr + apply one_div_ne_zero + exact_mod_cast Nat.succ_ne_zero k + apply hno + refine ⟨2 * (q.2 : ℝ) / ‖c k‖, ?_⟩ + rintro _ ⟨j, rfl⟩ + apply (le_div_iff₀ hc).mpr + have hnorm := norm_sub_le ((g + c k • H).val ⟨p q.1 j, hp q.1 j⟩) + (g.val ⟨p q.1 j, hp q.1 j⟩) + change ‖g.val ⟨p q.1 j, hp q.1 j⟩ + c k * h (p q.1 j) - + g.val ⟨p q.1 j, hp q.1 j⟩‖ ≤ _ at hnorm + rw [add_sub_cancel_left, norm_mul] at hnorm + nlinarith [hk j, hgA j] + have hdense := dense_iInter_of_isOpen (fun q => (hclosed q).isOpen_compl) + (fun q => interior_eq_empty_iff_dense_compl.mp (hempty q)) + obtain ⟨f, hf⟩ := hdense.nonempty + refine ⟨openExtension V f.val, f.property, ?_⟩ + intro i hbound + obtain ⟨M, hM⟩ := hbound + obtain ⟨N, hN⟩ := exists_nat_ge M + apply (mem_iInter.mp hf (i, N)) + intro j + have h := (hM (mem_range_self j)).trans hN + simpa only [openExtension_apply V _ (hp i j)] using h + +/-- **Existence of a completely nonextendable function.** Baire's theorem gives one +function unbounded on a countable family of escaping sequences that detects every +local continuation patch. Disconnected open sets are allowed. -/ +theorem IsHolomorphicallyConvex.exists_domainOfExistence + (hU : IsHolomorphicallyConvex U) (ho : IsOpen U) : + ∃ f : E → ℂ, IsDomainOfExistence U f := by + classical + obtain ⟨b, hbc, hb, hballs⟩ := exists_countable_ball_basis E + have : Countable b := hbc.to_subtype + have hne (B : b) : B.val.Nonempty := by + obtain ⟨c, r, hr, hB⟩ := hballs B.val B.property + exact ⟨c, hB ▸ mem_ball_self hr⟩ + let I := {q : b × b // q.2.val ⊆ U ∩ q.1.val ∧ ¬ q.1.val ⊆ U} + let x (q : I) := (hne q.val.2).some + let C (q : I) := connectedComponentIn (U ∩ q.val.1.val) (x q) + have hx (q : I) : x q ∈ U ∩ q.val.1.val := q.property.1 (hne q.val.2).some_mem + have hseq (q : I) : ∃ p : ℕ → E, + (∀ j, p j ∈ C q) ∧ EscapesCompactSubsets U p := by + obtain ⟨c, r, hr, hB⟩ := hballs q.val.1.val q.val.1.property + have hc : IsPreconnected q.val.1.val := hB ▸ (convex_ball c r).isPreconnected + obtain ⟨a, _, haU, haC⟩ := exists_boundary_point_of_component ho + (hb.isOpen q.val.1.property) hc (hx q) q.property.2 + obtain ⟨p, hp, ht⟩ := mem_closure_iff_seq_limit.mp haC + refine ⟨p, hp, ?_⟩ + intro K hK hKU + exact ht.eventually (hK.isClosed.isOpen_compl.mem_nhds (fun haK => haU (hKU haK))) + choose p hp he using hseq + have hpU (q : I) (j : ℕ) : p q j ∈ U := + (connectedComponentIn_subset _ _ (hp q j)).1 + obtain ⟨f, hf, hno⟩ := exists_unbounded_on_sequences hU ho p hpU he + refine ⟨f, hf, ?_⟩ + intro V W hV hc hW hWne hWU hWV hext + by_contra hnot + obtain ⟨g, hg, hgf⟩ := hext + obtain ⟨w, hw⟩ := hWne + let D := connectedComponentIn (U ∩ V) w + have hDo : IsOpen D := (ho.inter hV).connectedComponentIn + have hwD : w ∈ D := mem_connectedComponentIn ⟨hWU hw, hWV hw⟩ + have hDsub : D ⊆ U ∩ V := connectedComponentIn_subset _ _ + have heqD : EqOn g f D := + (hg.mono (hDsub.trans inter_subset_right)).eqOn_of_preconnected_of_eventuallyEq + (hf.mono (hDsub.trans inter_subset_left)) isPreconnected_connectedComponentIn hwD + (Filter.mem_of_superset (hW.mem_nhds hw) hgf) + obtain ⟨a, haV, haU, haD⟩ := exists_boundary_point_of_component ho hV hc.isPreconnected + ⟨hWU hw, hWV hw⟩ hnot + obtain ⟨r, hr, hrV⟩ := Metric.nhds_basis_closedBall.mem_iff.mp (hV.mem_nhds haV) + obtain ⟨B, hBb, haB, hBr⟩ := hb.exists_subset_of_mem_open (mem_ball_self hr) isOpen_ball + have hBcl : closure B ⊆ closedBall a r := + (closure_mono hBr).trans closure_ball_subset_closedBall + have hBV : closure B ⊆ V := hBcl.trans hrV + have hBK : IsCompact (closure B) := + (isCompact_closedBall a r).of_isClosed_subset isClosed_closure hBcl + obtain ⟨z, hzB, hzD⟩ := _root_.mem_closure_iff.mp haD B (hb.isOpen hBb) haB + obtain ⟨A, hAb, hzA, hAsub⟩ := hb.exists_subset_of_mem_open + (show z ∈ B ∩ D from ⟨hzB, hzD⟩) ((hb.isOpen hBb).inter hDo) + let q : I := ⟨(⟨B, hBb⟩, ⟨A, hAb⟩), + fun z hz => ⟨(hDsub (hAsub hz).2).1, (hAsub hz).1⟩, + fun h => haU (h haB)⟩ + have hxD : x q ∈ D := (hAsub (hne q.val.2).some_mem).2 + have hCsub : C q ⊆ U ∩ B := connectedComponentIn_subset _ _ + have hCV : C q ⊆ V := hCsub.trans (inter_subset_right.trans (subset_closure.trans hBV)) + have heqC : EqOn g f (C q) := + (hg.mono hCV).eqOn_of_preconnected_of_eventuallyEq + (hf.mono (hCsub.trans inter_subset_left)) isPreconnected_connectedComponentIn + (mem_connectedComponentIn (hx q)) + (Filter.mem_of_superset (hDo.mem_nhds hxD) heqD) + obtain ⟨M, hM⟩ := hBK.bddAbove_image (hg.continuousOn.mono hBV).norm + apply hno q + refine ⟨M, ?_⟩ + rintro _ ⟨j, rfl⟩ + change ‖f (p q j)‖ ≤ M + rw [← heqC (hp q j)] + exact hM ⟨p q j, subset_closure (hCsub (hp q j)).2, rfl⟩ + +/-- **Cartan–Thullen, reverse implication.** A single completely nonextendable +function obstructs common local continuation beyond the open set. -/ +theorem IsHolomorphicallyConvex.isDomainOfHolomorphy + (hU : IsHolomorphicallyConvex U) (ho : IsOpen U) : IsDomainOfHolomorphy U := by + obtain ⟨f, hf⟩ := hU.exists_domainOfExistence ho + exact hf.isDomainOfHolomorphy + +/-- **Cartan–Thullen.** Holomorphic convexity is equivalent to the domain-of-holomorphy +property. The reverse implication uses a completely nonextendable function. -/ +theorem isDomainOfHolomorphy_iff_isHolomorphicallyConvex (ho : IsOpen U) : + IsDomainOfHolomorphy U ↔ IsHolomorphicallyConvex U := + ⟨fun h => h.isHolomorphicallyConvex ho, fun h => h.isDomainOfHolomorphy ho⟩ + +/-- A domain of holomorphy is the domain of existence of a single scalar function. The converse +follows from the obstruction to common local continuation. -/ +theorem isDomainOfHolomorphy_iff_exists_domainOfExistence (ho : IsOpen U) : + IsDomainOfHolomorphy U ↔ ∃ f : E → ℂ, IsDomainOfExistence U f := + ⟨fun h => (h.isHolomorphicallyConvex ho).exists_domainOfExistence ho, + fun ⟨_, hf⟩ => hf.isDomainOfHolomorphy⟩ + +/-- Convex open subsets of finite-dimensional complex normed spaces are holomorphically convex. +This deduction uses the separating-hyperplane example and Thullen's lemma. -/ +theorem isHolomorphicallyConvex_of_convex (hU : Convex ℝ U) (ho : IsOpen U) : + IsHolomorphicallyConvex U := (isDomainOfHolomorphy_of_convex hU ho).isHolomorphicallyConvex ho + +end General + +variable {n : ℕ} {U : Set (Fin n → ℂ)} + +/-- Exact preservation of compact hull boundary distance characterizes domains of holomorphy, by the +equivalence with holomorphic convexity. -/ +theorem isDomainOfHolomorphy_iff_hasHolomorphicHullDistanceProperty (ho : IsOpen U) : + IsDomainOfHolomorphy U ↔ HasHolomorphicHullDistanceProperty U := + ⟨fun h => h.hasHolomorphicHullDistanceProperty ho, + fun h => (h.isHolomorphicallyConvex ho).isDomainOfHolomorphy ho⟩ + +/-- The uniform polydisc-radius formulation is another Cartan–Thullen characterization. -/ +theorem isDomainOfHolomorphy_iff_hasHolomorphicHullRadiusProperty (ho : IsOpen U) : + IsDomainOfHolomorphy U ↔ HasHolomorphicHullRadiusProperty U := + ⟨fun h => h.hasHolomorphicHullRadiusProperty ho, + fun h => (h.isHolomorphicallyConvex ho).isDomainOfHolomorphy ho⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanUniqueness.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanUniqueness.lean new file mode 100644 index 0000000000..6ee5218ce6 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CartanUniqueness.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Group.Bounded +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel + +/-! +# Cartan uniqueness on bounded domains + +The theorem in this file concerns holomorphic self-maps of bounded finite-dimensional domains. +It is Cartan's uniqueness theorem from [Scheidemann][Scheidemann2005] (2005), Theorem 3.3.1, +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 2.3.2, and [Lebl][Lebl2026] (2026), +Section 1.5. It is independent of sheaves and of Cartan's theorems A and B. + +The proof averages the bounded iterates and uses Montel's theorem to extract a locally uniform +limit. Derivative convergence gives identity derivative at the fixed point. Telescoping gives +invariance of the limit under the original map, so local injectivity and the identity principle +force the original map to be the identity. + +## Main results + +`eqOn_id_of_mapsTo_of_fderiv_eq_id` is Cartan's uniqueness theorem: a holomorphic self-map of a +bounded domain which fixes a point and has identity derivative there is the identity on the +connected component of that point. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [J. Lebl, *Tasty Bits of Several Complex Variables: A Whirlwind Tour of the Subject*][Lebl2026] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +/-- **Cartan's uniqueness theorem.** A holomorphic self-map of a bounded connected open set +that fixes an interior point and has identity derivative there is the identity on the set. +Boundedness is essential; no injectivity or surjectivity of the map is assumed. +The formulation includes zero-dimensional domains. -/ +theorem eqOn_id_of_mapsTo_of_fderiv_eq_id + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) (hb : Bornology.IsBounded U) + {f : E → E} (hf : AnalyticOnNhd ℂ f U) (hmaps : MapsTo f U U) + {a : E} (ha : a ∈ U) (hfix : f a = a) + (hderiv : fderiv ℂ f a = ContinuousLinearMap.id ℂ E) : EqOn f id U := by + classical + let : CompleteSpace E := FiniteDimensional.complete ℂ E + obtain ⟨M, hM0, hM⟩ := hb.exists_pos_norm_le + let A (n : ℕ) (z : E) : E := ((n + 1 : ℕ) : ℂ)⁻¹ • + ∑ k ∈ Finset.range (n + 1), f^[k] z + have hA (n : ℕ) : AnalyticOnNhd ℂ (A n) U := + ((DifferentiableOn.fun_sum (fun k _ => hf.differentiableOn.iterate hmaps k)).const_smul + ((n + 1 : ℕ) : ℂ)⁻¹).analyticOnNhd_of_finiteDimensional hU + have hAb (n : ℕ) (z : E) (hz : z ∈ U) : ‖A n z‖ ≤ M := by + have hn : (0 : ℝ) < n + 1 := by positivity + calc + ‖A n z‖ = ((n : ℝ) + 1)⁻¹ * ‖∑ k ∈ Finset.range (n + 1), f^[k] z‖ := by + dsimp only [A] + rw [norm_smul, norm_inv, norm_natCast, Nat.cast_add, Nat.cast_one] + _ ≤ ((n : ℝ) + 1)⁻¹ * (((n : ℝ) + 1) * M) := by + apply mul_le_mul_of_nonneg_left _ (inv_nonneg.mpr hn.le) + calc + _ ≤ ∑ k ∈ Finset.range (n + 1), ‖f^[k] z‖ := norm_sum_le _ _ + _ ≤ ∑ _k ∈ Finset.range (n + 1), M := + Finset.sum_le_sum fun k _ => hM _ (hmaps.iterate k hz) + _ = _ := by simp + _ = M := by field_simp + have hfd : HasFDerivAt f (ContinuousLinearMap.id ℂ E) a := by + rw [← hderiv] + exact (hf a ha).differentiableAt.hasFDerivAt + have hAd (n : ℕ) : fderiv ℂ (A n) a = ContinuousLinearMap.id ℂ E := by + have hk (k : ℕ) : HasFDerivAt f^[k] (ContinuousLinearMap.id ℂ E) a := by + simpa only [← ContinuousLinearMap.one_def, one_pow] using hfd.iterate hfix k + have H := (HasFDerivAt.fun_sum (u := Finset.range (n + 1)) (fun k _ => hk k)).const_smul + ((n + 1 : ℕ) : ℂ)⁻¹ + have hn : ((n + 1 : ℕ) : ℂ) ≠ 0 := by exact_mod_cast Nat.succ_ne_zero n + simpa only [A, Finset.sum_const, Finset.card_range, ← Nat.cast_smul_eq_nsmul ℂ, + smul_smul, inv_mul_cancel₀ hn, one_smul, Pi.smul_def] using H.fderiv + obtain ⟨g, φ, hφ, hg, hlim⟩ := + exists_subseq_tendstoLocallyUniformlyOn_of_uniform_bound hU hA hAb + have hgd : fderiv ℂ g a = ContinuousLinearMap.id ℂ E := by + have H := (hlim.fderiv_of_finiteDimensional (.of_forall fun n => hA (φ n)) hU).tendsto_at ha + simp only [hAd] at H + exact tendsto_nhds_unique H tendsto_const_nhds + have htel (n : ℕ) (z : E) : A n (f z) - A n z = + ((n + 1 : ℕ) : ℂ)⁻¹ • (f^[n + 1] z - z) := by + dsimp only [A] + rw [← smul_sub, ← Finset.sum_sub_distrib] + congr 1 + simpa only [Function.iterate_succ_apply, Function.iterate_zero_apply] using + (Finset.sum_range_sub (fun k => f^[k] z) (n + 1)) + have hzero (z : E) (hz : z ∈ U) : + Tendsto (fun n => A n (f z) - A n z) atTop (𝓝 0) := by + apply squeeze_zero_norm (fun n => ?_) + (show Tendsto (fun n : ℕ => ((n : ℝ) + 1)⁻¹ * (2 * M)) atTop (𝓝 0) by + simpa only [one_div, zero_mul] using + (tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℝ)).mul_const (2 * M)) + rw [htel, norm_smul, norm_inv, norm_natCast, Nat.cast_add, Nat.cast_one] + apply mul_le_mul_of_nonneg_left _ (by positivity) + exact (norm_sub_le _ _).trans (by linarith [hM _ (hmaps.iterate (n + 1) hz), hM z hz]) + have hgf (z : E) (hz : z ∈ U) : g (f z) = g z := by + have H := (hlim.tendsto_at (hmaps hz)).sub (hlim.tendsto_at hz) + exact sub_eq_zero.mp (tendsto_nhds_unique H ((hzero z hz).comp hφ.tendsto_atTop)) + obtain ⟨V, hV, haV, _, hinj⟩ := exists_open_injOn_of_injective_fderiv hU hg.differentiableOn ha + (by rw [hgd]; exact Function.injective_id) + have heq : f =ᶠ[𝓝 a] id := by + have hpre : f ⁻¹' V ∈ 𝓝 a := (hf a ha).continuousAt.preimage_mem_nhds + (hV.mem_nhds (by simpa only [hfix] using haV)) + filter_upwards [hU.mem_nhds ha, hV.mem_nhds haV, hpre] with z hz hzV hfzV + exact hinj hfzV hzV (hgf z hz) + exact hf.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_id hconn ha heq + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyCoefficients.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyCoefficients.lean new file mode 100644 index 0000000000..b7edfa7eb9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyCoefficients.lean @@ -0,0 +1,327 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral + +/-! +# Mixed Cauchy coefficients + +Higher Cauchy kernels on polydiscs with separate radii. Differentiating the evaluation point +raises the corresponding kernel exponent; the integration contour remains fixed. This identifies +every mixed derivative with the multi-index factorial times its Cauchy coefficient, proves +independence from the contour radii, and yields the sharp mixed-derivative Cauchy estimate. +`PolydiscTaylor` uses these coefficients for convergent Taylor expansions. + +## Main definitions + +* `cauchyKernel`: The higher Cauchy kernel of multi-index `m`. +* `polydiscCauchyTransform`: The higher Cauchy transform with a fixed contour and variable + evaluation point. +* `polydiscCauchyCoeffWithRadii`: Multi-index Cauchy coefficients for a polydisc with separate + radii. + +## Main results + +* `multiIndexDeriv_eq_factorial_smul_cauchyCoeff`: Mixed derivatives at the center are multi-index + factorials times the Cauchy coefficients. +* `polydiscCauchyCoeffWithRadii_eq_of_radii`: Changing the positive contour radii does not change + the Cauchy coefficients. +* `norm_multiIndexDeriv_le`: Cauchy's estimate for every mixed derivative, with the usual + multi-index factorial and a separate radius in each coordinate. +-/ + +public noncomputable section + +open Complex Filter Function MeasureTheory Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {d : ℕ} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- The higher Cauchy kernel of multi-index `m`. -/ +@[expose] def cauchyKernel (m : Fin d → ℕ) (w z : Fin d → ℂ) : ℂ := + ∏ i, (z i - w i)⁻¹ ^ (m i + 1) + +/-- The higher Cauchy transform with a fixed contour and variable + evaluation point. -/ +@[expose] def polydiscCauchyTransform (f : (Fin d → ℂ) → E) (c : Fin d → ℂ) (R : Fin d → ℝ) + (m : Fin d → ℕ) (w : Fin d → ℂ) : E := + ((2 * π * I : ℂ) ^ d)⁻¹ • torusIntegral (fun z => cauchyKernel m w z • f z) c R + +/-- Multi-index Cauchy coefficients for a polydisc with separate radii. -/ +@[expose] def polydiscCauchyCoeffWithRadii (f : (Fin d → ℂ) → E) (c : Fin d → ℂ) + (R : Fin d → ℝ) (m : Fin d → ℕ) : E := polydiscCauchyTransform f c R m c + +/-- Separate-radius coefficients recover the original equal-radius coefficients. -/ +theorem polydiscCauchyCoeffWithRadii_const (f : (Fin d → ℂ) → E) (c : Fin d → ℂ) + (R : ℝ) (m : Fin d → ℕ) : + polydiscCauchyCoeffWithRadii f c (fun _ => R) m = polydiscCauchyCoeff f c R m := rfl + +/-- Updating the pole in coordinate `i` isolates that factor of the Cauchy kernel. -/ +theorem cauchyKernel_update (m : Fin d → ℕ) (w z : Fin d → ℂ) (i : Fin d) (v : ℂ) : + cauchyKernel m (update w i v) z = + (∏ j ∈ Finset.univ.erase i, (z j - w j)⁻¹ ^ (m j + 1)) * + (z i - v)⁻¹ ^ (m i + 1) := by + rw [cauchyKernel, ← Finset.prod_erase_mul _ _ (Finset.mem_univ i)] + congr 1 + · apply Finset.prod_congr rfl + intro j hj + rw [update_of_ne (Finset.ne_of_mem_erase hj)] + · simp + +/-- Differentiating in coordinate `i` raises that kernel exponent by one. -/ +theorem hasDerivAt_cauchyKernel_update (m : Fin d → ℕ) (w z : Fin d → ℂ) + (i : Fin d) (v : ℂ) (hz : z i - v ≠ 0) : + HasDerivAt (fun a => cauchyKernel m (update w i a) z) + ((m i + 1 : ℂ) * cauchyKernel (update m i (m i + 1)) (update w i v) z) v := by + have hprod : (∏ j ∈ Finset.univ.erase i, (z j - w j)⁻¹ ^ (update m i (m i + 1) j + 1)) = + ∏ j ∈ Finset.univ.erase i, (z j - w j)⁻¹ ^ (m j + 1) := by + apply Finset.prod_congr rfl + intro j hj + rw [update_of_ne (Finset.ne_of_mem_erase hj)] + simp_rw [cauchyKernel_update] + convert! ((((hasDerivAt_id v).const_sub (z i)).inv hz).pow (m i + 1)).const_mul + (∏ j ∈ Finset.univ.erase i, (z j - w j)⁻¹ ^ (m j + 1)) using 1 + rw [hprod] + simp [pow_succ, div_eq_mul_inv] + ring + +/-- Cauchy's multi-index coefficient estimate with one radius for each coordinate. -/ +theorem norm_polydiscCauchyCoeffWithRadii_le {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) (m : Fin d → ℕ) : + ‖polydiscCauchyCoeffWithRadii f c R m‖ ≤ M * ∏ i, (R i)⁻¹ ^ m i := by + have hker (θ : Fin d → ℝ) : ‖cauchyKernel m c (torusMap c R θ)‖ = + ∏ i, (R i)⁻¹ ^ (m i + 1) := by + simp only [cauchyKernel, norm_prod, norm_pow, norm_inv, + norm_torusMap_sub (fun i => (hR i).le)] + rw [polydiscCauchyCoeffWithRadii, polydiscCauchyTransform, norm_smul] + refine (mul_le_mul_of_nonneg_left (norm_torusIntegral_le_of_norm_le_const + (C := M * ∏ i, (R i)⁻¹ ^ (m i + 1)) ?_) (norm_nonneg _)).trans_eq ?_ + · intro θ + rw [norm_smul, hker] + exact (mul_le_mul_of_nonneg_left + (hM _ (torusMap_mem_closedPolydisc (fun i => (hR i).le) θ)) + (Finset.prod_nonneg fun i _ => pow_nonneg (inv_nonneg.mpr (hR i).le) _)).trans_eq + (mul_comm _ _) + · simp only [norm_inv, norm_pow, norm_mul, norm_ofNat, norm_real, norm_I, mul_one, + Real.norm_eq_abs, abs_of_pos Real.pi_pos, abs_of_pos (hR _)] + have hp : (∏ i, R i) * (∏ i, (R i)⁻¹ ^ (m i + 1)) = ∏ i, (R i)⁻¹ ^ m i := by + rw [← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i hi + rw [pow_succ] + field_simp [(hR i).ne'] + calc + ((2 * π) ^ d)⁻¹ * (((2 * π) ^ d * ∏ i, R i) * (M * ∏ i, (R i)⁻¹ ^ (m i + 1))) = + M * ((∏ i, R i) * ∏ i, (R i)⁻¹ ^ (m i + 1)) := by + field_simp + _ = _ := by rw [hp] + +variable [CompleteSpace E] + +/-- Higher Cauchy kernels are jointly continuous in the interior evaluation point and the contour +parameter. -/ +theorem continuousOn_cauchyKernel_torus {c : Fin d → ℂ} {R : Fin d → ℝ} + (hR : ∀ i, 0 < R i) (m : Fin d → ℕ) : + ContinuousOn (fun p : (Fin d → ℂ) × (Fin d → ℝ) => + cauchyKernel m p.1 (torusMap c R p.2)) (polydisc c R ×ˢ univ) := by + apply continuousOn_finsetProd + intro i hi + apply ContinuousOn.pow + apply ContinuousOn.inv₀ + · exact ((((continuous_apply i).comp (continuous_torusMap c R)).comp + continuous_snd).sub ((continuous_apply i).comp continuous_fst)).continuousOn + · intro p hp + exact sub_ne_zero.mpr (torusMap_apply_ne_of_norm_sub_lt hR + (by simpa [dist_eq_norm] using mem_polydisc.mp hp.1 i)) + +omit [CompleteSpace E] in +/-- Coordinate differentiation under the fixed-contour higher Cauchy integral. -/ +theorem hasDerivAt_polydiscCauchyTransform_update {f : (Fin d → ℂ) → E} + {c w : Fin d → ℂ} {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hw : w ∈ polydisc c R) (m : Fin d → ℕ) (i : Fin d) : + HasDerivAt (fun a => polydiscCauchyTransform f c R m (update w i a)) + ((m i + 1 : ℂ) • polydiscCauchyTransform f c R (update m i (m i + 1)) w) (w i) := by + let V : Set ℂ := (update w i) ⁻¹' polydisc c R + let K : Set (Fin d → ℝ) := Icc 0 (fun _ => 2 * π) + let J (θ : Fin d → ℝ) : ℂ := ∏ j, R j * exp (θ j * I) * I + let G (a : ℂ) (θ : Fin d → ℝ) := + J θ • cauchyKernel m (update w i a) (torusMap c R θ) • f (torusMap c R θ) + let G' (a : ℂ) (θ : Fin d → ℝ) := + (m i + 1 : ℂ) • J θ • cauchyKernel (update m i (m i + 1)) + (update w i a) (torusMap c R θ) • f (torusMap c R θ) + have hV : IsOpen V := (isOpen_polydisc c R).preimage + (continuous_const.update i continuous_id) + have hwi : w i ∈ V := by simpa [V] using hw + have hu : Continuous (fun p : ℂ × (Fin d → ℝ) => update w i p.1) := + (show Continuous (fun _ : ℂ × (Fin d → ℝ) => w) from continuous_const).update i continuous_fst + have hker (k : Fin d → ℕ) : ContinuousOn + (fun p : ℂ × (Fin d → ℝ) => cauchyKernel k (update w i p.1) (torusMap c R p.2)) + (V ×ˢ K) := by + apply continuousOn_finsetProd + intro j hj + apply ContinuousOn.pow + apply ContinuousOn.inv₀ + · exact ((((continuous_apply j).comp (continuous_torusMap c R)).comp continuous_snd).sub + ((continuous_apply j).comp hu)).continuousOn + · intro p hp + exact sub_ne_zero.mpr (torusMap_apply_ne_of_norm_sub_lt hR + (by simpa [dist_eq_norm] using mem_polydisc.mp hp.1 j)) + have hfun : ContinuousOn (fun p : ℂ × (Fin d → ℝ) => f (torusMap c R p.2)) (V ×ˢ K) := + hfc.comp ((continuous_torusMap c R).comp continuous_snd).continuousOn + (fun p _ => torusMap_mem_closedPolydisc (fun j => (hR j).le) p.2) + have hJ : Continuous (fun p : ℂ × (Fin d → ℝ) => J p.2) := by dsimp [J]; fun_prop + have hG : ContinuousOn (fun p : ℂ × (Fin d → ℝ) => G p.1 p.2) (V ×ˢ K) := + hJ.continuousOn.smul ((hker m).smul hfun) + have hG' : ContinuousOn (fun p : ℂ × (Fin d → ℝ) => G' p.1 p.2) (V ×ˢ K) := + continuousOn_const.smul (hJ.continuousOn.smul ((hker _).smul hfun)) + have hd : ∀ a ∈ V, ∀ θ ∈ K, HasDerivAt (fun b => G b θ) (G' a θ) a := by + intro a ha θ hθ + have hp : torusMap c R θ i - a ≠ 0 := by + have H := sub_ne_zero.mpr (torusMap_apply_ne_of_norm_sub_lt + (c := c) (θ := θ) (i := i) (w := update w i a) hR + (by simpa [dist_eq_norm] using mem_polydisc.mp ha i)) + simpa using H + simpa only [G, G', Pi.smul_def, smul_smul, mul_assoc, mul_left_comm] using! + ((hasDerivAt_cauchyKernel_update m w (torusMap c R θ) i a hp).smul_const + (f (torusMap c R θ))).const_smul (J θ) + have H := (hasDerivAt_integral_of_continuousOn_compact (μ := volume) + (show IsCompact K from isCompact_Icc) hV hwi hG hG' hd).const_smul + (((2 * π * I : ℂ) ^ d)⁻¹) + have hval : (∫ θ in K, G' (w i) θ) = (m i + 1 : ℂ) • + torusIntegral (fun z => cauchyKernel (update m i (m i + 1)) w z • f z) c R := by + simp only [G', update_eq_self] + rw [integral_smul] + rfl + rw [hval, smul_comm (((2 * π * I : ℂ) ^ d)⁻¹) (m i + 1 : ℂ)] at H + simpa only [polydiscCauchyTransform, torusIntegral, G, K, J, Pi.smul_def] using! H + +/-- The zeroth Cauchy transform equals the original function in the open polydisc. -/ +theorem polydiscCauchyTransform_zero_eq {f : (Fin d → ℂ) → E} {c w : Fin d → ℂ} {R : Fin d → ℝ} + (hR : ∀ i, 0 < R i) (hw : w ∈ polydisc c R) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) : + polydiscCauchyTransform f c R 0 w = f w := by + simpa [polydiscCauchyTransform, cauchyKernel] using + two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul + hR + (fun i => by simpa [dist_eq_norm] using mem_polydisc.mp hw i) hfc hfa + +/-- Prepending an index to a list increments its count there and fixes the other counts. -/ +private theorem count_cons_eq_update (is : List (Fin d)) (i : Fin d) : + (fun j => (i :: is).count j) = update (fun j => is.count j) i (is.count i + 1) := by + funext j + by_cases hji : j = i + · subst j; simp + · simp [hji, Ne.symm hji] + +/-- The product of factorials of the counts after prepending an index. -/ +private theorem prod_factorial_count_cons (is : List (Fin d)) (i : Fin d) : + (∏ j, (((i :: is).count j).factorial : ℂ)) = + (∏ j, ((is.count j).factorial : ℂ)) * (is.count i + 1 : ℂ) := by + calc + (∏ j, (((i :: is).count j).factorial : ℂ)) = + ∏ j, (if j = i then (is.count i + 1 : ℂ) else 1) * ((is.count j).factorial : ℂ) := by + apply Finset.prod_congr rfl + intro j hj + by_cases hji : j = i + · subst j; simp [Nat.factorial_succ] + · simp [hji, Ne.symm hji] + _ = _ := by rw [Finset.prod_mul_distrib]; simp [mul_comm] + +omit [CompleteSpace E] in +/-- Repeated coordinate differentiation of the zeroth Cauchy transform yields factorials times the +corresponding higher Cauchy transform. -/ +theorem iteratedPartialDeriv_polydiscCauchyTransform_zero {f : (Fin d → ℂ) → E} + {c w : Fin d → ℂ} {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hw : w ∈ polydisc c R) (is : List (Fin d)) : + iteratedPartialDeriv is (polydiscCauchyTransform f c R 0) w = + (∏ j, ((is.count j).factorial : ℂ)) • + polydiscCauchyTransform f c R (fun j => is.count j) w := by + induction is generalizing w with + | nil => simp [iteratedPartialDeriv, Pi.zero_def] + | cons i is ih => + change partialDeriv i (iteratedPartialDeriv is (polydiscCauchyTransform f c R 0)) w = _ + have heq : partialDeriv i (iteratedPartialDeriv is (polydiscCauchyTransform f c R 0)) w = + partialDeriv i (fun v => (∏ j, ((is.count j).factorial : ℂ)) • + polydiscCauchyTransform f c R (fun j => is.count j) v) w := by + apply partialDeriv_congr + filter_upwards [(isOpen_polydisc c R).eventually_mem hw] with v hv + exact ih hv + rw [heq, partialDeriv] + have H := + (hasDerivAt_polydiscCauchyTransform_update hR hfc hw (fun j => is.count j) i).const_smul + (∏ j, ((is.count j).factorial : ℂ)) + have HD := H.deriv + simp only [Pi.smul_def, smul_smul] at HD + rw [prod_factorial_count_cons, count_cons_eq_update] + convert! HD using 1 + +/-- Mixed derivatives at the center are multi-index factorials times the Cauchy coefficients. -/ +theorem multiIndexDeriv_eq_factorial_smul_cauchyCoeff {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) (m : Fin d → ℕ) : + multiIndexDeriv m f c = (∏ i, (m i).factorial : ℂ) • polydiscCauchyCoeffWithRadii f c R m := by + have hc : c ∈ polydisc c R := mem_polydisc.mpr (by simpa using hR) + have hcongr := iteratedPartialDeriv_congrOn (isOpen_polydisc c R) + (fun z hz => (polydiscCauchyTransform_zero_eq hR hz hfc hfa).symm) (multiIndexList m) hc + rw [multiIndexDeriv, hcongr, iteratedPartialDeriv_polydiscCauchyTransform_zero hR hfc hc] + simp only [count_multiIndexList, polydiscCauchyCoeffWithRadii] + +/-- Cauchy coefficients are the mixed Taylor coefficients, independent of a contour choice. -/ +theorem polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) (m : Fin d → ℕ) : + polydiscCauchyCoeffWithRadii f c R m = + (∏ i, (m i).factorial : ℂ)⁻¹ • multiIndexDeriv m f c := by + rw [multiIndexDeriv_eq_factorial_smul_cauchyCoeff hR hfc hfa m, smul_smul, + inv_mul_cancel₀ (Finset.prod_ne_zero_iff.mpr (fun i _ => + Nat.cast_ne_zero.mpr (m i).factorial_ne_zero)), one_smul] + +/-- Changing the positive contour radii does not change the Cauchy coefficients. -/ +theorem polydiscCauchyCoeffWithRadii_eq_of_radii {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R S : Fin d → ℝ} (hR : ∀ i, 0 < R i) (hS : ∀ i, 0 < S i) + (hfcR : ContinuousOn f (closedPolydisc c R)) + (hfaR : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hfcS : ContinuousOn f (closedPolydisc c S)) + (hfaS : ∀ z ∈ closedPolydisc c S, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) (m : Fin d → ℕ) : + polydiscCauchyCoeffWithRadii f c R m = polydiscCauchyCoeffWithRadii f c S m := by + rw [polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hR hfcR hfaR, + polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hS hfcS hfaS] + +/-- Cauchy's estimate for every mixed derivative, with the usual multi-index factorial and a +separate radius in each coordinate. -/ +theorem norm_multiIndexDeriv_le {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} + {R : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) (m : Fin d → ℕ) : + ‖multiIndexDeriv m f c‖ ≤ (∏ i, ((m i).factorial : ℝ)) * (M * ∏ i, (R i)⁻¹ ^ m i) := by + rw [multiIndexDeriv_eq_factorial_smul_cauchyCoeff hR hfc hfa, norm_smul] + simpa only [norm_prod, norm_natCast] using + mul_le_mul_of_nonneg_left (norm_polydiscCauchyCoeffWithRadii_le hR hM m) + (norm_nonneg (∏ i, ((m i).factorial : ℂ))) + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyDerivatives.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyDerivatives.lean new file mode 100644 index 0000000000..111c9f0226 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyDerivatives.lean @@ -0,0 +1,138 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.Deriv.ZPow +public import Mathlib.Analysis.Complex.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral + +/-! +# Cauchy's derivative formula at an arbitrary point of a disk + +Mathlib's higher-derivative circle formula is stated at the center. Here the evaluation point +may be anywhere in the open disk. Differentiating the contour kernel with respect to that point +preserves the hypothesis of continuity on the boundary: no boundary derivatives of the function +are required. + +These Banach-valued, one-variable results also support iterated Cauchy formulas in several +variables. The circle center and evaluation point are independent, and the derivative order is +arbitrary. The statements use Mathlib's `HasDerivAt`, `iteratedDeriv`, `DiffContOnCl`, and +circle-integral interfaces rather than introducing a separate contour or derivative theory. +Their intended Mathlib home is `Analysis.Complex.CauchyIntegral`. + +## Main results + +* `hasDerivAt_circleIntegral_sub_zpow_smul`: Differentiation in the evaluation point raises the + order of the circle Cauchy kernel. +* `DiffContOnCl.iteratedDeriv_eq_circleIntegral_sub_zpow_smul`: Cauchy's formula for every + derivative at any point inside the circle. +* `hasDerivAt_circleIntegral_sub_zpow_mul`: Differentiation in the evaluation point raises the order + of the circle Cauchy kernel. +* `DiffContOnCl.iteratedDeriv_eq_circleIntegral_sub_zpow_mul`: Cauchy's formula for every derivative + at any point inside the circle. +-/ + +open Complex MeasureTheory Metric Filter Set +open scoped Topology + +public noncomputable section + +section Banach +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Differentiation in the evaluation point raises the order of the circle Cauchy kernel. -/ +theorem hasDerivAt_circleIntegral_sub_zpow_smul + {c w : ℂ} {R : ℝ} (hR : 0 ≤ R) (hw : w ∈ ball c R) + {f : ℂ → E} (hf : ContinuousOn f (sphere c R)) (n : ℕ) : + HasDerivAt (fun w => ∮ s in C(c, R), (s - w) ^ (-(n + 1 : ℤ)) • f s) + (((n : ℂ) + 1) • ∮ s in C(c, R), (s - w) ^ (-((n + 1 : ℕ) + 1 : ℤ)) • f s) w := by + have hkernel (k : ℕ) : ContinuousOn (fun p : ℂ × ℝ => + (circleMap c R p.2 - p.1) ^ (-(k + 1 : ℤ))) + (ball c R ×ˢ Icc 0 (2 * Real.pi)) := by + exact (((continuous_circleMap c R).comp continuous_snd).sub continuous_fst).continuousOn.zpow₀ _ + (fun p hp => Or.inl (sub_ne_zero.mpr (circleMap_ne_mem_ball hp.1 p.2))) + have hcircle : ContinuousOn (fun p : ℂ × ℝ => deriv (circleMap c R) p.2) + (ball c R ×ˢ Icc 0 (2 * Real.pi)) := by + simp only [deriv_circleMap] + fun_prop + have hfun : ContinuousOn (fun p : ℂ × ℝ => f (circleMap c R p.2)) + (ball c R ×ˢ Icc 0 (2 * Real.pi)) := + hf.comp ((continuous_circleMap c R).comp continuous_snd).continuousOn + (fun p _ => circleMap_mem_sphere c hR p.2) + have h := hasDerivAt_integral_of_continuousOn_compact + (μ := volume) (K := Icc 0 (2 * Real.pi)) + (F := fun w θ => deriv (circleMap c R) θ • + ((circleMap c R θ - w) ^ (-(n + 1 : ℤ)) • f (circleMap c R θ))) + (F' := fun w θ => ((n : ℂ) + 1) • (deriv (circleMap c R) θ • + ((circleMap c R θ - w) ^ (-((n + 1 : ℕ) + 1 : ℤ)) • f (circleMap c R θ)))) + isCompact_Icc isOpen_ball hw + (hcircle.smul ((hkernel n).smul hfun)) + (continuousOn_const.smul (hcircle.smul ((hkernel (n + 1)).smul hfun))) ?_ + · simpa only [circleIntegral_def_Icc, integral_smul] using h + intro x hx θ _ + have hd := (hasDerivAt_zpow (-(n + 1 : ℤ)) (circleMap c R θ - x) + (Or.inl (sub_ne_zero.mpr (circleMap_ne_mem_ball hx θ)))).comp x + ((hasDerivAt_id x).const_sub (circleMap c R θ)) + have hexp : -(n + 1 : ℤ) - 1 = -((n + 1 : ℕ) + 1 : ℤ) := by omega + have hd' : HasDerivAt (fun w => (circleMap c R θ - w) ^ (-(n + 1 : ℤ))) + (((n : ℂ) + 1) * (circleMap c R θ - x) ^ (-((n + 1 : ℕ) + 1 : ℤ))) x := by + simpa only [Function.comp_def, id_eq, hexp, Int.cast_neg, Int.cast_add, + Int.cast_natCast, Int.cast_one, mul_neg_one, neg_mul, neg_neg] using hd + convert (hd'.smul_const (f (circleMap c R θ))).const_smul (deriv (circleMap c R) θ) using 1 + simp only [smul_smul] + congr 1 + ring + +variable [CompleteSpace E] + +/-- Cauchy's formula for every derivative at any point inside the circle. The function need only be +holomorphic in the open disk and continuous on its closure. -/ +theorem DiffContOnCl.iteratedDeriv_eq_circleIntegral_sub_zpow_smul + {c : ℂ} {R : ℝ} {f : ℂ → E} (hf : DiffContOnCl ℂ f (ball c R)) + (hR : 0 < R) (n : ℕ) {w : ℂ} (hw : w ∈ ball c R) : + iteratedDeriv n f w = ((n.factorial : ℂ) * (2 * (Real.pi : ℂ) * I)⁻¹) • + ∮ s in C(c, R), (s - w) ^ (-(n + 1 : ℤ)) • f s := by + induction n generalizing w with + | zero => + simpa using + (hf.two_pi_i_inv_smul_circleIntegral_sub_inv_smul hw).symm + | succ n ih => + have heq : (iteratedDeriv n f) =ᶠ[nhds w] + (fun w => ((n.factorial : ℂ) * (2 * (Real.pi : ℂ) * I)⁻¹) • + ∮ s in C(c, R), (s - w) ^ (-(n + 1 : ℤ)) • f s) := by + filter_upwards [isOpen_ball.mem_nhds hw] with v hv + exact ih hv + rw [iteratedDeriv_succ, heq.deriv_eq] + have hd := ((hasDerivAt_circleIntegral_sub_zpow_smul hR.le hw + (hf.continuousOn_ball.mono sphere_subset_closedBall) n).const_smul + ((n.factorial : ℂ) * (2 * (Real.pi : ℂ) * I)⁻¹)).deriv + apply hd.trans + simp only [Nat.factorial_succ, Nat.cast_mul, Nat.cast_add, Nat.cast_one, smul_smul] + congr 1 + ring + +end Banach + +/-- Differentiation in the evaluation point raises the order of the circle Cauchy kernel. -/ +theorem hasDerivAt_circleIntegral_sub_zpow_mul + {c w : ℂ} {R : ℝ} (hR : 0 ≤ R) (hw : w ∈ ball c R) + {f : ℂ → ℂ} (hf : ContinuousOn f (sphere c R)) (n : ℕ) : + HasDerivAt (fun w => ∮ s in C(c, R), (s - w) ^ (-(n + 1 : ℤ)) * f s) + (((n : ℂ) + 1) * ∮ s in C(c, R), (s - w) ^ (-((n + 1 : ℕ) + 1 : ℤ)) * f s) w := by + simpa only [smul_eq_mul] using hasDerivAt_circleIntegral_sub_zpow_smul hR hw hf n + +/-- Cauchy's formula for every derivative at any point inside the circle. The function need only be +holomorphic in the open disk and continuous on its closure. -/ +theorem DiffContOnCl.iteratedDeriv_eq_circleIntegral_sub_zpow_mul + {c : ℂ} {R : ℝ} {f : ℂ → ℂ} (hf : DiffContOnCl ℂ f (ball c R)) + (hR : 0 < R) (n : ℕ) {w : ℂ} (hw : w ∈ ball c R) : + iteratedDeriv n f w = (n.factorial : ℂ) * (2 * (Real.pi : ℂ) * I)⁻¹ * + ∮ s in C(c, R), (s - w) ^ (-(n + 1 : ℤ)) * f s := by + simpa only [smul_eq_mul] using hf.iteratedDeriv_eq_circleIntegral_sub_zpow_smul hR n hw + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyEstimates.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyEstimates.lean new file mode 100644 index 0000000000..e4787fee99 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyEstimates.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Liouville +public import Mathlib.Topology.MetricSpace.Thickening +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Cauchy estimates and local derivative bounds + +These estimates reuse the one-variable Cauchy estimate on coordinate slices. The source has the +supremum norm, so a coordinate disc fits in the ball of the same radius. Derivatives are also +uniformly bounded on small closed thickenings of compact subsets of a one-variable holomorphic +domain. + +## Main results + +`norm_partialDeriv_le` is the Cauchy estimate for a coordinate derivative on a polydisc. +`norm_partialDeriv_le_of_slice` is the one-variable slice form. +`AnalyticOnNhd.exists_cthickening_deriv_bound` bounds derivatives uniformly on a closed +thickening of a compact subset of a one-variable domain. +-/ + +public section + +open Complex Function Metric Set + +/-- The derivative of a holomorphic function is uniformly bounded on a sufficiently small closed +thickening of any compact subset of its open domain. -/ +theorem AnalyticOnNhd.exists_cthickening_deriv_bound + {Ω K : Set ℂ} {f : ℂ → ℂ} (hf : AnalyticOnNhd ℂ f Ω) + (hΩopen : IsOpen Ω) (hK : IsCompact K) (hKΩ : K ⊆ Ω) : + ∃ δ : ℝ, 0 < δ ∧ Metric.cthickening δ K ⊆ Ω ∧ + ∃ C : ℝ, 0 ≤ C ∧ ∀ w ∈ Metric.cthickening δ K, ‖deriv f w‖ ≤ C := by + obtain ⟨δ₁, hδ₁, hδ₁compact⟩ := hK.exists_isCompact_cthickening + obtain ⟨δ₂, hδ₂, hδ₂Ω⟩ := hK.exists_cthickening_subset_open hΩopen hKΩ + let δ := min δ₁ δ₂ + have hcompact : IsCompact (Metric.cthickening δ K) := + hδ₁compact.of_isClosed_subset Metric.isClosed_cthickening + (Metric.cthickening_mono (min_le_left _ _) K) + have hsub : Metric.cthickening δ K ⊆ Ω := + (Metric.cthickening_mono (min_le_right _ _) K).trans hδ₂Ω + obtain ⟨C, hC⟩ := hcompact.bddAbove_image (hf.deriv.continuousOn.mono hsub).norm + exact ⟨δ, lt_min hδ₁ hδ₂, hsub, max C 0, le_max_right _ _, + fun w hw => (hC (Set.mem_image_of_mem _ hw)).trans (le_max_left _ _)⟩ + +namespace SeveralComplexVariables + +variable {ι F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Updating one coordinate within its closed disc stays in the corresponding sup-norm ball. -/ +theorem update_mem_closedBall {z : ι → ℂ} {i : ι} {w : ℂ} {r : ℝ} + (hr : 0 ≤ r) (hw : w ∈ closedBall (z i) r) : update z i w ∈ closedBall z r := by + rw [mem_closedBall, dist_pi_le_iff hr] + intro j + by_cases hji : j = i + · simpa [hji] using hw + · simpa [Function.update_of_ne hji] using hr + +omit [Fintype ι] in +/-- Cauchy's first derivative bound only needs holomorphy along the chosen coordinate disc. -/ +theorem norm_partialDeriv_le_of_slice {f : (ι → ℂ) → F} {z : ι → ℂ} + (i : ι) {r M : ℝ} (hr : 0 < r) + (hf : DifferentiableOn ℂ (fun w => f (update z i w)) (closedBall (z i) r)) + (hM : ∀ w ∈ sphere (z i) r, ‖f (update z i w)‖ ≤ M) : + ‖partialDeriv i f z‖ ≤ M / r := + Complex.norm_deriv_le_of_forall_mem_sphere_norm_le hr + (hf.diffContOnCl_ball Subset.rfl) hM + +/-- A bound on a closed sup-norm ball controls every coordinate derivative at its center. -/ +theorem norm_partialDeriv_le {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) {z : ι → ℂ} (i : ι) {r M : ℝ} (hr : 0 < r) + (hball : closedBall z r ⊆ U) (hM : ∀ w ∈ closedBall z r, ‖f w‖ ≤ M) : + ‖partialDeriv i f z‖ ≤ M / r := by + apply norm_partialDeriv_le_of_slice i hr + · intro w hw + exact ((hf _ (hball (update_mem_closedBall hr.le hw))).differentiableAt.comp w + (hasDerivAt_update z i w).differentiableAt).differentiableWithinAt + · intro w hw + exact hM _ (update_mem_closedBall hr.le (sphere_subset_closedBall hw)) + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyIntegral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyIntegral.lean new file mode 100644 index 0000000000..37b7bcb084 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyIntegral.lean @@ -0,0 +1,204 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc + +/-! +# Cauchy's integral formula on a polydisc + +The vector-valued iterated Cauchy formula assumes continuity and coordinatewise analyticity on +the closed polydisc. It does not depend on the several-variable Osgood theorem. The +distinguished boundary is the coordinate torus of the closed polydisc `closedPolydisc`. + +## Main results + +`two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul` is the iterated formula with a separate +radius in each coordinate; `two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul_const` is the +equal-radius specialization. `torusIntegrable_cauchyKernelWithRadii` records integrability of the +Cauchy kernel on that torus whenever the evaluation point lies in the open polydisc. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped ENNReal NNReal Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-! +### Cauchy's formula on a polydisc +-/ + +omit [CompleteSpace E] in +/-- The vector-valued Cauchy kernel of a continuous function is integrable on a torus whenever the +evaluation point lies in the interior polydisc. -/ +theorem torusIntegrable_cauchyKernelWithRadii {n : ℕ} {f : (Fin n → ℂ) → E} {c w : Fin n → ℂ} {R : + Fin n → ℝ} + (hR : ∀ i, 0 < R i) (hw : ∀ i, ‖w i - c i‖ < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) : + TorusIntegrable (fun z => (∏ i, (z i - w i)⁻¹) • f z) c R := by + have hmaps : MapsTo (torusMap c R) + (Icc (0 : Fin n → ℝ) fun _ => 2 * π) (closedPolydisc c R) := + fun θ _ => torusMap_mem_closedPolydisc (fun i => (hR i).le) θ + have hfθ : ContinuousOn (fun θ => f (torusMap c R θ)) + (Icc (0 : Fin n → ℝ) fun _ => 2 * π) := + hfc.comp (continuous_torusMap c R).continuousOn hmaps + have hker : ContinuousOn + (fun θ : Fin n → ℝ => (∏ i, (torusMap c R θ i - w i)⁻¹)) + (Icc (0 : Fin n → ℝ) fun _ => 2 * π) := by + refine continuousOn_finsetProd _ fun i _ => ?_ + refine ((((continuous_apply i).comp (continuous_torusMap c R)).continuousOn).sub + continuousOn_const).inv₀ ?_ + intro θ _ + exact sub_ne_zero.2 (torusMap_apply_ne_of_norm_sub_lt hR (hw i)) + exact (hker.smul hfθ).integrableOn_compact isCompact_Icc + +/-- Splitting off the first coordinate factors the finite-product Cauchy kernel. -/ +theorem cauchyKernel_cons {n : ℕ} (x : ℂ) (y : Fin n → ℂ) (w : Fin (n + 1) → ℂ) : + (∏ i, ((Fin.cons x y : Fin (n + 1) → ℂ) i - w i)⁻¹) = + (x - w 0)⁻¹ * ∏ i, (y i - w i.succ)⁻¹ := by + simp [Fin.prod_univ_succ, mul_comm] + +/-- The one-variable Cauchy formula along the first-coordinate slice of a closed polydisc. All other +coordinates are fixed at the evaluation point. -/ +private theorem circleIntegral_cauchyKernel_cons {n : ℕ} + {f : (Fin (n + 1) → ℂ) → E} {c w : Fin (n + 1) → ℂ} {R : Fin (n + 1) → ℝ} + (hw : ∀ i, ‖w i - c i‖ < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + (2 * π * I : ℂ)⁻¹ • + (∮ x in C(c 0, R 0), (x - w 0)⁻¹ • f (Fin.cons x (w ∘ Fin.succ))) = + f (Fin.cons (w 0) (w ∘ Fin.succ)) := by + have hcons : Continuous (fun x : ℂ => (Fin.cons x (w ∘ Fin.succ) : Fin (n + 1) → ℂ)) := + Continuous.finCons (A := fun _ : Fin (n + 1) => ℂ) continuous_id continuous_const + have hψcont : ContinuousOn (fun x => f (Fin.cons x (w ∘ Fin.succ))) + (closedBall (c 0) (R 0)) := + hfc.comp hcons.continuousOn fun x hx => + cons_mem_closedPolydisc hx (fun i _ => + mem_closedBall.2 (le_of_lt (by simpa [dist_eq_norm] using hw i.succ))) + have hψdiff : ∀ x ∈ ball (c 0) (R 0), + DifferentiableAt ℂ (fun t => f (Fin.cons t (w ∘ Fin.succ))) x := by + intro x hx + have hz : Fin.cons x (w ∘ Fin.succ) ∈ closedPolydisc c R := + cons_mem_closedPolydisc (ball_subset_closedBall hx) fun i _ => + mem_closedBall.2 (le_of_lt (by simpa [dist_eq_norm] using hw i.succ)) + simpa [Fin.update_cons_zero] using (hfa _ hz 0).differentiableAt + have hcircle : + ((2 * π * I : ℂ)⁻¹ • + ∮ x in C(c 0, R 0), (x - w 0)⁻¹ • f (Fin.cons x (w ∘ Fin.succ))) = + f (Fin.cons (w 0) (w ∘ Fin.succ)) := by + have hw0 : w 0 ∈ ball (c 0) (R 0) := by simpa [dist_eq_norm] using hw 0 + simpa using + two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable + (s := (∅ : Set ℂ)) countable_empty hw0 hψcont fun x hx => hψdiff x hx.1 + exact hcircle + +/-- Iterated Cauchy integral formula on a closed polydisc. -/ +theorem two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul {n : ℕ} {f : (Fin n → ℂ) → E} + {c w : Fin n → ℂ} {R : Fin n → ℝ} + (hR : ∀ i, 0 < R i) (hw : ∀ i, ‖w i - c i‖ < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + ((2 * π * I : ℂ) ^ n)⁻¹ • + torusIntegral (fun z => (∏ i, (z i - w i)⁻¹) • f z) c R = f w := by + induction n with + | zero => + have : w = c := Subsingleton.elim _ _ + subst this + simp [torusIntegral_dim0] + | succ n ih => + set F : (Fin (n + 1) → ℂ) → E := + fun z => (∏ i, (z i - w i)⁻¹) • f z + have hFint : TorusIntegrable F c R := + torusIntegrable_cauchyKernelWithRadii hR hw hfc + have hinter : ∀ x ∈ sphere (c 0) (R 0), + torusIntegral (fun y => F (Fin.cons x y)) (c ∘ Fin.succ) (R ∘ Fin.succ) = + (x - w 0)⁻¹ • ((2 * π * I : ℂ) ^ n • + f (Fin.cons x (w ∘ Fin.succ))) := by + intro x hx + have hxcl := sphere_subset_closedBall hx + have hgcont : ContinuousOn (fun y => f (Fin.cons x y)) + (closedPolydisc (c ∘ Fin.succ) (R ∘ Fin.succ)) := + hfc.comp (continuousOn_const.finCons continuousOn_id) + (fun y hy => cons_mem_closedPolydisc hxcl hy) + have hga : ∀ y ∈ closedPolydisc (c ∘ Fin.succ) (R ∘ Fin.succ), ∀ j, + AnalyticAt ℂ (fun t => f (Fin.cons x (update y j t))) (y j) := by + intro y hy j + have hz := cons_mem_closedPolydisc hxcl hy + simpa [Fin.cons_update] using hfa (Fin.cons x y) hz j.succ + have hw' : ∀ i : Fin n, ‖w i.succ - c i.succ‖ < R i.succ := fun i => hw i.succ + have ih' := + ih (f := fun y => f (Fin.cons x y)) (c := c ∘ Fin.succ) (w := w ∘ Fin.succ) + (fun i => hR i.succ) hw' hgcont hga + have ih_int : + torusIntegral (fun y => (∏ i, (y i - w i.succ)⁻¹) • f (Fin.cons x y)) + (c ∘ Fin.succ) (R ∘ Fin.succ) = + (2 * π * I : ℂ) ^ n • f (Fin.cons x (w ∘ Fin.succ)) := + ((eq_inv_smul_iff₀ (two_pi_I_pow_ne_zero n)).mp ih'.symm).symm + have hsmul := torusIntegral_smul (x - w 0)⁻¹ + (fun y => (∏ i, (y i - w i.succ)⁻¹) • f (Fin.cons x y)) + (c ∘ Fin.succ) (R ∘ Fin.succ) + calc + torusIntegral (fun y => F (Fin.cons x y)) (c ∘ Fin.succ) (R ∘ Fin.succ) + = torusIntegral (fun y => (x - w 0)⁻¹ • + (∏ i, (y i - w i.succ)⁻¹) • f (Fin.cons x y)) + (c ∘ Fin.succ) (R ∘ Fin.succ) := by + congr 1 + funext y + simp only [F] + rw [cauchyKernel_cons x y w, mul_smul] + _ = (x - w 0)⁻¹ • torusIntegral + (fun y => (∏ i, (y i - w i.succ)⁻¹) • f (Fin.cons x y)) + (c ∘ Fin.succ) (R ∘ Fin.succ) := hsmul + _ = (x - w 0)⁻¹ • ((2 * π * I : ℂ) ^ n • + f (Fin.cons x (w ∘ Fin.succ))) := by rw [ih_int] + have hcircle := circleIntegral_cauchyKernel_cons hw hfc hfa + have houter : + torusIntegral F c R = + (2 * π * I : ℂ) ^ n • + ∮ x in C(c 0, R 0), (x - w 0)⁻¹ • f (Fin.cons x (w ∘ Fin.succ)) := by + rw [torusIntegral_succ hFint] + refine (circleIntegral.integral_congr (hR 0).le fun x hx => hinter x hx).trans ?_ + rw [show (fun x => (x - w 0)⁻¹ • ((2 * π * I : ℂ) ^ n • + f (Fin.cons x (w ∘ Fin.succ)))) = + fun x => ((2 * π * I : ℂ) ^ n) • ((x - w 0)⁻¹ • + f (Fin.cons x (w ∘ Fin.succ))) by + funext x; simp [smul_smul, mul_comm]] + rw [circleIntegral.integral_smul] + have hw_eq : Fin.cons (w 0) (w ∘ Fin.succ) = w := Fin.cons_self_tail w + rw [← hw_eq, houter, smul_smul] + convert hcircle using 2 + simp [pow_succ, two_pi_I_pow_ne_zero n] + +omit [CompleteSpace E] in +/-- Equal-radius compatibility form of Cauchy-kernel integrability. -/ +theorem torusIntegrable_cauchyKernel {n : ℕ} {f : (Fin n → ℂ) → E} + {c w : Fin n → ℂ} {R : ℝ} (hR : 0 < R) (hw : ∀ i, ‖w i - c i‖ < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) : + TorusIntegrable (fun z => (∏ i, (z i - w i)⁻¹) • f z) c (fun _ => R) := + torusIntegrable_cauchyKernelWithRadii (fun _ => hR) hw hfc + +/-- Equal-radius compatibility form of the polydisc Cauchy formula. -/ +theorem two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul_const {n : ℕ} {f : (Fin n → ℂ) → E} + {c w : Fin n → ℂ} {R : ℝ} + (hR : 0 < R) (hw : ∀ i, ‖w i - c i‖ < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hfa : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + ((2 * π * I : ℂ) ^ n)⁻¹ • + torusIntegral (fun z => (∏ i, (z i - w i)⁻¹) • f z) c (fun _ => R) = f w := + two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul (fun _ => hR) hw hfc hfa + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyPompeiu.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyPompeiu.lean new file mode 100644 index 0000000000..c3e835d038 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyPompeiu.lean @@ -0,0 +1,382 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.ContDiff.Basic +public import Mathlib.Analysis.Calculus.FDeriv.Const +public import Mathlib.Analysis.Complex.RealDeriv +public import Mathlib.Analysis.SpecialFunctions.Complex.Circle +public import Mathlib.Analysis.SpecialFunctions.PolarCoord +public import Mathlib.MeasureTheory.Integral.IntegralEqImproper + +/-! +# The Cauchy–Pompeiu identity + +For a real-linear map `L` and a direction `v`, the antiholomorphic part of `L` along `v` is `(L +v + I • L (I • v)) / 2`; for the real derivative of a function of one complex variable and `v = +1` this is the Wirtinger derivative `∂f/∂\bar z`. A real-linear map is complex-linear exactly +when all its antiholomorphic parts vanish. + +The Cauchy–Pompeiu identity states that for a compactly supported `C¹` function `φ : ℂ → F`, `∫ +(∂φ/∂\bar z)(w) / w = -π φ(0)`. The proof passes to polar coordinates: in the direction of the +ray the integrand is the radial derivative, whose integral over each ray is `-φ(0)`, and in the +angular direction it is the angular derivative divided by the radius, whose integral over each +circle vanishes by periodicity. No Green or Stokes theorem is used. + +References: [Hörmander][Hormander1973] (1973), Theorem 1.2.1; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Lemma 4.2.4. + +## Main definitions + +* `dbarAlong`: The antiholomorphic part of a real-linear map along a direction: `(L v + I • L (I • + v)) / 2`. +* `complexLinearOfDbar`: A real-linear map whose antiholomorphic parts all vanish, as a + complex-linear map. +* `polarRadialDeriv`: The radial derivative of `φ` at the point with polar coordinates `p`. +* `polarAngularDeriv`: The angular derivative of `φ` at the point with polar coordinates `p`, + divided by the radius. + +## Main results + +* `integral_inv_smul_dbarAlong_fderiv`: **The Cauchy–Pompeiu identity.** For a compactly supported + `C¹` function `φ : ℂ → F`, `∫ w⁻¹ • ∂φ/∂\bar z (w) = -π • φ 0`. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex MeasureTheory Set Filter +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +section Dbar + +/-- The antiholomorphic part of a real-linear map along a direction: `(L v + I • L (I • v)) / 2`. +For the real derivative of a function of one complex variable at `v = 1` this is `∂/∂\bar z`. -/ +@[expose] def dbarAlong (L : E →L[ℝ] F) (v : E) : F := (2 : ℂ)⁻¹ • (L v + I • L (I • v)) + +/-- The antiholomorphic part along `v` vanishes exactly when `L` commutes with `I` on `v`. -/ +theorem dbarAlong_eq_zero_iff (L : E →L[ℝ] F) (v : E) : + dbarAlong L v = 0 ↔ L (I • v) = I • L v := by + unfold dbarAlong + rw [smul_eq_zero, or_iff_right (inv_ne_zero two_ne_zero)] + constructor + · intro h + have h1 : L v = -(I • L (I • v)) := eq_neg_of_add_eq_zero_left h + calc L (I • v) = -(I • I • L (I • v)) := by + rw [smul_smul, I_mul_I, neg_one_smul, neg_neg] + _ = I • L v := by rw [h1, smul_neg] + · intro h + rw [h, smul_smul, I_mul_I, neg_one_smul, add_neg_cancel] + +/-- The antiholomorphic part of the zero map vanishes. -/ +theorem dbarAlong_zero (v : E) : dbarAlong (0 : E →L[ℝ] F) v = 0 := by + simp [dbarAlong] + +/-- The antiholomorphic part is additive in the map. -/ +theorem dbarAlong_add (L M : E →L[ℝ] F) (v : E) : + dbarAlong (L + M) v = dbarAlong L v + dbarAlong M v := by + simp only [dbarAlong, FunLike.coe_add, Pi.add_apply, smul_add] + module + +/-- The antiholomorphic part respects differences of maps. -/ +theorem dbarAlong_sub (L M : E →L[ℝ] F) (v : E) : + dbarAlong (L - M) v = dbarAlong L v - dbarAlong M v := by + simp only [dbarAlong, FunLike.coe_sub, Pi.sub_apply, smul_sub] + module + +/-- The antiholomorphic part of a complex-linear map vanishes. -/ +theorem dbarAlong_restrictScalars (L : E →L[ℂ] F) (v : E) : + dbarAlong (L.restrictScalars ℝ) v = 0 := by + rw [dbarAlong_eq_zero_iff] + simp + +/-- The antiholomorphic part of the composition of a real-linear map with a continuous linear map `T +: E →L[ℝ] F` and a complex-linear evaluation. -/ +theorem dbarAlong_comp_clm {G : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + (T : F →L[ℂ] G) (L : E →L[ℝ] F) (v : E) : + dbarAlong ((T.restrictScalars ℝ).comp L) v = T (dbarAlong L v) := by + simp [dbarAlong, map_add, map_smul] + +/-- A real-linear map whose antiholomorphic parts all vanish, as a complex-linear map. -/ +@[expose] def complexLinearOfDbar (L : E →L[ℝ] F) (h : ∀ v, dbarAlong L v = 0) : E →L[ℂ] F where + toFun := L + map_add' := map_add L + map_smul' := fun c v => by + have hI : ∀ v, L (I • v) = I • L v := fun v => (dbarAlong_eq_zero_iff L v).mp (h v) + simp only [RingHom.id_apply] + calc L (c • v) = L ((c.re : ℝ) • v + (c.im : ℝ) • (I • v)) := by + congr 1 + rw [← Complex.coe_smul, ← Complex.coe_smul, smul_smul, ← add_smul, Complex.re_add_im] + _ = c • L v := by + rw [map_add, map_smul, map_smul, hI, ← Complex.coe_smul, ← Complex.coe_smul, smul_smul, + ← add_smul, Complex.re_add_im] + cont := L.cont + +/-- The complex-linear map built from vanishing antiholomorphic parts has the same underlying +function. -/ +@[simp] theorem coe_complexLinearOfDbar (L : E →L[ℝ] F) (h : ∀ v, dbarAlong L v = 0) : + ⇑(complexLinearOfDbar L h) = ⇑L := rfl + +/-- Restricting scalars of `complexLinearOfDbar L h` recovers `L`. -/ +theorem restrictScalars_complexLinearOfDbar (L : E →L[ℝ] F) (h : ∀ v, dbarAlong L v = 0) : + (complexLinearOfDbar L h).restrictScalars ℝ = L := by + ext v + rfl + +end Dbar + +section Polar + +/-- The radial derivative of `φ` at the point with polar coordinates `p`. -/ +@[expose] def polarRadialDeriv (φ : ℂ → F) (p : ℝ × ℝ) : F := + fderiv ℝ φ (p.1 * exp (p.2 * I)) (exp (p.2 * I)) + +/-- The angular derivative of `φ` at the point with polar coordinates `p`, divided by the radius. -/ +@[expose] def polarAngularDeriv (φ : ℂ → F) (p : ℝ × ℝ) : F := + fderiv ℝ φ (p.1 * exp (p.2 * I)) (I * exp (p.2 * I)) + +/-- Rotation identity for a real-linear map on `ℂ`. -/ +theorem apply_exp_add_I_smul_apply_I_mul_exp (L : ℂ →L[ℝ] F) (θ : ℝ) : + L (exp (θ * I)) + I • L (I * exp (θ * I)) = exp (-(θ * I)) • (L 1 + I • L I) := by + have h1 : exp (θ * I) = (Real.cos θ) • (1 : ℂ) + (Real.sin θ) • I := by + rw [exp_mul_I] + simp [Complex.real_smul] + have h2 : I * exp (θ * I) = (-Real.sin θ) • (1 : ℂ) + (Real.cos θ) • I := by + rw [exp_mul_I] + simp only [Complex.real_smul, ofReal_neg] + ring_nf + simp [I_sq] + ring + have h3 : exp (-(θ * I)) = (cos (θ : ℂ) - sin (θ : ℂ) * I) := by + rw [← neg_mul, ← ofReal_neg, exp_mul_I] + simp [Complex.ofReal_neg] + ring + rw [h2, h1, map_add, map_add, map_smul, map_smul, map_smul, map_smul, h3] + simp only [← Complex.coe_smul, ofReal_neg, ofReal_cos, ofReal_sin] + match_scalars <;> first + | ring1 + | linear_combination (Complex.sin θ) * I_sq + +/-- The polar-coordinate form of the Cauchy–Pompeiu integrand. -/ +theorem smul_inv_smul_dbarAlong_polar (φ : ℂ → F) {r θ : ℝ} (hr : 0 < r) : + r • ((Complex.polarCoord.symm (r, θ))⁻¹ • dbarAlong (fderiv ℝ φ (Complex.polarCoord.symm (r, + θ))) 1) = + (2 : ℂ)⁻¹ • (polarRadialDeriv φ (r, θ) + I • polarAngularDeriv φ (r, θ)) := by + have hw : Complex.polarCoord.symm (r, θ) = r * exp (θ * I) := by + rw [Complex.polarCoord_symm_apply, exp_mul_I] + push_cast + ring + rw [hw] + have hinv : ((r : ℂ) * exp (θ * I))⁻¹ = (r : ℂ)⁻¹ * exp (-(θ * I)) := by + rw [mul_inv, ← exp_neg] + rw [hinv, polarRadialDeriv, polarAngularDeriv] + simp only + rw [apply_exp_add_I_smul_apply_I_mul_exp, dbarAlong] + simp only [smul_eq_mul, mul_one] + rw [← Complex.coe_smul, smul_smul, smul_smul, smul_smul] + congr 1 + have : (r : ℂ) ≠ 0 := by exact_mod_cast hr.ne' + field_simp + +/-- The radial derivative of a `C¹` function is continuous in polar coordinates. -/ +theorem continuous_polarRadialDeriv {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) : + Continuous (polarRadialDeriv φ) := by + unfold polarRadialDeriv + exact ((hφ.continuous_fderiv one_ne_zero).comp (by fun_prop)).clm_apply (by fun_prop) + +/-- The angular derivative of a `C¹` function is continuous in polar coordinates. -/ +theorem continuous_polarAngularDeriv {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) : + Continuous (polarAngularDeriv φ) := by + unfold polarAngularDeriv + exact ((hφ.continuous_fderiv one_ne_zero).comp (by fun_prop)).clm_apply (by fun_prop) + +/-- The real derivative vanishes at points whose modulus exceeds the support radius. -/ +theorem fderiv_eq_zero_of_norm_gt {φ : ℂ → F} {R : ℝ} (hR : tsupport φ ⊆ Metric.closedBall 0 R) + {w : ℂ} (hw : R < ‖w‖) : fderiv ℝ φ w = 0 := by + apply image_eq_zero_of_notMem_tsupport + intro h + have := hR (tsupport_fderiv_subset ℝ h) + rw [Metric.mem_closedBall, dist_zero_right] at this + exact absurd this (not_le.mpr hw) + +/-- A uniform bound on the derivative bounds the radial derivative. -/ +theorem norm_polarRadialDeriv_le {φ : ℂ → F} {C : ℝ} (hC : ∀ w, ‖fderiv ℝ φ w‖ ≤ C) (p : ℝ × ℝ) : + ‖polarRadialDeriv φ p‖ ≤ C := by + unfold polarRadialDeriv + calc ‖fderiv ℝ φ (p.1 * exp (p.2 * I)) (exp (p.2 * I))‖ + ≤ ‖fderiv ℝ φ (p.1 * exp (p.2 * I))‖ * ‖exp (p.2 * I)‖ := ContinuousLinearMap.le_opNorm _ _ + _ ≤ C := by rw [norm_exp_ofReal_mul_I, mul_one]; exact hC _ + +/-- A uniform bound on the derivative bounds the angular derivative. -/ +theorem norm_polarAngularDeriv_le {φ : ℂ → F} {C : ℝ} (hC : ∀ w, ‖fderiv ℝ φ w‖ ≤ C) (p : ℝ × ℝ) : + ‖polarAngularDeriv φ p‖ ≤ C := by + unfold polarAngularDeriv + calc ‖fderiv ℝ φ (p.1 * exp (p.2 * I)) (I * exp (p.2 * I))‖ + ≤ ‖fderiv ℝ φ (p.1 * exp (p.2 * I))‖ * ‖I * exp (p.2 * I)‖ := ContinuousLinearMap.le_opNorm + _ _ + _ ≤ C := by rw [norm_mul, norm_I, norm_exp_ofReal_mul_I, one_mul, mul_one]; exact hC _ + +/-- The modulus of `r e^{iθ}` is `|r|`. -/ +theorem norm_mul_exp_ofReal_mul_I (r θ : ℝ) : ‖(r : ℂ) * exp (θ * I)‖ = |r| := by + rw [norm_mul, norm_exp_ofReal_mul_I, mul_one, Complex.norm_real, Real.norm_eq_abs] + +/-- The radial derivative vanishes beyond the support radius. -/ +theorem polarRadialDeriv_eq_zero {φ : ℂ → F} {R : ℝ} (hR : tsupport φ ⊆ Metric.closedBall 0 R) + {p : ℝ × ℝ} (hp : R < |p.1|) : polarRadialDeriv φ p = 0 := by + unfold polarRadialDeriv + rw [fderiv_eq_zero_of_norm_gt hR (by rwa [norm_mul_exp_ofReal_mul_I])] + rfl + +/-- The angular derivative vanishes beyond the support radius. -/ +theorem polarAngularDeriv_eq_zero {φ : ℂ → F} {R : ℝ} (hR : tsupport φ ⊆ Metric.closedBall 0 R) + {p : ℝ × ℝ} (hp : R < |p.1|) : polarAngularDeriv φ p = 0 := by + unfold polarAngularDeriv + rw [fderiv_eq_zero_of_norm_gt hR (by rwa [norm_mul_exp_ofReal_mul_I])] + rfl + +omit [NormedSpace ℂ F] in +/-- A bounded continuous function on the polar-coordinate rectangle vanishing beyond a radius is +integrable on the polar target. -/ +theorem integrableOn_polarCoord_target_of_bound {A : ℝ × ℝ → F} (hA : Continuous A) {C R : ℝ} + (hC : ∀ p, ‖A p‖ ≤ C) (hzero : ∀ p : ℝ × ℝ, R < |p.1| → A p = 0) : + IntegrableOn A polarCoord.target := by + have hC0 : 0 ≤ C := (norm_nonneg _).trans (hC 0) + have hg : Integrable ((Icc (0 : ℝ) R ×ˢ Icc (-π) π).indicator fun _ => C) := + (integrableOn_const (isCompact_Icc.prod isCompact_Icc).measure_lt_top.ne).integrable_indicator + (measurableSet_Icc.prod measurableSet_Icc) + refine Integrable.mono' hg.integrableOn hA.aestronglyMeasurable ?_ + refine ae_restrict_of_forall_mem polarCoord.open_target.measurableSet fun p hp => ?_ + rw [polarCoord_target] at hp + by_cases h : p.1 ≤ R + · rw [indicator_of_mem (show p ∈ Icc (0 : ℝ) R ×ˢ Icc (-π) π from + ⟨⟨hp.1.le, h⟩, hp.2.1.le, hp.2.2.le⟩)] + exact hC p + · rw [hzero p (by rw [abs_of_pos hp.1]; exact not_le.mp h), norm_zero] + exact indicator_nonneg (fun _ _ => hC0) p + +omit [NormedSpace ℂ F] in +/-- A continuous function on the half-line vanishing beyond a radius is integrable there. -/ +theorem integrableOn_Ioi_of_continuous_of_eq_zero {g : ℝ → F} (hg : Continuous g) {R : ℝ} + (hz : ∀ r, R < r → g r = 0) : IntegrableOn g (Ioi 0) := by + have h1 : IntegrableOn g (Icc 0 R) := hg.continuousOn.integrableOn_Icc + have h2 : IntegrableOn g (Ioi R) := + ((integrable_zero _ _ _).integrableOn).congr_fun (fun r hr => (hz r hr).symm) measurableSet_Ioi + refine (h1.union h2).mono_set fun r hr => ?_ + rcases le_or_gt r R with h | h + · exact Or.inl ⟨le_of_lt hr, h⟩ + · exact Or.inr h + +variable [CompleteSpace F] + +/-- The radial integral of the radial derivative along a ray is `-φ 0`. -/ +theorem integral_Ioi_polarRadialDeriv {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) {R : ℝ} + (hR : tsupport φ ⊆ Metric.closedBall 0 R) (θ : ℝ) : + ∫ r in Ioi (0 : ℝ), polarRadialDeriv φ (r, θ) = -φ 0 := by + have hderiv : ∀ r ∈ Ici (0 : ℝ), + HasDerivAt (fun r : ℝ => φ (r * exp (θ * I))) (polarRadialDeriv φ (r, θ)) r := by + intro r _ + have h1 : HasDerivAt (fun r : ℝ => (r : ℂ) * exp (θ * I)) (exp (θ * I)) r := by + simpa using (hasDerivAt_id r).ofReal_comp.mul_const (exp (θ * I)) + exact (hφ.differentiable one_ne_zero _).hasFDerivAt.comp_hasDerivAt r h1 + have hint : IntegrableOn (fun r : ℝ => polarRadialDeriv φ (r, θ)) (Ioi 0) := by + refine integrableOn_Ioi_of_continuous_of_eq_zero (R := R) + ((continuous_polarRadialDeriv hφ).comp (by fun_prop)) fun r hr => ?_ + exact polarRadialDeriv_eq_zero hR (lt_of_lt_of_le hr (le_abs_self r)) + have hlim : Tendsto (fun r : ℝ => φ (r * exp (θ * I))) atTop (𝓝 0) := by + refine tendsto_const_nhds.congr' ((eventually_gt_atTop R).mono fun r hr => ?_) + symm + apply image_eq_zero_of_notMem_tsupport + intro h + have := hR h + rw [Metric.mem_closedBall, dist_zero_right, norm_mul_exp_ofReal_mul_I] at this + exact absurd (lt_of_lt_of_le hr (le_abs_self r)) (not_lt.mpr this) + have := integral_Ioi_of_hasDerivAt_of_tendsto' hderiv hint hlim + simpa using this + +/-- The angular integral of the angular derivative around a circle vanishes. -/ +theorem integral_Ioo_polarAngularDeriv {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) {r : ℝ} (hr : 0 < r) : + ∫ θ in Ioo (-π) π, polarAngularDeriv φ (r, θ) = 0 := by + have hderiv : ∀ θ ∈ uIcc (-π) π, + HasDerivAt (fun θ : ℝ => φ (r * exp (θ * I))) (r • polarAngularDeriv φ (r, θ)) θ := by + intro θ _ + have h1 : HasDerivAt (fun θ : ℝ => (r : ℂ) * exp (θ * I)) ((r : ℂ) * (exp (θ * I) * I)) θ := by + simpa using ((hasDerivAt_id θ).ofReal_comp.mul_const I).cexp.const_mul (r : ℂ) + refine ((hφ.differentiable one_ne_zero _).hasFDerivAt.comp_hasDerivAt θ h1).congr_deriv ?_ + unfold polarAngularDeriv + rw [show (r : ℂ) * (exp (θ * I) * I) = r • (I * exp (θ * I)) by + rw [Complex.real_smul]; ring, map_smul] + have hcont : IntervalIntegrable (fun θ : ℝ => r • polarAngularDeriv φ (r, θ)) volume (-π) π := + (((continuous_polarAngularDeriv hφ).comp (by fun_prop)).const_smul r).intervalIntegrable _ _ + have hftc := intervalIntegral.integral_eq_sub_of_hasDerivAt hderiv hcont + have hzero : φ (r * exp (π * I)) - φ (r * exp ((-π : ℝ) * I)) = 0 := by + rw [show ((-π : ℝ) : ℂ) * I = -(π * I) by push_cast; ring, exp_neg, exp_pi_mul_I] + simp + rw [hzero, intervalIntegral.integral_of_le (by linarith [Real.pi_pos]), + integral_Ioc_eq_integral_Ioo, integral_smul] at hftc + exact (smul_eq_zero.mp hftc).resolve_left hr.ne' + +/-- **The Cauchy–Pompeiu identity.** For a compactly supported `C¹` function `φ : ℂ → F`, +`∫ w⁻¹ • ∂φ/∂\bar z (w) = -π • φ 0`. -/ +theorem integral_inv_smul_dbarAlong_fderiv {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) + (hsupp : HasCompactSupport φ) : + ∫ w, w⁻¹ • dbarAlong (fderiv ℝ φ w) 1 = -((π : ℂ) • φ 0) := by + obtain ⟨R, hR⟩ := hsupp.isBounded.subset_closedBall 0 + obtain ⟨C, hC⟩ := (hsupp.fderiv ℝ).exists_bound_of_continuous (hφ.continuous_fderiv one_ne_zero) + have hAi : IntegrableOn (polarRadialDeriv φ) polarCoord.target := + integrableOn_polarCoord_target_of_bound (continuous_polarRadialDeriv hφ) + (norm_polarRadialDeriv_le hC) fun p hp => polarRadialDeriv_eq_zero hR hp + have hBi : IntegrableOn (polarAngularDeriv φ) polarCoord.target := + integrableOn_polarCoord_target_of_bound (continuous_polarAngularDeriv hφ) + (norm_polarAngularDeriv_le hC) fun p hp => polarAngularDeriv_eq_zero hR hp + rw [← Complex.integral_comp_polarCoord_symm] + have hpt : EqOn (fun p : ℝ × ℝ => p.1 • ((Complex.polarCoord.symm p)⁻¹ • + dbarAlong (fderiv ℝ φ (Complex.polarCoord.symm p)) 1)) + (fun p => (2 : ℂ)⁻¹ • (polarRadialDeriv φ p + I • polarAngularDeriv φ p)) + polarCoord.target := by + rintro ⟨r, θ⟩ hp + rw [polarCoord_target] at hp + exact smul_inv_smul_dbarAlong_polar φ hp.1 + have hBi2 : Integrable (fun p => I • polarAngularDeriv φ p) (volume.restrict polarCoord.target) := + hBi.smul I + rw [setIntegral_congr_fun polarCoord.open_target.measurableSet hpt, integral_smul, + integral_add hAi hBi2, integral_smul] + have hA_int : ∫ p in polarCoord.target, polarRadialDeriv φ p = -((2 * π : ℝ) • φ 0) := by + have hAi' : Integrable (polarRadialDeriv φ) + ((volume.restrict (Ioi (0 : ℝ))).prod (volume.restrict (Ioo (-π) π))) := by + rwa [Measure.prod_restrict, ← Measure.volume_eq_prod, ← polarCoord_target] + rw [polarCoord_target, Measure.volume_eq_prod, ← Measure.prod_restrict, + integral_prod_symm _ hAi'] + simp_rw [integral_Ioi_polarRadialDeriv hφ hR] + rw [setIntegral_const, measureReal_def, Real.volume_Ioo, + ENNReal.toReal_ofReal (by linarith [Real.pi_pos]), smul_neg] + congr 2 + ring + have hB_int : ∫ p in polarCoord.target, polarAngularDeriv φ p = 0 := by + have hBi' : Integrable (polarAngularDeriv φ) + ((volume.restrict (Ioi (0 : ℝ))).prod (volume.restrict (Ioo (-π) π))) := by + rwa [Measure.prod_restrict, ← Measure.volume_eq_prod, ← polarCoord_target] + rw [polarCoord_target, Measure.volume_eq_prod, ← Measure.prod_restrict, integral_prod _ hBi'] + exact setIntegral_eq_zero_of_forall_eq_zero fun r hr => integral_Ioo_polarAngularDeriv hφ hr + rw [hA_int, hB_int, smul_zero, add_zero, ← Complex.coe_smul, smul_neg, smul_smul] + congr 2 + push_cast + field_simp + +end Polar + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean new file mode 100644 index 0000000000..457cdca800 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean @@ -0,0 +1,130 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Conformal +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Coordinate Cauchy–Riemann equations + +Real differentiability and the coordinate Cauchy–Riemann equations characterize holomorphy on an +open finite-dimensional domain. The proof uses Mathlib's one-variable conversion theorem and +Osgood, rather than constructing a second complex derivative theory. + +The domain `ι → ℂ` is intentional: each Wirtinger derivative and each displayed Cauchy–Riemann +equation singles out a coordinate. The codomain may be a complex normed space, with completeness +assumed for the analyticity results. Coordinate-free holomorphy is expressed by the usual +complex Fréchet derivative; these results describe it in coordinates and relate the real +derivative to the existing `partialDeriv` interface. + +## Main definitions + +* `wirtingerDeriv`: The holomorphic Wirtinger derivative, defined from the real Fréchet derivative. +* `conjWirtingerDeriv`: The antiholomorphic Wirtinger derivative, defined from the real Fréchet + derivative. + +## Main results + +* `hasFDerivAt_update_real`: The real derivative of a coordinate slice is the restriction of the + real derivative to that coordinate's complex plane. +* `analyticOnNhd_iff_differentiableAt_real_cauchyRiemann`: On an open set, holomorphy is equivalent + to real differentiability together with the coordinate Cauchy–Riemann equations. +* `AnalyticOnNhd.conjWirtingerDeriv_eq_zero`: The antiholomorphic Wirtinger derivative vanishes for + a holomorphic function. +* `AnalyticOnNhd.wirtingerDeriv_eq_partialDeriv`: For holomorphic functions the holomorphic + Wirtinger derivative agrees with the complex coordinate derivative `partialDeriv`. +-/ + +public noncomputable section + +open Complex Filter Function Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The holomorphic Wirtinger derivative, defined from the real Fréchet derivative. -/ +@[expose] def wirtingerDeriv (i : ι) (f : (ι → ℂ) → F) (z : ι → ℂ) : F := + (1 / 2 : ℂ) • (fderiv ℝ f z (Pi.single i 1) - I • fderiv ℝ f z (Pi.single i I)) + +/-- The antiholomorphic Wirtinger derivative, defined from the real Fréchet derivative. -/ +@[expose] def conjWirtingerDeriv (i : ι) (f : (ι → ℂ) → F) (z : ι → ℂ) : F := + (1 / 2 : ℂ) • (fderiv ℝ f z (Pi.single i 1) + I • fderiv ℝ f z (Pi.single i I)) + +/-- The real derivative of a coordinate slice is the restriction of the real derivative to that +coordinate's complex plane. -/ +theorem hasFDerivAt_update_real {f : (ι → ℂ) → F} (z : ι → ℂ) (i : ι) (w : ℂ) + (hf : DifferentiableAt ℝ f (update z i w)) : + HasFDerivAt (fun v => f (update z i v)) + ((fderiv ℝ f (update z i w)).comp + ((ContinuousLinearMap.single ℂ (fun _ : ι => ℂ) i).restrictScalars ℝ)) w := by + have hs : HasFDerivAt (update z i) + ((ContinuousLinearMap.single ℂ (fun _ : ι => ℂ) i).restrictScalars ℝ) w := by + convert! (hasDerivAt_update z i w).hasFDerivAt.restrictScalars ℝ using 1 + ext v j + simp [Pi.single_apply, smul_eq_mul] + exact hf.hasFDerivAt.comp w hs + +variable [CompleteSpace F] + +/-- On an open set, holomorphy is equivalent to real differentiability together with the coordinate +Cauchy–Riemann equations. Continuous real differentiability is not needed. -/ +theorem analyticOnNhd_iff_differentiableAt_real_cauchyRiemann + {U : Set (ι → ℂ)} (hU : IsOpen U) {f : (ι → ℂ) → F} : + AnalyticOnNhd ℂ f U ↔ + (∀ z ∈ U, DifferentiableAt ℝ f z) ∧ + ∀ z ∈ U, ∀ i, fderiv ℝ f z (Pi.single i I) = I • fderiv ℝ f z (Pi.single i 1) := by + constructor + · intro hf + refine ⟨fun z hz => (hf z hz).differentiableAt.restrictScalars ℝ, ?_⟩ + intro z hz i + rw [(hf z hz).differentiableAt.fderiv_restrictScalars ℝ] + change fderiv ℂ f z (Pi.single i I) = I • fderiv ℂ f z (Pi.single i 1) + rw [show Pi.single i I = I • (Pi.single i (1 : ℂ)) by + ext j; by_cases hji : j = i <;> simp [hji]] + exact map_smul _ _ _ + · rintro ⟨hreal, hCR⟩ + apply analyticOnNhd_pi_of_analyticOnNhd_update hU + (fun z hz => (hreal z hz).continuousAt.continuousWithinAt) + intro z hz i + rw [analyticAt_iff_eventually_differentiableAt] + have hmem : ∀ᶠ w in 𝓝 (z i), update z i w ∈ U := by + exact ((hasDerivAt_update z i (z i)).continuousAt.preimage_mem_nhds + (by simpa using hU.mem_nhds hz)) + filter_upwards [hmem] with w hw + have H := hasFDerivAt_update_real z i w (hreal _ hw) + apply differentiableAt_complex_iff_differentiableAt_real.mpr + refine ⟨H.differentiableAt, ?_⟩ + rw [H.fderiv] + simpa using hCR (update z i w) hw i + +/-- The antiholomorphic Wirtinger derivative vanishes for a holomorphic function. -/ +theorem _root_.AnalyticOnNhd.conjWirtingerDeriv_eq_zero {U : Set (ι → ℂ)} + {f : (ι → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) + {z : ι → ℂ} (hz : z ∈ U) (i : ι) : conjWirtingerDeriv i f z = 0 := by + have hCR := (analyticOnNhd_iff_differentiableAt_real_cauchyRiemann hU).mp hf |>.2 z hz i + simp [conjWirtingerDeriv, hCR, smul_smul] + +/-- For holomorphic functions the holomorphic Wirtinger derivative agrees with the complex +coordinate derivative `partialDeriv`. -/ +theorem _root_.AnalyticOnNhd.wirtingerDeriv_eq_partialDeriv {U : Set (ι → ℂ)} + {f : (ι → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) + {z : ι → ℂ} (hz : z ∈ U) (i : ι) : wirtingerDeriv i f z = partialDeriv i f z := by + have hCR := (analyticOnNhd_iff_differentiableAt_real_cauchyRiemann hU).mp hf |>.2 z hz i + rw [wirtingerDeriv, hCR, smul_smul, I_mul_I, neg_one_smul, sub_neg_eq_add, + ← two_smul ℂ, smul_smul] + norm_num + rw [partialDeriv_eq_fderiv (hf z hz).differentiableAt, + (hf z hz).differentiableAt.fderiv_restrictScalars ℝ] + rfl + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchySeries.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchySeries.lean new file mode 100644 index 0000000000..90cc526e8c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchySeries.lean @@ -0,0 +1,679 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Constructions +public import Mathlib.Analysis.Calculus.FDeriv.Analytic +public import Mathlib.Data.Fin.Tuple.NatAntidiagonal +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral + +/-! +# Multivariable Cauchy coefficients and series + +Cauchy coefficients, their estimates, and their packaging as a `FormalMultilinearSeries`. +`hasFPowerSeriesOnBall_polydiscCauchy_full` represents the function on the entire open +equal-radius polydisc. The original half-radius theorem remains as a compatibility wrapper. +Diagonal coefficients are identified with iterated Fréchet derivatives. + +Apply Mathlib's `HasFPowerSeriesOnBall.tendstoLocallyUniformlyOn` and +`HasFPowerSeriesOnBall.uniform_geometric_approx` to obtain locally uniform partial-sum +convergence and geometric remainder bounds on smaller polydiscs. Individual mixed coefficients +and radius independence are developed in `CauchyCoefficients`; the separate-radius multi-index +expansion, its uniform convergence and remainder estimates are in `PolydiscTaylor`. + +## Main definitions + +* `multiIndexMonomial`: The continuous multilinear monomial associated to a multi-index of total + degree `n`. +* `polydiscCauchyCoeff`: The multi-index Cauchy coefficient of a vector-valued function on a + polydisc. +* `polydiscCauchySeries`: The formal multilinear series obtained by grouping the polydisc Cauchy + coefficients by total degree. + +## Main results + +* `hasSum_polydiscCauchySeries`: The Cauchy series converges to the function at every point of the + open polydisc. +* `hasFPowerSeriesOnBall_polydiscCauchy_full`: The Cauchy series represents the function on the full + open supremum-norm ball, not just the half-radius ball needed by the original Osgood proof. +* `hasFPowerSeriesOnBall_polydiscCauchy`: A continuous, separately analytic function on a closed + polydisc is represented on the concentric polydisc of half the radius by its multivariable Cauchy + series. +* `polydiscCauchySeries_diag_eq_iteratedFDeriv`: On the diagonal, the Cauchy series is the usual + Taylor series of iterated Fréchet derivatives. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped ENNReal NNReal Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-! +### Multi-index Cauchy series +-/ + +/-- The continuous multilinear monomial associated to a multi-index of total degree `n`. -/ +noncomputable def multiIndexMonomial {d n : ℕ} (m : Fin d → ℕ) + (hm : ∑ i, m i = n) : + ContinuousMultilinearMap ℂ (fun _ : Fin n => (Fin d → ℂ)) ℂ := by + let e : (Σ i, Fin (m i)) ≃ Fin n := Fintype.equivFinOfCardEq (by simpa using hm) + exact ((ContinuousMultilinearMap.mkPiAlgebra ℂ (Σ i, Fin (m i)) ℂ).compContinuousLinearMap + (fun q => ContinuousLinearMap.proj q.1)).domDomCongr e + +/-- On the diagonal, `multiIndexMonomial` evaluates to the usual multi-index monomial. -/ +theorem multiIndexMonomial_apply {d n : ℕ} (m : Fin d → ℕ) + (hm : ∑ i, m i = n) (w : Fin d → ℂ) : + multiIndexMonomial m hm (fun _ => w) = ∏ i, w i ^ m i := by + simp [multiIndexMonomial, Fintype.prod_sigma] + +/-- The operator norm of `multiIndexMonomial` is at most one for the sup norm. -/ +theorem norm_multiIndexMonomial_le {d n : ℕ} (m : Fin d → ℕ) + (hm : ∑ i, m i = n) : ‖multiIndexMonomial m hm‖ ≤ 1 := by + rw [multiIndexMonomial, ContinuousMultilinearMap.norm_domDomCongr] + refine (ContinuousMultilinearMap.norm_compContinuousLinearMap_le _ _).trans ?_ + rw [ContinuousMultilinearMap.norm_mkPiAlgebra] + simp only [one_mul] + refine Finset.prod_le_one₀ (fun _ _ => norm_nonneg _) fun q _ => ?_ + refine ContinuousLinearMap.opNorm_le_bound _ zero_le_one fun w => ?_ + simpa using norm_le_pi_norm w q.1 + +/-- Absolute summability of a finite product of geometric series. -/ +theorem summable_norm_pi_geometric {K : Type*} [NormedCommRing K] + {d : ℕ} (x : Fin d → K) (hx : ∀ i, ‖x i‖ < 1) : + Summable fun m : Fin d → ℕ => ‖∏ i, x i ^ m i‖ := by + induction d with + | zero => + exact (hasSum_single (0 : Fin 0 → ℕ) fun m hm => + (hm (Subsingleton.elim _ _)).elim).summable + | succ d ih => + let e := Fin.consEquiv (fun _ : Fin (d + 1) => ℕ) + have hhead : Summable (fun n : ℕ => ‖x 0 ^ n‖) := + summable_norm_geometric_of_norm_lt_one (hx 0) + have htail := ih (fun i => x i.succ) (fun i => hx i.succ) + have hprod := hhead.mul_of_nonneg htail (fun _ => norm_nonneg _) (fun _ => norm_nonneg _) + rw [← e.summable_iff] + refine Summable.of_nonneg_of_le (fun _ => norm_nonneg _) ?_ hprod + intro p + simpa only [Function.comp_apply, e, Fin.consEquiv_apply, Fin.prod_univ_succ, + Fin.cons_zero, Fin.cons_succ] using + norm_mul_le (x 0 ^ p.1) (∏ i, x i.succ ^ p.2 i) + +/-- The multivariable geometric series sums to the product of its one-variable sums. -/ +theorem hasSum_pi_geometric {K : Type*} [NormedField K] [CompleteSpace K] + {d : ℕ} (x : Fin d → K) (hx : ∀ i, ‖x i‖ < 1) : + HasSum (fun m : Fin d → ℕ => ∏ i, x i ^ m i) (∏ i, (1 - x i)⁻¹) := by + induction d with + | zero => + simp + | succ d ih => + let e := Fin.consEquiv (fun _ : Fin (d + 1) => ℕ) + have hhead : HasSum (fun n : ℕ => x 0 ^ n) (1 - x 0)⁻¹ := + hasSum_geometric_of_norm_lt_one (hx 0) + have htail : HasSum (fun m : Fin d → ℕ => ∏ i, x i.succ ^ m i) + (∏ i : Fin d, (1 - x i.succ)⁻¹) := + ih (fun i => x i.succ) (fun i => hx i.succ) + have hnormHead : Summable (fun n : ℕ => ‖x 0 ^ n‖) := + summable_norm_geometric_of_norm_lt_one (hx 0) + have hnormTail : Summable (fun m : Fin d → ℕ => ‖∏ i, x i.succ ^ m i‖) := + summable_norm_pi_geometric _ (fun i => hx i.succ) + have hsummul : Summable + (fun p : ℕ × (Fin d → ℕ) => x 0 ^ p.1 * ∏ i, x i.succ ^ p.2 i) := + (hnormHead.mul_norm hnormTail).of_norm + have hprod : HasSum + (fun p : ℕ × (Fin d → ℕ) => x 0 ^ p.1 * ∏ i, x i.succ ^ p.2 i) + ((1 - x 0)⁻¹ * ∏ i : Fin d, (1 - x i.succ)⁻¹) := by + rw [← hhead.tsum_eq, ← htail.tsum_eq, + tsum_mul_tsum_of_summable_norm hnormHead hnormTail] + exact hsummul.hasSum + rw [← e.hasSum_iff] + convert hprod using 1 + · ext p + simp [e, Fin.prod_univ_succ] + · simp [Fin.prod_univ_succ, mul_comm] + +/-- A multivariable geometric series, summed by total degree. -/ +private theorem hasSum_antidiagonalTuple_geometric {K : Type*} [NormedField K] [CompleteSpace K] + {d : ℕ} (x : Fin d → K) + (hx : ∀ i, ‖x i‖ < 1) : + HasSum (fun n : ℕ => ∑ m ∈ Finset.Nat.antidiagonalTuple d n, ∏ i, x i ^ m i) + (∏ i, (1 - x i)⁻¹) := by + have h := hasSum_pi_geometric x hx + let e := Finset.Nat.sigmaAntidiagonalTupleEquivTuple d + have he0 : HasSum + ((fun m : Fin d → ℕ => ∏ i, x i ^ m i) ∘ e) + (∏ i, (1 - x i)⁻¹) := e.hasSum_iff.mpr h + have he : HasSum + (fun p : Σ n, Finset.Nat.antidiagonalTuple d n => + ∏ i, x i ^ (p.2 : Fin d → ℕ) i) + (∏ i, (1 - x i)⁻¹) := by + convert he0 using 1 + · ext p + rfl + have hfin : ∀ n, HasSum + (fun m : Finset.Nat.antidiagonalTuple d n => ∏ i, x i ^ (m : Fin d → ℕ) i) + (∑ m ∈ Finset.Nat.antidiagonalTuple d n, ∏ i, x i ^ m i) := by + intro n + rw [← Finset.sum_finset_coe] + exact hasSum_fintype (f := fun m : Finset.Nat.antidiagonalTuple d n => + ∏ i, x i ^ (m : Fin d → ℕ) i) + exact he.sigma hfin + +/-- The multi-index Cauchy coefficient of a vector-valued function on a polydisc. -/ +@[expose] noncomputable def polydiscCauchyCoeff {d : ℕ} (f : (Fin d → ℂ) → E) + (c : Fin d → ℂ) (R : ℝ) (m : Fin d → ℕ) : E := + ((2 * π * I : ℂ) ^ d)⁻¹ • torusIntegral + (fun z => (∏ i, (z i - c i)⁻¹ ^ (m i + 1)) • f z) c (fun _ => R) + +/-- The formal multilinear series obtained by grouping the polydisc Cauchy coefficients by total +degree. -/ +noncomputable def polydiscCauchySeries {d : ℕ} (f : (Fin d → ℂ) → E) + (c : Fin d → ℂ) (R : ℝ) : FormalMultilinearSeries ℂ (Fin d → ℂ) E := fun n => + ∑ m : Finset.Nat.antidiagonalTuple d n, + (multiIndexMonomial (m : Fin d → ℕ) + (Finset.Nat.mem_antidiagonalTuple.mp m.property)).smulRight + (polydiscCauchyCoeff f c R m) + +omit [CompleteSpace E] in +/-- Evaluation of the homogeneous terms of `polydiscCauchySeries` on the diagonal. -/ +theorem polydiscCauchySeries_apply {d n : ℕ} (f : (Fin d → ℂ) → E) + (c h : Fin d → ℂ) (R : ℝ) : + polydiscCauchySeries f c R n (fun _ => h) = + ∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) • polydiscCauchyCoeff f c R m := by + simp [polydiscCauchySeries, multiIndexMonomial_apply] + +omit [CompleteSpace E] in +/-- Cauchy's coefficient estimate for the multi-index coefficients of a bounded function on a closed +polydisc. -/ +theorem norm_polydiscCauchyCoeff_le {d : ℕ} {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) (m : Fin d → ℕ) : + ‖polydiscCauchyCoeff f c R m‖ ≤ M * R⁻¹ ^ (∑ i, m i) := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans (hM c (by + intro i _ + simp [mem_closedBall, dist_self, hR.le])) + rw [polydiscCauchyCoeff, norm_smul] + refine (mul_le_mul_of_nonneg_left (norm_torusIntegral_le_of_norm_le_const + (C := M * R⁻¹ ^ (∑ i, (m i + 1))) ?_) + (norm_nonneg _)).trans_eq ?_ + · intro θ + rw [norm_smul] + calc + ‖∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ (m i + 1)‖ * + ‖f (torusMap c (fun _ => R) θ)‖ + ≤ ‖∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ (m i + 1)‖ * M := + mul_le_mul_of_nonneg_left (hM _ (torusMap_mem_closedPolydisc (fun _ => hR.le) θ)) + (norm_nonneg _) + _ = M * R⁻¹ ^ (∑ i, (m i + 1)) := by + simp only [norm_prod, norm_pow, norm_inv, norm_torusMap_sub (fun _ => hR.le)] + rw [Finset.prod_pow_eq_pow_sum] + ring + · simp only [norm_inv, norm_pow, norm_mul, norm_ofNat, norm_real, norm_I, mul_one, + Real.norm_eq_abs, abs_of_pos hR, abs_of_pos Real.pi_pos, Fin.prod_const] + simp only [Finset.sum_add_distrib, Finset.sum_const, Finset.card_univ, Fintype.card_fin, + nsmul_eq_mul, mul_one] + field_simp + simp only [one_div, pow_add] + calc + R ^ d * M * (R⁻¹ ^ (∑ x, m x) * R⁻¹ ^ d) = + M * R⁻¹ ^ (∑ x, m x) * (R ^ d * R⁻¹ ^ d) := by ring + _ = M * R⁻¹ ^ ∑ x, m x := by + rw [← mul_pow, mul_inv_cancel₀ hR.ne', one_pow, mul_one] + +omit [CompleteSpace E] in +/-- Cauchy estimate for the homogeneous terms of the polydisc Cauchy series. -/ +private theorem norm_polydiscCauchySeries_mul_pow_le {d : ℕ} {f : (Fin d → ℂ) → E} + {c : Fin d → ℂ} {R M r : ℝ} (hR : 0 < R) (hr : 0 ≤ r) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) (n : ℕ) : + ‖polydiscCauchySeries f c R n‖ * r ^ n ≤ + M * ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (r * R⁻¹) ^ (m : Fin d → ℕ) i := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans (hM c (by + intro i _ + simp [mem_closedBall, dist_self, hR.le])) + rw [polydiscCauchySeries] + calc + ‖∑ m : Finset.Nat.antidiagonalTuple d n, + (multiIndexMonomial (m : Fin d → ℕ) + (Finset.Nat.mem_antidiagonalTuple.mp m.property)).smulRight + (polydiscCauchyCoeff f c R m)‖ * r ^ n + ≤ (∑ m : Finset.Nat.antidiagonalTuple d n, + ‖(multiIndexMonomial (m : Fin d → ℕ) + (Finset.Nat.mem_antidiagonalTuple.mp m.property)).smulRight + (polydiscCauchyCoeff f c R m)‖) * r ^ n := by + gcongr + exact norm_sum_le _ _ + _ ≤ (∑ _m : Finset.Nat.antidiagonalTuple d n, M * R⁻¹ ^ n) * r ^ n := by + gcongr with m + rw [ContinuousMultilinearMap.norm_smulRight] + calc + ‖multiIndexMonomial (m : Fin d → ℕ) + (Finset.Nat.mem_antidiagonalTuple.mp m.property)‖ * + ‖polydiscCauchyCoeff f c R m‖ + ≤ 1 * (M * R⁻¹ ^ (∑ i, (m : Fin d → ℕ) i)) := by + gcongr + · exact norm_multiIndexMonomial_le _ _ + · exact norm_polydiscCauchyCoeff_le hR hM _ + _ = M * R⁻¹ ^ n := by + rw [Finset.Nat.mem_antidiagonalTuple.mp m.property] + ring + _ = M * ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (r * R⁻¹) ^ (m : Fin d → ℕ) i := by + rw [Finset.sum_mul, Finset.mul_sum] + apply Finset.sum_congr rfl + intro m _ + simp_rw [mul_pow] + rw [Finset.prod_mul_distrib, Finset.prod_pow_eq_pow_sum, + Finset.prod_pow_eq_pow_sum, + Finset.Nat.mem_antidiagonalTuple.mp m.property] + ring + +omit [CompleteSpace E] in +/-- Below the radius, the Cauchy estimates give a summable geometric majorant. -/ +private theorem summable_norm_polydiscCauchySeries_mul_pow {d : ℕ} + {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R M r : ℝ} (hR : 0 < R) + (hr : 0 ≤ r) (hrR : r < R) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) : + Summable fun n => ‖polydiscCauchySeries f c R n‖ * r ^ n := by + have hq0 : 0 ≤ r * R⁻¹ := mul_nonneg hr (inv_nonneg.mpr hR.le) + have hq1 : r * R⁻¹ < 1 := by + rw [← div_eq_mul_inv, div_lt_one hR] + exact hrR + have hq1norm : ∀ _i : Fin d, ‖(r * R⁻¹ : ℝ)‖ < 1 := fun _ => by + rw [Real.norm_eq_abs, abs_of_nonneg hq0] + exact hq1 + have hseries : HasSum (fun n : ℕ => + ∑ m ∈ Finset.Nat.antidiagonalTuple d n, + ∏ i, (r * R⁻¹) ^ (m : Fin d → ℕ) i) + (∏ _i : Fin d, (1 - r * R⁻¹)⁻¹) := + hasSum_antidiagonalTuple_geometric (K := ℝ) (fun _ => r * R⁻¹) hq1norm + have hgeom : Summable fun n : ℕ => + ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (r * R⁻¹) ^ (m : Fin d → ℕ) i := by + exact hseries.summable.congr fun n => + (Finset.sum_finset_coe + (fun m : Fin d → ℕ => ∏ i, (r * R⁻¹) ^ m i) + (Finset.Nat.antidiagonalTuple d n)).symm + have hmajor : Summable fun n => M * + ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (r * R⁻¹) ^ (m : Fin d → ℕ) i := hgeom.mul_left M + refine Summable.of_nonneg_of_le (fun _ => mul_nonneg (norm_nonneg _) (pow_nonneg hr _)) + (norm_polydiscCauchySeries_mul_pow_le hR hr hM) ?_ + exact hmajor + +/-- Expansion of the polydisc Cauchy kernel by total degree. -/ +private theorem hasSum_polydiscCauchyKernel {d : ℕ} {z c h : Fin d → ℂ} + (hz : ∀ i, z i ≠ c i) (hh : ∀ i, ‖h i‖ < ‖z i - c i‖) : + HasSum (fun n : ℕ => ∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (z i - c i)⁻¹ ^ ((m : Fin d → ℕ) i + 1)) + (∏ i, (z i - (c + h) i)⁻¹) := by + have hx : ∀ i, ‖h i / (z i - c i)‖ < 1 := by + intro i + rw [norm_div, div_lt_one (norm_pos_iff.mpr (sub_ne_zero.mpr (hz i)))] + exact hh i + have hs := (hasSum_antidiagonalTuple_geometric + (fun i => h i / (z i - c i)) hx).mul_right (∏ i, (z i - c i)⁻¹) + have hterm : (fun n : ℕ => ∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (z i - c i)⁻¹ ^ ((m : Fin d → ℕ) i + 1)) = + fun n => (∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (h i / (z i - c i)) ^ (m : Fin d → ℕ) i) * + ∏ i, (z i - c i)⁻¹ := by + funext n + rw [Finset.sum_mul] + apply Finset.sum_congr rfl + intro m _ + rw [← Finset.prod_mul_distrib, ← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i _ + rw [pow_succ, div_pow, inv_pow] + field_simp [sub_ne_zero.mpr (hz i)] + have hconst : (∏ i, (z i - (c + h) i)⁻¹) = + (∏ i, (1 - h i / (z i - c i))⁻¹) * ∏ i, (z i - c i)⁻¹ := by + rw [← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i _ + have hzi : z i - c i ≠ 0 := sub_ne_zero.mpr (hz i) + have hzih : z i - (c + h) i ≠ 0 := by + intro heq + have : z i - c i = h i := by + calc + z i - c i = (c + h) i - c i := by rw [sub_eq_zero.mp heq] + _ = h i := by simp [Pi.add_apply] + have hi := hh i + rw [this] at hi + exact (lt_irrefl _ hi) + simp only [Pi.add_apply] + field_simp [hzi, hzih] + ring + have hsource : (fun n => (∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (h i / (z i - c i)) ^ (m : Fin d → ℕ) i) * + ∏ i, (z i - c i)⁻¹) = + fun n => (∑ m ∈ Finset.Nat.antidiagonalTuple d n, + ∏ i, (h i / (z i - c i)) ^ m i) * ∏ i, (z i - c i)⁻¹ := by + funext n + exact congrArg (fun v => v * ∏ i, (z i - c i)⁻¹) + (Finset.sum_finset_coe + (fun m : Fin d → ℕ => ∏ i, (h i / (z i - c i)) ^ m i) + (Finset.Nat.antidiagonalTuple d n)) + rw [hterm, hsource, hconst] + exact hs + +omit [CompleteSpace E] in +/-- A uniformly absolutely summable series may be integrated termwise on a torus. -/ +theorem hasSum_torusIntegral_of_uniform {d : ℕ} {κ : Type*} [Countable κ] + {F : κ → (Fin d → ℂ) → E} + {g : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R : Fin d → ℝ} {a : κ → ℝ} + (ha : Summable a) + (hFint : ∀ n, TorusIntegrable (F n) c R) + (hbound : ∀ n θ, ‖F n (torusMap c R θ)‖ ≤ a n) + (hsum : ∀ θ, HasSum (fun n => F n (torusMap c R θ)) (g (torusMap c R θ))) : + HasSum (fun n => torusIntegral (F n) c R) (torusIntegral g c R) := by + let J : (Fin d → ℝ) → ℂ := fun θ => ∏ i, R i * exp (θ i * I) * I + have h := MeasureTheory.hasSum_integral_of_dominated_convergence + (μ := volume.restrict (Icc (0 : Fin d → ℝ) fun _ => 2 * π)) + (F := fun n θ => J θ • F n (torusMap c R θ)) + (f := fun θ => J θ • g (torusMap c R θ)) + (fun n _ => (∏ i, |R i|) * a n) + (fun n => (hFint n).function_integrable.1) + (fun n => ae_of_all _ fun θ => by + rw [norm_smul] + have hJ : ‖J θ‖ = ∏ i, |R i| := by simp [J] + rw [hJ] + exact mul_le_mul_of_nonneg_left (hbound n θ) (by positivity)) + (ae_of_all _ fun _ => (ha.mul_left (∏ i, |R i|))) + (by + simp only [tsum_mul_left] + exact integrableOn_const (hs := measure_Icc_lt_top.ne)) + (ae_of_all _ fun θ => (hsum θ).const_smul (J θ)) + simpa [torusIntegral, J] using h + +/-- The homogeneous term of total degree `n` in the Cauchy kernel expansion. -/ +private noncomputable def polydiscCauchyTerm {d : ℕ} (f : (Fin d → ℂ) → E) + (c h : Fin d → ℂ) (n : ℕ) (z : Fin d → ℂ) : E := + (∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (z i - c i)⁻¹ ^ ((m : Fin d → ℕ) i + 1)) • f z + +omit [CompleteSpace E] in +/-- Torus integrals commute with finite sums. -/ +private theorem torusIntegral_fintype_sum {d : ℕ} {α : Type*} [Fintype α] + {F : α → (Fin d → ℂ) → E} {c : Fin d → ℂ} {R : Fin d → ℝ} + (hF : ∀ a, TorusIntegrable (F a) c R) : + torusIntegral (fun z => ∑ a, F a z) c R = ∑ a, torusIntegral (F a) c R := by + simp only [torusIntegral, Finset.smul_sum] + exact integral_finsetSum _ fun a _ => (hF a).function_integrable + +omit [CompleteSpace E] in +/-- Each monomial summand of the Cauchy kernel expansion is torus integrable. -/ +private theorem torusIntegrable_polydiscCauchySummand {d : ℕ} + {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} {R : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) (m : Fin d → ℕ) : + TorusIntegrable (fun z => ((∏ i, h i ^ m i) * + ∏ i, (z i - c i)⁻¹ ^ (m i + 1)) • f z) c (fun _ => R) := by + have hfθ : ContinuousOn (fun θ => f (torusMap c (fun _ => R) θ)) + (Icc (0 : Fin d → ℝ) fun _ => 2 * π) := + hfc.comp (continuous_torusMap_const c R).continuousOn + (fun θ _ => torusMap_mem_closedPolydisc (fun _ => hR.le) θ) + have hscalar : ContinuousOn (fun θ : Fin d → ℝ => + (∏ i, h i ^ m i) * + ∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ (m i + 1)) + (Icc (0 : Fin d → ℝ) fun _ => 2 * π) := by + refine continuousOn_const.mul (continuousOn_finsetProd _ fun i _ => ?_) + refine (((((continuous_apply i).comp (continuous_torusMap_const c R)).continuousOn).sub + continuousOn_const).inv₀ ?_).pow _ + intro θ _ + apply sub_ne_zero.mpr + intro heq + have := norm_torusMap_sub (c := c) (fun _ => hR.le) θ i + have heq' : torusMap c (fun _ => R) θ i = c i := by + simpa only [Function.comp_apply] using heq + rw [heq', sub_self, norm_zero] at this + exact hR.ne' this.symm + exact (hscalar.smul hfθ).integrableOn_compact isCompact_Icc + +omit [CompleteSpace E] in +/-- Each homogeneous term of the Cauchy kernel expansion is torus integrable. -/ +private theorem torusIntegrable_polydiscCauchyTerm {d n : ℕ} + {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} {R : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) : + TorusIntegrable (polydiscCauchyTerm f c h n) c (fun _ => R) := by + have hfθ : ContinuousOn (fun θ => f (torusMap c (fun _ => R) θ)) + (Icc (0 : Fin d → ℝ) fun _ => 2 * π) := + hfc.comp (continuous_torusMap_const c R).continuousOn + (fun θ _ => torusMap_mem_closedPolydisc (fun _ => hR.le) θ) + have hscalar : ContinuousOn (fun θ : Fin d → ℝ => + ∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ + ((m : Fin d → ℕ) i + 1)) + (Icc (0 : Fin d → ℝ) fun _ => 2 * π) := by + refine continuousOn_finsetSum _ fun m _ => + continuousOn_const.mul (continuousOn_finsetProd _ fun i _ => ?_) + refine (((((continuous_apply i).comp (continuous_torusMap_const c R)).continuousOn).sub + continuousOn_const).inv₀ ?_).pow _ + intro θ _ + apply sub_ne_zero.mpr + intro heq + have := norm_torusMap_sub (c := c) (fun _ => hR.le) θ i + have heq' : torusMap c (fun _ => R) θ i = c i := by + simpa only [Function.comp_apply] using heq + rw [heq', sub_self, norm_zero] at this + exact hR.ne' this.symm + exact (hscalar.smul hfθ).integrableOn_compact isCompact_Icc + +omit [CompleteSpace E] in +/-- Bound for the homogeneous Cauchy terms on the distinguished boundary. -/ +private theorem norm_polydiscCauchyTerm_le {d n : ℕ} {f : (Fin d → ℂ) → E} + {c h : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) (θ : Fin d → ℝ) : + ‖polydiscCauchyTerm f c h n (torusMap c (fun _ => R) θ)‖ ≤ + (M * R⁻¹ ^ d) * ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (‖h i‖ * R⁻¹) ^ (m : Fin d → ℕ) i := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans (hM c (by + intro i _ + simp [mem_closedBall, dist_self, hR.le])) + rw [polydiscCauchyTerm, norm_smul] + calc + ‖∑ m : Finset.Nat.antidiagonalTuple d n, + (∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ + ((m : Fin d → ℕ) i + 1)‖ * + ‖f (torusMap c (fun _ => R) θ)‖ + ≤ (∑ m : Finset.Nat.antidiagonalTuple d n, + ‖(∏ i, h i ^ (m : Fin d → ℕ) i) * + ∏ i, (torusMap c (fun _ => R) θ i - c i)⁻¹ ^ + ((m : Fin d → ℕ) i + 1)‖) * M := by + gcongr + · exact norm_sum_le _ _ + · exact hM _ (torusMap_mem_closedPolydisc (fun _ => hR.le) θ) + _ = (M * R⁻¹ ^ d) * ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, (‖h i‖ * R⁻¹) ^ (m : Fin d → ℕ) i := by + rw [Finset.mul_sum, Finset.sum_mul] + apply Finset.sum_congr rfl + intro m _ + simp only [norm_mul, norm_prod, norm_pow, norm_inv, + norm_torusMap_sub (fun _ => hR.le)] + simp_rw [pow_succ, mul_pow] + simp only [Finset.prod_mul_distrib, Finset.prod_const, Finset.card_univ, + Fintype.card_fin] + ring + +omit [CompleteSpace E] in +/-- A term of the Cauchy series, evaluated on a diagonal, is a torus integral. -/ +private theorem polydiscCauchySeries_apply_eq_torusIntegral {d n : ℕ} + {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} {R : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) : + polydiscCauchySeries f c R n (fun _ => h) = + ((2 * π * I : ℂ) ^ d)⁻¹ • + torusIntegral (polydiscCauchyTerm f c h n) c (fun _ => R) := by + let A : ℂ := ((2 * π * I : ℂ) ^ d)⁻¹ + let a : Finset.Nat.antidiagonalTuple d n → ℂ := + fun m => ∏ i, h i ^ (m : Fin d → ℕ) i + let K : Finset.Nat.antidiagonalTuple d n → (Fin d → ℂ) → E := + fun m z => (∏ i, (z i - c i)⁻¹ ^ ((m : Fin d → ℕ) i + 1)) • f z + rw [polydiscCauchySeries_apply] + simp only [polydiscCauchyCoeff] + change (∑ m, a m • (A • torusIntegral (K m) c (fun _ => R))) = + A • torusIntegral (polydiscCauchyTerm f c h n) c (fun _ => R) + have hInt : ∀ m, TorusIntegrable (fun z => a m • K m z) c (fun _ => R) := by + intro m + simpa only [a, K, smul_smul] using + (torusIntegrable_polydiscCauchySummand (f := f) (c := c) (h := h) hR hfc + (m : Fin d → ℕ)) + calc + (∑ m, a m • (A • torusIntegral (K m) c (fun _ => R))) = + A • ∑ m, a m • torusIntegral (K m) c (fun _ => R) := by + rw [Finset.smul_sum] + apply Finset.sum_congr rfl + intro m _ + simp only [smul_smul] + rw [mul_comm] + _ = A • ∑ m, torusIntegral (fun z => a m • K m z) c (fun _ => R) := by + congr 1 + apply Finset.sum_congr rfl + intro m _ + exact (torusIntegral_smul (a m) (K m) c (fun _ => R)).symm + _ = A • torusIntegral (fun z => ∑ m, a m • K m z) c (fun _ => R) := by + rw [torusIntegral_fintype_sum hInt] + _ = A • torusIntegral (polydiscCauchyTerm f c h n) c (fun _ => R) := by + congr 2 + funext z + rw [polydiscCauchyTerm, Finset.sum_smul] + apply Finset.sum_congr rfl + intro m _ + simp only [a, K, smul_smul] + +omit [CompleteSpace E] in +/-- The polydisc Cauchy series sums to the Cauchy integral. -/ +private theorem hasSum_polydiscCauchySeries_integral {d : ℕ} + {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hh : ∀ i, ‖h i‖ < R) (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) : + HasSum (fun n => polydiscCauchySeries f c R n (fun _ => h)) + (((2 * π * I : ℂ) ^ d)⁻¹ • torusIntegral + (fun z => (∏ i, (z i - (c + h) i)⁻¹) • f z) c (fun _ => R)) := by + let q : Fin d → ℝ := fun i => ‖h i‖ * R⁻¹ + let a : ℕ → ℝ := fun n => (M * R⁻¹ ^ d) * + ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, q i ^ (m : Fin d → ℕ) i + have hq0 : ∀ i, 0 ≤ q i := fun i => mul_nonneg (norm_nonneg _) (inv_nonneg.mpr hR.le) + have hq1 : ∀ i, ‖q i‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (hq0 i)] + simp only [q] + rw [← div_eq_mul_inv, div_lt_one hR] + exact hh i + have hgeom : Summable fun n => + ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, q i ^ (m : Fin d → ℕ) i := by + exact (hasSum_antidiagonalTuple_geometric q hq1).summable.congr fun n => + (Finset.sum_finset_coe + (fun m : Fin d → ℕ => ∏ i, q i ^ m i) + (Finset.Nat.antidiagonalTuple d n)).symm + have ha : Summable a := by + change Summable fun n => (M * R⁻¹ ^ d) * + ∑ m : Finset.Nat.antidiagonalTuple d n, + ∏ i, q i ^ (m : Fin d → ℕ) i + exact hgeom.mul_left (M * R⁻¹ ^ d) + have ht := hasSum_torusIntegral_of_uniform (E := E) + (g := fun z => (∏ i, (z i - (c + h) i)⁻¹) • f z) ha + (fun n => torusIntegrable_polydiscCauchyTerm hR hfc) + (fun n θ => by + simpa [a, q] using norm_polydiscCauchyTerm_le hR hM θ) + (fun θ => by + have hz : ∀ i, torusMap c (fun _ => R) θ i ≠ c i := by + intro i heq + have := norm_torusMap_sub (c := c) (fun _ => hR.le) θ i + rw [heq, sub_self, norm_zero] at this + exact hR.ne' this.symm + have hk := hasSum_polydiscCauchyKernel + (z := torusMap c (fun _ => R) θ) (c := c) (h := h) hz (fun i => by + rw [norm_torusMap_sub (c := c) (fun _ => hR.le) θ i] + exact hh i) + simpa [polydiscCauchyTerm] using + hk.smul_const (f (torusMap c (fun _ => R) θ))) + have hs := ht.const_smul (((2 * π * I : ℂ) ^ d)⁻¹) + simpa only [polydiscCauchySeries_apply_eq_torusIntegral hR hfc] using hs + +/-- The Cauchy series converges to the function at every point of the open polydisc. -/ +theorem hasSum_polydiscCauchySeries {d : ℕ} + {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hh : ∀ i, ‖h i‖ < R) (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hfa : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) : + HasSum (fun n => polydiscCauchySeries f c R n (fun _ => h)) (f (c + h)) := by + have H := hasSum_polydiscCauchySeries_integral hR hh hfc hM + rwa [two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul_const hR + (fun i => by simpa using hh i) hfc hfa] at H + +/-- The Cauchy series represents the function on the full open supremum-norm ball, not just the +half-radius ball needed by the original Osgood proof. -/ +theorem hasFPowerSeriesOnBall_polydiscCauchy_full {d : ℕ} + {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hfa : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) : + HasFPowerSeriesOnBall f (polydiscCauchySeries f c R) c (ENNReal.ofReal R) := by + refine ⟨?_, ENNReal.ofReal_pos.mpr hR, ?_⟩ + · apply le_of_forall_lt_imp_le_of_dense + intro q hq + have hqtop : q ≠ ⊤ := ne_top_of_lt hq + have hqR : (q.toNNReal : ℝ) < R := by + have H := (ENNReal.toReal_lt_toReal hqtop ENNReal.ofReal_ne_top).mpr hq + simpa [ENNReal.toReal_ofReal hR.le, ENNReal.coe_toNNReal_eq_toReal] using H + simpa [ENNReal.coe_toNNReal hqtop] using + (polydiscCauchySeries f c R).le_radius_of_summable_norm + (summable_norm_polydiscCauchySeries_mul_pow hR q.toNNReal.coe_nonneg hqR hM) + · intro h hh + let r : ℝ≥0 := ⟨R, hR.le⟩ + have hr : (r : ℝ≥0∞) = ENNReal.ofReal R := by + rw [ENNReal.coe_nnreal_eq] + rfl + rw [← hr, Metric.mem_eball, edist_eq_enorm_sub, sub_zero, enorm_lt_coe] at hh + exact hasSum_polydiscCauchySeries hR + (fun i => (norm_le_pi_norm h i).trans_lt hh) hfc hfa hM + +/-- A continuous, separately analytic function on a closed polydisc is represented on the concentric +polydisc of half the radius by its multivariable Cauchy series. -/ +theorem hasFPowerSeriesOnBall_polydiscCauchy {d : ℕ} + {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hfa : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) : + HasFPowerSeriesOnBall f (polydiscCauchySeries f c R) c + (ENNReal.ofReal (R / 2)) := by + exact (hasFPowerSeriesOnBall_polydiscCauchy_full hR hfc hfa hM).mono + (ENNReal.ofReal_pos.mpr (by positivity)) + (ENNReal.ofReal_le_ofReal (by linarith)) + +/-- On the diagonal, the Cauchy series is the usual Taylor series of iterated Fréchet derivatives. +This uses Mathlib's general coefficient theorem, not a new derivative theory. -/ +theorem polydiscCauchySeries_diag_eq_iteratedFDeriv {d : ℕ} + {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R M : ℝ} (hR : 0 < R) + (hfc : ContinuousOn f (closedPolydisc c (fun _ => R))) + (hfa : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) + (hM : ∀ z ∈ closedPolydisc c (fun _ => R), ‖f z‖ ≤ M) (n : ℕ) (v : Fin d → ℂ) : + polydiscCauchySeries f c R n (fun _ => v) = + (n.factorial : ℂ)⁻¹ • iteratedFDeriv ℂ n f c (fun _ => v) := by + have h := hasFPowerSeriesOnBall_polydiscCauchy_full hR hfc hfa hM + rw [← h.factorial_smul v n, ← Nat.cast_smul_eq_nsmul ℂ, smul_smul, + inv_mul_cancel₀ (Nat.cast_ne_zero.mpr n.factorial_ne_zero), one_smul] + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyTransform.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyTransform.lean new file mode 100644 index 0000000000..d0ef717f7d --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyTransform.lean @@ -0,0 +1,277 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.ParametricIntegral +public import Mathlib.Analysis.SpecialFunctions.Pow.Integral +public import Mathlib.LinearAlgebra.Complex.FiniteDimensional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu + +/-! +# The Cauchy transform in one variable with parameters + +For a compactly supported `C¹` function `g` on `ℂ × G`, the Cauchy transform in the first +variable is `u(z, y) = π⁻¹ ∫ w⁻¹ • g (z - w, y)`. The kernel `w⁻¹` is locally integrable in the +plane, so `u` is real-differentiable with derivative obtained by differentiating under the +integral; the translation structure places the derivative on `g`. The Cauchy–Pompeiu identity +then gives `∂u/∂\bar z = g`, and along the parameter directions the antiholomorphic part of the +derivative of `u` is the Cauchy transform of the corresponding antiholomorphic part of the +derivative of `g`. The transform vanishes on every slice on which `g` vanishes. + +References: [Hörmander][Hormander1973] (1973), Theorem 1.2.2 and Theorem 2.3.1; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Proposition 4.2.2. + +## Main definitions + +* `cauchyTransformFst`: The Cauchy transform in the first variable of a function on `ℂ × G`. + +## Main results + +* `hasFDerivAt_cauchyTransformFst`: **Differentiation of the Cauchy transform.** The derivative is + the Cauchy transform of the derivative. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex MeasureTheory Set Filter Metric +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {G F : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The Cauchy transform in the first variable of a function on `ℂ × G`. -/ +@[expose] def cauchyTransformFst (g : ℂ × G → F) (x : ℂ × G) : F := + (π : ℂ)⁻¹ • ∫ w : ℂ, w⁻¹ • g (x - (w, 0)) + +section Kernel + +omit [NormedSpace ℂ F] [CompleteSpace F] in +/-- The Cauchy kernel is locally integrable in the plane. -/ +theorem integrable_indicator_closedBall_mul_inv_norm (C R : ℝ) : + Integrable ((closedBall (0 : ℂ) R).indicator fun w => C * ‖w‖⁻¹) := by + have hmeas : AEStronglyMeasurable (fun w : ℂ => C * ‖w‖⁻¹) volume := + (measurable_const.mul measurable_norm.inv).aestronglyMeasurable + have h : IntegrableOn (fun w : ℂ => C * ‖w‖⁻¹) (ball 0 (R + 1)) := by + refine integrableOn_ball_of_norm_le_rpow (E := ℂ) (μ := volume) (C := |C|) (α := 1) ?_ ?_ + (ae_of_all _ fun w => ?_) hmeas + · rw [Complex.finrank_real_complex]; norm_num + · rw [Complex.finrank_real_complex]; norm_num + · rw [Real.rpow_neg_one, norm_mul, Real.norm_eq_abs, norm_inv, norm_norm] + exact (h.mono_set (closedBall_subset_ball (lt_add_one R))).integrable_indicator + measurableSet_closedBall + +omit [CompleteSpace F] in +/-- A kernel-type bound: a function of the form `w⁻¹ • h w` with `h` bounded and vanishing outside a +closed ball is integrable. -/ +theorem integrable_inv_smul_of_bound {h : ℂ → F} (hmeas : AEStronglyMeasurable h volume) {C R : ℝ} + (hC : ∀ w, ‖h w‖ ≤ C) (hz : ∀ w, R < ‖w‖ → h w = 0) : + Integrable fun w : ℂ => w⁻¹ • h w := by + refine Integrable.mono' (integrable_indicator_closedBall_mul_inv_norm C R) + (measurable_inv.aestronglyMeasurable.smul hmeas) (ae_of_all _ fun w => ?_) + by_cases hw : w ∈ closedBall (0 : ℂ) R + · rw [indicator_of_mem hw, norm_smul, norm_inv, mul_comm] + exact mul_le_mul_of_nonneg_right (hC w) (inv_nonneg.mpr (norm_nonneg _)) + · rw [mem_closedBall, dist_zero_right, not_le] at hw + rw [indicator_of_notMem (by rwa [mem_closedBall, dist_zero_right, not_le]), hz w hw, + smul_zero, norm_zero] + +end Kernel + +section Support + +variable {g : ℂ × G → F} + +omit [NormedSpace ℂ G] [NormedSpace ℂ F] [CompleteSpace F] in +/-- Points far in the first variable leave the support after translation. -/ +theorem sub_notMem_of_norm_gt {R' : ℝ} (hR : tsupport g ⊆ closedBall 0 R') {x₀ x : ℂ × G} + (hx : x ∈ ball x₀ 1) {w : ℂ} (hw : R' + ‖x₀‖ + 1 < ‖w‖) : x - (w, 0) ∉ tsupport g := by + intro hmem + have h1 := hR hmem + rw [mem_closedBall, dist_zero_right] at h1 + have hx' : ‖x‖ < ‖x₀‖ + 1 := by + have := mem_ball.mp hx + rw [dist_eq_norm] at this + calc ‖x‖ = ‖(x - x₀) + x₀‖ := by rw [sub_add_cancel] + _ ≤ ‖x - x₀‖ + ‖x₀‖ := norm_add_le _ _ + _ < ‖x₀‖ + 1 := by linarith + have h2 : ‖w‖ - ‖x‖ ≤ ‖x - (w, 0)‖ := by + have : ‖((w, 0) : ℂ × G)‖ = ‖w‖ := by rw [Prod.norm_mk, norm_zero, max_eq_left (norm_nonneg _)] + rw [← this, norm_sub_rev] + exact norm_sub_norm_le _ _ + linarith + +omit [NormedSpace ℂ G] [NormedSpace ℂ F] [CompleteSpace F] in +/-- The translated function vanishes for large `w`. -/ +theorem eq_zero_of_norm_gt {R' : ℝ} (hR : tsupport g ⊆ closedBall 0 R') {x₀ x : ℂ × G} + (hx : x ∈ ball x₀ 1) {w : ℂ} (hw : R' + ‖x₀‖ + 1 < ‖w‖) : g (x - (w, 0)) = 0 := + image_eq_zero_of_notMem_tsupport (sub_notMem_of_norm_gt hR hx hw) + +omit [CompleteSpace F] in +/-- The derivative of the translated function vanishes for large `w`. -/ +theorem fderiv_eq_zero_of_norm_gt' {R' : ℝ} (hR : tsupport g ⊆ closedBall 0 R') {x₀ x : ℂ × G} + (hx : x ∈ ball x₀ 1) {w : ℂ} (hw : R' + ‖x₀‖ + 1 < ‖w‖) : fderiv ℝ g (x - (w, 0)) = 0 := + image_eq_zero_of_notMem_tsupport fun h => + sub_notMem_of_norm_gt hR hx hw (tsupport_fderiv_subset ℝ h) + +end Support + +section Derivative + +variable {g : ℂ × G → F} + +omit [CompleteSpace F] in +/-- Integrability of the derivative kernel. -/ +theorem integrable_inv_smul_fderiv_sub (hg : ContDiff ℝ 1 g) (hs : HasCompactSupport g) + (x₀ : ℂ × G) : Integrable fun w : ℂ => w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) := by + obtain ⟨R', hR⟩ := hs.isBounded.subset_closedBall 0 + obtain ⟨C, hC⟩ := (hs.fderiv ℝ).exists_bound_of_continuous (hg.continuous_fderiv one_ne_zero) + refine integrable_inv_smul_of_bound (R := R' + ‖x₀‖ + 1) + (((hg.continuous_fderiv one_ne_zero).comp (by fun_prop)).aestronglyMeasurable) + (fun w => hC _) fun w hw => fderiv_eq_zero_of_norm_gt' hR (mem_ball_self one_pos) hw + +omit [CompleteSpace F] in +/-- Integrability of the Cauchy transform integrand. -/ +theorem integrable_inv_smul_sub (hg : ContDiff ℝ 1 g) (hs : HasCompactSupport g) (x₀ : ℂ × G) : + Integrable fun w : ℂ => w⁻¹ • g (x₀ - (w, 0)) := by + obtain ⟨R', hR⟩ := hs.isBounded.subset_closedBall 0 + obtain ⟨C, hC⟩ := hs.exists_bound_of_continuous hg.continuous + refine integrable_inv_smul_of_bound (R := R' + ‖x₀‖ + 1) + ((hg.continuous.comp (by fun_prop)).aestronglyMeasurable) + (fun w => hC _) fun w hw => eq_zero_of_norm_gt hR (mem_ball_self one_pos) hw + +omit [CompleteSpace F] in +/-- **Differentiation of the Cauchy transform.** The derivative is the Cauchy transform of the +derivative. -/ +theorem hasFDerivAt_cauchyTransformFst (hg : ContDiff ℝ 1 g) (hs : HasCompactSupport g) + (x₀ : ℂ × G) : + HasFDerivAt (cauchyTransformFst g) + ((π : ℂ)⁻¹ • ∫ w : ℂ, w⁻¹ • fderiv ℝ g (x₀ - (w, 0))) x₀ := by + obtain ⟨R', hR⟩ := hs.isBounded.subset_closedBall 0 + obtain ⟨C, hC⟩ := (hs.fderiv ℝ).exists_bound_of_continuous (hg.continuous_fderiv one_ne_zero) + have hmain : HasFDerivAt (fun x : ℂ × G => ∫ w : ℂ, w⁻¹ • g (x - (w, 0))) + (∫ w : ℂ, w⁻¹ • fderiv ℝ g (x₀ - (w, 0))) x₀ := by + refine hasFDerivAt_integral_of_dominated_of_fderiv_le (𝕜 := ℝ) + (F' := fun x w => w⁻¹ • fderiv ℝ g (x - (w, 0))) + (bound := (closedBall (0 : ℂ) (R' + ‖x₀‖ + 1)).indicator fun w => C * ‖w‖⁻¹) + (ball_mem_nhds x₀ one_pos) ?_ (integrable_inv_smul_sub hg hs x₀) ?_ ?_ + (integrable_indicator_closedBall_mul_inv_norm _ _) ?_ + · exact Eventually.of_forall fun x => + measurable_inv.aestronglyMeasurable.smul + ((hg.continuous.comp (by fun_prop)).aestronglyMeasurable) + · exact measurable_inv.aestronglyMeasurable.smul + (((hg.continuous_fderiv one_ne_zero).comp (by fun_prop)).aestronglyMeasurable) + · refine ae_of_all _ fun w x hx => ?_ + by_cases hw : w ∈ closedBall (0 : ℂ) (R' + ‖x₀‖ + 1) + · rw [indicator_of_mem hw, norm_smul, norm_inv, mul_comm] + exact mul_le_mul_of_nonneg_right (hC _) (inv_nonneg.mpr (norm_nonneg _)) + · rw [mem_closedBall, dist_zero_right, not_le] at hw + rw [indicator_of_notMem (by rwa [mem_closedBall, dist_zero_right, not_le]), + fderiv_eq_zero_of_norm_gt' hR hx hw, smul_zero, norm_zero] + · refine ae_of_all _ fun w x _ => ?_ + have h1 : HasFDerivAt (fun x : ℂ × G => x - (w, 0)) (ContinuousLinearMap.id ℝ (ℂ × G)) x := + (hasFDerivAt_id x).sub_const _ + have h2 := ((hg.differentiable one_ne_zero) _).hasFDerivAt.comp x h1 + rw [ContinuousLinearMap.comp_id] at h2 + exact h2.const_smul w⁻¹ + exact hmain.const_smul _ + +omit [CompleteSpace F] in +/-- The derivative of the Cauchy transform applied to a direction. -/ +theorem fderiv_cauchyTransformFst_apply (hg : ContDiff ℝ 1 g) (hs : HasCompactSupport g) + (x₀ v : ℂ × G) : + fderiv ℝ (cauchyTransformFst g) x₀ v = (π : ℂ)⁻¹ • ∫ w : ℂ, w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) v + := by + rw [(hasFDerivAt_cauchyTransformFst hg hs x₀).fderiv, smul_apply, + ContinuousLinearMap.integral_apply (integrable_inv_smul_fderiv_sub hg hs x₀)] + congr 1 + +omit [CompleteSpace F] in +/-- The antiholomorphic part of the derivative of the Cauchy transform along a direction is the +Cauchy transform of the antiholomorphic part of the derivative. -/ +theorem dbarAlong_fderiv_cauchyTransformFst (hg : ContDiff ℝ 1 g) (hs : HasCompactSupport g) + (x₀ v : ℂ × G) : + dbarAlong (fderiv ℝ (cauchyTransformFst g) x₀) v = + (π : ℂ)⁻¹ • ∫ w : ℂ, w⁻¹ • dbarAlong (fderiv ℝ g (x₀ - (w, 0))) v := by + have hint := integrable_inv_smul_fderiv_sub hg hs x₀ + have h1 : Integrable fun w : ℂ => w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) v := by + simpa only [FunLike.coe_smul, Pi.smul_apply] using hint.apply_continuousLinearMap v + have h2 : Integrable fun w : ℂ => w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) (I • v) := by + simpa only [FunLike.coe_smul, Pi.smul_apply] using hint.apply_continuousLinearMap (I • v) + have h1' : Integrable fun w : ℂ => (2 : ℂ)⁻¹ • (w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) v) := h1.smul _ + have h2' : Integrable fun w : ℂ => + ((2 : ℂ)⁻¹ * I) • (w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) (I • v)) := h2.smul _ + have hpt : ∀ w : ℂ, w⁻¹ • ((2 : ℂ)⁻¹ • (fderiv ℝ g (x₀ - (w, 0)) v + + I • fderiv ℝ g (x₀ - (w, 0)) (I • v))) = + (2 : ℂ)⁻¹ • (w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) v) + + ((2 : ℂ)⁻¹ * I) • (w⁻¹ • fderiv ℝ g (x₀ - (w, 0)) (I • v)) := by + intro w + module + unfold dbarAlong + rw [fderiv_cauchyTransformFst_apply hg hs, fderiv_cauchyTransformFst_apply hg hs] + simp_rw [hpt] + rw [integral_add h1' h2', integral_smul, integral_smul] + module + +omit [NormedSpace ℂ G] [CompleteSpace F] in +/-- The Cauchy transform vanishes on a slice where `g` vanishes. -/ +theorem cauchyTransformFst_eq_zero {y : G} (hy : ∀ z : ℂ, g (z, y) = 0) (z : ℂ) : + cauchyTransformFst g (z, y) = 0 := by + unfold cauchyTransformFst + have : ∀ w : ℂ, w⁻¹ • g (z - w, y) = 0 := fun w => by rw [hy, smul_zero] + simp only [Prod.mk_sub_mk, sub_zero, this, integral_zero, smul_zero] + +end Derivative + +section Pompeiu + +variable {h : ℂ × G → F} + +/-- The Cauchy–Pompeiu identity in the first variable with parameters: the Cauchy transform of +`∂h/∂\bar z₁` recovers `h`. -/ +theorem integral_inv_smul_dbarAlong_fderiv_sub (hh : ContDiff ℝ 1 h) (hs : HasCompactSupport h) + (x₀ : ℂ × G) : + ∫ w : ℂ, w⁻¹ • dbarAlong (fderiv ℝ h (x₀ - (w, 0))) ((1 : ℂ), (0 : G)) = (π : ℂ) • h x₀ := by + set ψ : ℂ → F := fun w => h (x₀ - (w, 0)) with hψ + have hiso : Isometry fun w : ℂ => x₀ - (w, 0) := by + refine Isometry.of_dist_eq fun w w' => ?_ + rw [dist_eq_norm, dist_eq_norm, sub_sub_sub_cancel_left, Prod.mk_sub_mk, sub_zero, Prod.norm_mk, + norm_zero, max_eq_left (norm_nonneg _), norm_sub_rev] + have hψs : HasCompactSupport ψ := hs.comp_isClosedEmbedding hiso.isClosedEmbedding + have hψc : ContDiff ℝ 1 ψ := + hh.comp (contDiff_const.sub (ContinuousLinearMap.inl ℝ ℂ G).contDiff) + have hder : ∀ w : ℂ, fderiv ℝ ψ w = + (fderiv ℝ h (x₀ - (w, 0))).comp (-(ContinuousLinearMap.inl ℝ ℂ G)) := by + intro w + have h1 : HasFDerivAt (fun w : ℂ => x₀ - (w, 0)) (-(ContinuousLinearMap.inl ℝ ℂ G)) w := + (ContinuousLinearMap.inl ℝ ℂ G).hasFDerivAt.const_sub x₀ + exact (((hh.differentiable one_ne_zero) _).hasFDerivAt.comp w h1).fderiv + have hdbar : ∀ w : ℂ, dbarAlong (fderiv ℝ ψ w) 1 = + -dbarAlong (fderiv ℝ h (x₀ - (w, 0))) ((1 : ℂ), (0 : G)) := by + intro w + rw [hder] + simp only [dbarAlong, ContinuousLinearMap.comp_apply, neg_apply, + ContinuousLinearMap.inl_apply, map_neg, smul_eq_mul, mul_one, Prod.smul_mk, smul_zero, + smul_neg] + module + have := integral_inv_smul_dbarAlong_fderiv hψc hψs + simp_rw [hdbar, smul_neg, integral_neg] at this + rw [neg_eq_iff_eq_neg.mp this, neg_neg, hψ] + simp only + rw [show ((0 : ℂ), (0 : G)) = 0 from rfl, sub_zero] + +end Pompeiu + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean new file mode 100644 index 0000000000..7e904b2791 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean @@ -0,0 +1,121 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.LocallyConvex.BalancedCoreHull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt + +/-! +# Circular sets and balanced geometry + +Circular symmetry rotates all coordinates by the same scalar. This is weaker than Reinhardt +symmetry. Openness, connectedness and nonemptiness remain separate properties. Balanced sets and +their hulls use Mathlib's `Balanced` and `balancedHull`. Reference: +[Scheidemann][Scheidemann2005] (2005), Section 2.1 and Corollary 3.3.3. + +## Main definitions + +* `IsCircular`: Invariance under one common complex rotation, about the origin. + +## Main results + +* `isCircular_of_balanced`: Balanced sets are circular, including the empty set. +* `isCircular_balancedHull`: Mathlib's balanced hull is circular. +* `isPathConnected_balancedHull`: A nonempty balanced hull is path connected, independently of the + original set's connectedness. +* `IsReinhardt.isCircular`: Independent coordinate rotations include common rotations. +* `IsCompleteReinhardt.balanced`: Complete Reinhardt sets are balanced for complex scalar + multiplication. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set Metric + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] {U V : Set E} + +/-- Invariance under one common complex rotation, about the origin. -/ +@[expose] def IsCircular (U : Set E) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃c : ℂ⦄, ‖c‖ = 1 → c • z ∈ U + +/-- Multiplication by a complex scalar of norm one preserves a circular set. -/ +theorem IsCircular.smul_mem (hU : IsCircular U) {z : E} (hz : z ∈ U) + {c : ℂ} (hc : ‖c‖ = 1) : c • z ∈ U := hU hz hc + +/-- The empty set is circular. -/ +theorem isCircular_empty : IsCircular (∅ : Set E) := fun _ h => h.elim + +/-- The whole space is circular. -/ +theorem isCircular_univ : IsCircular (univ : Set E) := fun _ _ _ _ => mem_univ _ + +/-- Intersections preserve circular symmetry. -/ +theorem IsCircular.inter (hU : IsCircular U) (hV : IsCircular V) : IsCircular (U ∩ V) := + fun _ hz _ hc => ⟨hU hz.1 hc, hV hz.2 hc⟩ + +/-- Unions preserve circular symmetry. -/ +theorem IsCircular.union (hU : IsCircular U) (hV : IsCircular V) : IsCircular (U ∪ V) := + fun _ hz _ hc => hz.elim (fun h => Or.inl (hU h hc)) (fun h => Or.inr (hV h hc)) + +/-- Balanced sets are circular, including the empty set. -/ +theorem isCircular_of_balanced (hU : Balanced ℂ U) : IsCircular U := + fun _ hz _ hc => (balanced_iff_smul_mem.mp hU) hc.le hz + +/-- Mathlib's balanced hull is circular. -/ +theorem isCircular_balancedHull (U : Set E) : IsCircular (balancedHull ℂ U) := + isCircular_of_balanced (balancedHull.balanced U) + +/-- A nonempty balanced hull is path connected, independently of the original set's connectedness. +This follows by contraction along the real radial segments. -/ +theorem isPathConnected_balancedHull (hne : U.Nonempty) : IsPathConnected (balancedHull ℂ U) := by + let : NormedSpace ℝ E := NormedSpace.restrictScalars ℝ ℂ E + have hB := balancedHull.balanced (𝕜 := ℂ) U + have hs : StarConvex ℝ (0 : E) (balancedHull ℂ U) := by + intro z hz a b ha hb hab + simp only [smul_zero, zero_add] + rw [RCLike.real_smul_eq_coe_smul (K := ℂ)] + apply (balanced_iff_smul_mem.mp hB) _ hz + simpa [abs_of_nonneg hb] using (show b ≤ 1 by linarith) + exact hs.isPathConnected (hB.zero_mem (hne.mono (subset_balancedHull ℂ))) + +/-- Linear inverse images preserve circular symmetry. -/ +theorem IsCircular.preimage (L : E →L[ℂ] F) {V : Set F} (hV : IsCircular V) : + IsCircular (L ⁻¹' V) := by + intro z hz c hc + change L (c • z) ∈ V + rw [map_smul] + exact hV hz hc + +/-- Balls about zero are circular for any complex norm, without a coordinate assumption. -/ +theorem isCircular_ball (r : ℝ) : IsCircular (ball (0 : E) r) := by + intro z hz c hc + simpa only [mem_ball, dist_zero_right, norm_smul, hc, one_mul] using hz + +/-- Independent coordinate rotations include common rotations. -/ +theorem IsReinhardt.isCircular {ι : Type*} [Fintype ι] {U : Set (ι → ℂ)} + (hU : IsReinhardt U) : IsCircular U := by + intro z hz c hc + exact hU hz (fun i => by simp [hc]) + +/-- Complete Reinhardt sets are balanced for complex scalar multiplication. -/ +theorem IsCompleteReinhardt.balanced {ι : Type*} [Fintype ι] {U : Set (ι → ℂ)} + (hU : IsCompleteReinhardt U) : Balanced ℂ U := by + rw [balanced_iff_smul_mem] + intro c hc z hz + apply hU hz + intro i + simpa only [Pi.smul_apply, norm_smul, one_mul] using + mul_le_mul_of_nonneg_right hc (norm_nonneg (z i)) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CircularContinuation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CircularContinuation.lean new file mode 100644 index 0000000000..8f85e3893c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CircularContinuation.lean @@ -0,0 +1,238 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.CPolynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy + +/-! +# Homogeneous expansion and continuation on circular domains + +The terms are diagonals of Mathlib continuous multilinear Taylor coefficients, hence homogeneous +polynomials. Convergence is grouped by total degree, not by individual coordinate monomials. +Cauchy projections identify the terms on circular domains, and geometric majorants give locally +uniform convergence on the balanced hull. Reference: [Scheidemann][Scheidemann2005] (2005), +Theorem 2.1.8. Banach-valued targets are allowed. + +## Main results + +`homogeneousTerm` is the degree-`k` diagonal of a multilinear Taylor series. +`IsCircular.hasSumLocallyUniformlyOn_homogeneousTerm_balancedHull` is locally uniform convergence of +the homogeneous expansion on the balanced hull. `exists_extension_balancedHull` is continuation from +a circular domain to its balanced hull. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric Complex +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The homogeneous term of degree `k` of a multilinear power series centered at zero. -/ +@[expose] def homogeneousTerm (p : FormalMultilinearSeries ℂ E F) (k : ℕ) (z : E) : F := + p k (fun _ => z) + +omit [FiniteDimensional ℂ E] [CompleteSpace F] in +/-- A homogeneous term is the corresponding multilinear map on the constant tuple. -/ +theorem homogeneousTerm_apply (p : FormalMultilinearSeries ℂ E F) (k : ℕ) (z : E) : + homogeneousTerm p k z = p k (fun _ => z) := rfl + +omit [FiniteDimensional ℂ E] [CompleteSpace F] in +/-- The degree is expressed by the usual scalar homogeneity identity. -/ +theorem homogeneousTerm_smul (p : FormalMultilinearSeries ℂ E F) (k : ℕ) (c : ℂ) (z : E) : + homogeneousTerm p k (c • z) = c ^ k • homogeneousTerm p k z := by + simpa [homogeneousTerm] using (p k).map_smul_univ (fun _ => c) (fun _ => z) + +omit [FiniteDimensional ℂ E] [CompleteSpace F] in +/-- A homogeneous Taylor term is analytic on the whole ambient space. -/ +theorem analyticOnNhd_homogeneousTerm (p : FormalMultilinearSeries ℂ E F) (k : ℕ) + (S : Set E) : AnalyticOnNhd ℂ (homogeneousTerm p k) S := by + intro z _ + exact (p k).analyticAt.comp (analyticAt_pi_iff.mpr fun _ => analyticAt_id) + +/-- On a circular domain, the homogeneous Taylor terms are the Cauchy projections under simultaneous +rotation of all coordinates. -/ +theorem homogeneousTerm_eq_circleIntegral {U : Set E} (ho : IsOpen U) + (hc : IsPreconnected U) (hrot : IsCircular U) (hzero : (0 : E) ∈ U) + {f : E → F} (hf : AnalyticOnNhd ℂ f U) {p : FormalMultilinearSeries ℂ E F} + (hp : HasFPowerSeriesAt f p 0) (k : ℕ) : + EqOn (homogeneousTerm p k) + (fun z => (2 * Real.pi * I : ℂ)⁻¹ • + ∮ w in C(0, 1), w⁻¹ ^ k • w⁻¹ • f (w • z)) U := by + let H : E × ℂ → F := fun q => q.2⁻¹ ^ k • q.2⁻¹ • f (q.2 • q.1) + have hH : AnalyticOnNhd ℂ H {q | q.2 ≠ 0 ∧ q.2 • q.1 ∈ U} := by + intro q hq + exact ((analyticAt_snd.inv hq.1).pow k).smul + ((analyticAt_snd.inv hq.1).smul + ((hf _ hq.2).comp_of_eq (analyticAt_snd.smul analyticAt_fst) rfl)) + have hproj := (analyticOnNhd_circleIntegral_kernel (c := 0) ho hH + (by norm_num : (0 : ℝ) ≤ 1) + (fun z hz w hw => by + have hw' : ‖w‖ = 1 := by simpa using hw + exact ⟨norm_ne_zero_iff.mp (by rw [hw']; norm_num), + hrot.smul_mem hz hw'⟩)).const_smul + (c := (2 * Real.pi * I : ℂ)⁻¹) + apply DifferentiableOn.eqOn_of_preconnected_of_eventuallyEq ho hc + (analyticOnNhd_homogeneousTerm p k U).differentiableOn hproj.differentiableOn hzero + obtain ⟨r, hr, hball⟩ := Metric.isOpen_iff.mp ho 0 hzero + filter_upwards [ball_mem_nhds (0 : E) hr] with z hz + let L : ℂ →L[ℂ] E := (ContinuousLinearMap.id ℂ ℂ).smulRight z + have hline : HasFPowerSeriesAt (fun w : ℂ => f (w • z)) + (p.compContinuousLinearMap L) 0 := by + have hp' : HasFPowerSeriesAt f p (L 0) := by simpa [L] using hp + exact hp'.compContinuousLinearMap + have hd : DifferentiableOn ℂ (fun w : ℂ => f (w • z)) (closedBall 0 1) := by + intro w hw + apply ((hf _ (hball ?_)).differentiableAt.comp w L.differentiableAt).differentiableWithinAt + change w • z ∈ ball 0 r + rw [mem_ball_zero_iff, norm_smul] + exact (mul_le_of_le_one_left (norm_nonneg z) (mem_closedBall_zero_iff.mp hw)).trans_lt + (mem_ball_zero_iff.mp hz) + have he := hline.eq_formalMultilinearSeries + (hd.hasFPowerSeriesOnBall (R := 1) (by norm_num)).hasFPowerSeriesAt + have he' := congrArg (fun q : FormalMultilinearSeries ℂ ℂ F => q k (fun _ => 1)) he + simpa only [FormalMultilinearSeries.compContinuousLinearMap_apply, L, + Function.comp_def, Pi.smul_apply, NNReal.coe_one, + ContinuousLinearMap.smulRight_apply, ContinuousLinearMap.id_apply, one_smul, + homogeneousTerm, cauchyPowerSeries_apply, sub_zero, one_div, H] using he' + +omit [FiniteDimensional ℂ E] in +/-- Openness lets every point of a balanced hull be represented by a strict, nonzero contraction of +a point of the original set. -/ +private theorem exists_strict_contraction {U : Set E} (ho : IsOpen U) + (hzero : (0 : E) ∈ U) {x : E} (hx : x ∈ balancedHull ℂ U) : + ∃ (c : ℂ) (z : E), c ≠ 0 ∧ ‖c‖ < 1 ∧ z ∈ U ∧ c • z = x := by + obtain ⟨d, hd, y, hy, rfl⟩ := mem_balancedHull_iff.mp hx + by_cases hd0 : d = 0 + · exact ⟨1 / 2, 0, by norm_num, by norm_num, hzero, by simp [hd0]⟩ + have hn : {t : ℝ | (t : ℂ) • y ∈ U} ∈ 𝓝 1 := by + exact (continuous_ofReal.smul continuous_const).continuousAt.preimage_mem_nhds + (ho.mem_nhds (by simpa using hy)) + obtain ⟨ε, hε, hsub⟩ := Metric.mem_nhds_iff.mp hn + let t : ℝ := 1 + ε / 2 + have ht : 1 < t := by dsimp [t]; linarith + have ht0 : 0 < t := zero_lt_one.trans ht + have hty : (t : ℂ) • y ∈ U := hsub (by + simp only [mem_ball, Real.dist_eq, t, add_sub_cancel_left, abs_of_pos (half_pos hε)] + exact half_lt_self hε) + refine ⟨d / t, (t : ℂ) • y, div_ne_zero hd0 (ofReal_ne_zero.mpr ht0.ne'), ?_, hty, ?_⟩ + · rw [norm_div, Complex.norm_of_nonneg ht0.le] + exact (div_lt_one ht0).mpr (hd.trans_lt ht) + · rw [smul_smul, div_mul_cancel₀ _ (ofReal_ne_zero.mpr ht0.ne')] + +/-- Cauchy projections give a locally summable geometric majorant throughout the balanced hull of a +circular domain. -/ +private theorem hasSumLocallyUniformlyOn_homogeneousTerm {U : Set E} (ho : IsOpen U) + (hc : IsPreconnected U) (hrot : IsCircular U) (hzero : (0 : E) ∈ U) + {f : E → F} (hf : AnalyticOnNhd ℂ f U) {p : FormalMultilinearSeries ℂ E F} + (hp : HasFPowerSeriesAt f p 0) : + HasSumLocallyUniformlyOn (homogeneousTerm p) (fun z => ∑' k, homogeneousTerm p k z) + (balancedHull ℂ U) := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro x hx + obtain ⟨c, z, hc0, hc1, hz, rfl⟩ := exists_strict_contraction ho hzero hx + have hn : ∀ᶠ y in 𝓝 z, ∀ w ∈ sphere (0 : ℂ) 1, w • y ∈ U := by + apply (isCompact_sphere (0 : ℂ) 1).eventually_forall_of_forall_eventually + intro w hw + apply (continuous_snd.smul continuous_fst).continuousAt.preimage_mem_nhds + exact ho.mem_nhds (hrot.smul_mem hz (by simpa using hw)) + obtain ⟨δ, hδ, hball⟩ := nhds_basis_closedBall.mem_iff.mp hn + let K := (fun q : E × ℂ => q.2 • q.1) '' (closedBall z δ ×ˢ sphere 0 1) + have hK : IsCompact K := ((isCompact_closedBall z δ).prod (isCompact_sphere 0 1)).image + (continuous_snd.smul continuous_fst) + have hKU : K ⊆ U := by + rintro _ ⟨⟨y, w⟩, ⟨hy, hw⟩, rfl⟩ + exact hball hy w hw + obtain ⟨M, hM⟩ := hK.bddAbove_image (hf.continuousOn.mono hKU).norm + let C := max M 0 + have hbound (y : E) (hy : y ∈ closedBall z δ) (k : ℕ) : ‖homogeneousTerm p k y‖ ≤ C := by + have hyU : y ∈ U := by simpa using hball hy 1 (by simp) + rw [homogeneousTerm_eq_circleIntegral ho hc hrot hzero hf hp k hyU] + apply (circleIntegral.norm_two_pi_i_inv_smul_integral_le_of_norm_le_const + (by norm_num : (0 : ℝ) ≤ 1) ?_).trans_eq (one_mul C) + intro w hw + have hw' : ‖w‖ = 1 := by simpa using hw + simp only [norm_smul, norm_pow, norm_inv, hw', inv_one, one_pow, one_mul] + exact (hM ⟨w • y, ⟨(y, w), ⟨hy, hw⟩, rfl⟩, rfl⟩).trans (le_max_left _ _) + let N := {y : E | c⁻¹ • y ∈ ball z δ} + have hN : N ∈ 𝓝 (c • z) := by + apply (continuous_const.smul continuous_id).continuousAt.preimage_mem_nhds + simpa [hc0] using ball_mem_nhds z hδ + have hterm (k : ℕ) (y : E) (hy : y ∈ N) : + ‖homogeneousTerm p k y‖ ≤ C * ‖c‖ ^ k := by + have he : y = c • (c⁻¹ • y) := by simp [hc0] + calc + ‖homogeneousTerm p k y‖ = ‖c‖ ^ k * ‖homogeneousTerm p k (c⁻¹ • y)‖ := by + conv_lhs => rw [he, homogeneousTerm_smul] + rw [norm_smul, norm_pow] + _ ≤ ‖c‖ ^ k * C := mul_le_mul_of_nonneg_left + (hbound _ (ball_subset_closedBall hy) k) (by positivity) + _ = C * ‖c‖ ^ k := mul_comm _ _ + refine ⟨N, mem_nhdsWithin_of_mem_nhds hN, ?_⟩ + exact hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + (tendstoUniformlyOn_tsum ((summable_geometric_of_lt_one (norm_nonneg c) hc1).mul_left C) + hterm) + +/-- Homogeneous Taylor expansion on a circular domain extends to its balanced hull. Cauchy +projections under common rotations and compact majorants on radial contractions give +convergence; analytic uniqueness identifies the sum with the original function. The chosen +Taylor series is supplied explicitly. -/ +theorem IsCircular.hasSumLocallyUniformlyOn_homogeneousTerm_balancedHull {U : Set E} (ho : IsOpen U) + (hc : IsPreconnected U) (hrot : IsCircular U) (hzero : (0 : E) ∈ U) + {f : E → F} (hf : AnalyticOnNhd ℂ f U) {p : FormalMultilinearSeries ℂ E F} + (hp : HasFPowerSeriesAt f p 0) : + HasSumLocallyUniformlyOn (homogeneousTerm p) f U ∧ + HasSumLocallyUniformlyOn (homogeneousTerm p) (fun z => ∑' k, homogeneousTerm p k z) + (balancedHull ℂ U) ∧ + AnalyticOnNhd ℂ (fun z => ∑' k, homogeneousTerm p k z) (balancedHull ℂ U) := by + have hs := hasSumLocallyUniformlyOn_homogeneousTerm ho hc hrot hzero hf hp + have ha : AnalyticOnNhd ℂ (fun z => ∑' k, homogeneousTerm p k z) (balancedHull ℂ U) := by + apply hs.analyticOnNhd_of_finiteDimensional _ (ho.balancedHull hzero) + filter_upwards with s + exact Finset.analyticOnNhd_fun_sum s fun k _ => + analyticOnNhd_homogeneousTerm p k _ + have he : EqOn (fun z => ∑' k, homogeneousTerm p k z) f U := by + apply DifferentiableOn.eqOn_of_preconnected_of_eventuallyEq ho hc + (ha.mono (subset_balancedHull ℂ)).differentiableOn hf.differentiableOn hzero + filter_upwards [hp.eventually_hasSum] with z hz + simpa only [homogeneousTerm, zero_add] using hz.tsum_eq + exact ⟨(hs.mono (subset_balancedHull ℂ)).congr_right (fun z hz => he hz), hs, ha⟩ + +/-- A holomorphic function on a circular domain containing zero extends to its balanced hull. +Depends on homogeneous expansion. -/ +theorem exists_extension_balancedHull {U : Set E} (ho : IsOpen U) + (hc : IsPreconnected U) (hrot : IsCircular U) (hzero : (0 : E) ∈ U) + {f : E → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g (balancedHull ℂ U) ∧ EqOn g f U := by + obtain ⟨p, hp⟩ := hf 0 hzero + obtain ⟨hs, _, ha⟩ + := IsCircular.hasSumLocallyUniformlyOn_homogeneousTerm_balancedHull ho hc hrot hzero hf hp + exact ⟨_, ha, fun z hz => (hs.hasSum hz).tsum_eq⟩ + +/-- Extensions to the balanced hull are unique by the identity theorem and geometry. -/ +theorem eqOn_balancedHull_of_eqOn {U : Set E} (ho : IsOpen U) (hzero : (0 : E) ∈ U) + {f g : E → F} (hf : AnalyticOnNhd ℂ f (balancedHull ℂ U)) + (hg : AnalyticOnNhd ℂ g (balancedHull ℂ U)) (he : EqOn f g U) : + EqOn f g (balancedHull ℂ U) := + DifferentiableOn.eqOn_of_preconnected_of_eqOn (ho.balancedHull hzero) + (isPathConnected_balancedHull ⟨0, hzero⟩).isConnected.isPreconnected + hf.differentiableOn hg.differentiableOn ho ⟨0, hzero⟩ (subset_balancedHull ℂ) he + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean new file mode 100644 index 0000000000..a814576b6c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Uniqueness +public import Mathlib.Analysis.LocallyConvex.Separation +public import Mathlib.Analysis.RCLike.Extend +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Common extension domains inside a complex vector space + +`IsCommonAnalyticExtension U V` says that `U ⊆ V` and every scalar analytic function on `U` +extends to `V`. It does not impose openness, connectedness, or maximality, and does not define +an abstract envelope. Simultaneous extension cannot introduce new scalar values, by extending +the reciprocal of a nowhere-zero function. + +Convex separation also bounds common extension domains by the real convex hull. References: +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Proposition 2.9.2 and Corollary 2.9.3, +specialized to domains in a complex normed space. + +## Main definitions + +* `IsCommonAnalyticExtension`: Every scalar analytic function on `U` extends to the larger set `V`. + +## Main results + +* `IsCommonAnalyticExtension.trans`: Common extension composes. +* `IsCommonAnalyticExtension.image_eq`: A scalar analytic function on a connected common extension + domain has exactly its original range. +* `IsCommonAnalyticExtension.subset_convexHull`: A common extension domain lies in the real convex + hull of the original domain. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public section + +open Filter Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Every scalar analytic function on `U` extends to the larger set `V`. Topological hypotheses and +maximality are separate; no extension outside the ambient space is intended. -/ +@[expose] def IsCommonAnalyticExtension (U V : Set E) : Prop := + U ⊆ V ∧ ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → + ∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f U + +/-- Construct a common extension property from containment and extension of each scalar analytic +function. -/ +theorem isCommonAnalyticExtension_of_forall {U V : Set E} (hUV : U ⊆ V) + (he : ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → + ∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f U) : IsCommonAnalyticExtension U V := + ⟨hUV, he⟩ + +/-- A common extension pair includes the original set in the extension set. -/ +theorem IsCommonAnalyticExtension.subset {U V : Set E} (h : IsCommonAnalyticExtension U V) : + U ⊆ V := h.1 + +/-- Apply a common extension property to a scalar analytic function. -/ +theorem IsCommonAnalyticExtension.exists_extension {U V : Set E} + (h : IsCommonAnalyticExtension U V) {f : E → ℂ} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f U := h.2 f hf + +/-- Every set is a common extension domain for itself. -/ +theorem isCommonAnalyticExtension_refl (U : Set E) : IsCommonAnalyticExtension U U := + ⟨Subset.rfl, fun f hf => ⟨f, hf, fun _ _ => rfl⟩⟩ + +/-- Common extension composes. -/ +theorem IsCommonAnalyticExtension.trans {U V W : Set E} + (hUV : IsCommonAnalyticExtension U V) (hVW : IsCommonAnalyticExtension V W) : + IsCommonAnalyticExtension U W := by + refine ⟨hUV.1.trans hVW.1, fun f hf => ?_⟩ + obtain ⟨g, hg, he⟩ := hUV.2 f hf + obtain ⟨k, hk, he'⟩ := hVW.2 g hg + exact ⟨k, hk, (he'.mono hUV.1).trans he⟩ + +/-- An omitted scalar value remains omitted on a connected common extension domain. -/ +theorem IsCommonAnalyticExtension.ne_on {U V : Set E} (h : IsCommonAnalyticExtension U V) + (ho : IsOpen U) (hne : U.Nonempty) (hc : IsPreconnected V) + {f : E → ℂ} (hf : AnalyticOnNhd ℂ f V) {c : ℂ} (hno : ∀ z ∈ U, f z ≠ c) : + ∀ z ∈ V, f z ≠ c := by + have hi : AnalyticOnNhd ℂ (fun z => (f z - c)⁻¹) U := + fun z hz => ((hf z (h.1 hz)).sub analyticAt_const).inv (sub_ne_zero.mpr (hno z hz)) + obtain ⟨g, hg, he⟩ := h.2 _ hi + have hp : AnalyticOnNhd ℂ (fun z => (f z - c) * g z) V := + (hf.sub analyticOnNhd_const).mul hg + obtain ⟨a, ha⟩ := hne + have he₁ : (fun z => (f z - c) * g z) =ᶠ[𝓝 a] (fun _ => (1 : ℂ)) := by + filter_upwards [ho.mem_nhds ha] with z hz + rw [he hz] + exact mul_inv_cancel₀ (sub_ne_zero.mpr (hno z hz)) + have hp₁ := hp.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const hc (h.1 ha) he₁ + intro z hz heq + have := hp₁ hz + simp [heq] at this + +/-- A scalar analytic function on a connected common extension domain has exactly its original +range. This is the Euclidean version of Proposition 2.9.2. -/ +theorem IsCommonAnalyticExtension.image_eq {U V : Set E} (h : IsCommonAnalyticExtension U V) + (ho : IsOpen U) (hne : U.Nonempty) (hc : IsPreconnected V) + {f : E → ℂ} (hf : AnalyticOnNhd ℂ f V) : f '' V = f '' U := by + classical + apply Subset.antisymm _ (image_mono h.1) + rintro c ⟨z, hz, rfl⟩ + by_contra hn + have hno : ∀ w ∈ U, f w ≠ f z := fun w hw he => hn ⟨w, hw, he⟩ + exact h.ne_on ho hne hc hf hno z hz rfl + +/-- A common extension domain lies in the real convex hull of the original domain. The proof uses +real convex separation, complexification of the separating functional, and preservation of +omitted values. This assertion involves no abstract envelopes. -/ +theorem IsCommonAnalyticExtension.subset_convexHull [FiniteDimensional ℂ E] + {U V : Set E} (h : IsCommonAnalyticExtension U V) (ho : IsOpen U) + (hne : U.Nonempty) (hc : IsPreconnected V) : V ⊆ convexHull ℝ U := by + intro z hz + by_contra hn + obtain ⟨l, hl⟩ := geometric_hahn_banach_open_point (convex_convexHull ℝ U) + (ho.convexHull (𝕜 := ℝ)) hn + let L : E →L[ℂ] ℂ := l.extendRCLike + have hno : ∀ w ∈ U, L w ≠ L z := by + intro w hw he + have he' : l w = l z := by + simpa only [L, StrongDual.re_extendRCLike_apply] using + congrArg (RCLike.re : ℂ → ℝ) he + exact (ne_of_lt (hl w (_root_.subset_convexHull ℝ U hw))) he' + exact h.ne_on ho hne hc (fun w _ => L.analyticAt w) hno z hz rfl + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean new file mode 100644 index 0000000000..9ea9888b92 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean @@ -0,0 +1,374 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.FDeriv.Symmetric +public import Mathlib.Geometry.Manifold.PartitionOfUnity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform + +/-! +# Hartogs' compact-hole extension theorem in a product space + +Ehrenpreis' proof of Hartogs' extension theorem. Let `D ⊆ ℂ × G` be open with `G` a nontrivial +finite-dimensional complex normed space, `K ⊆ D` compact with `D \ K` connected, and `f` +holomorphic on `D \ K`. A smooth cutoff `φ` equal to one near `K` with compact support in `D` +gives the smooth function `F₀ = (1 - φ) f`, extended by zero across `K`. Its antiholomorphic +derivatives `∂F₀/∂\bar z` along every direction are compactly supported, and their symmetry, +from the symmetry of the second derivative of `F₀`, shows that the Cauchy transform `u` in the +first variable of `∂F₀/∂\bar z₁` has the same antiholomorphic derivatives as `F₀`. Hence `F₀ - +u` is holomorphic on `D`. On the open set of points of `D` whose second coordinate lies outside +the projection of the support of `φ`, both `F₀ = f` and `u = 0`; this set is nonempty because +the projection of `D` cannot be compact, and the identity principle on `D \ K` finishes the +proof. + +References: [Hörmander][Hormander1973] (1973), Theorem 2.3.2; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 4.2.5; [Boas][Boas2013] (2013), Section +2.4. + +## Main results + +* `exists_analyticOnNhd_extension_of_isCompact_prod`: **Hartogs' compact-hole extension theorem in a + product space.** For an open set `D ⊆ ℂ × G` with `G` a nontrivial finite-dimensional complex + normed space, a compact `K ⊆ D` with `D \ K` connected, and `f` holomorphic on `D \ K`, there is a + holomorphic function on `D` agreeing with `f` on `D \ K`. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex MeasureTheory Set Filter Metric Function +open scoped Topology + +namespace SeveralComplexVariables + +section Symmetry + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The antiholomorphic derivatives of a `C²` function commute: the antiholomorphic part along `v'` +of the derivative of `∂F₀/∂\bar z_v` equals the antiholomorphic part along `v` of the derivative +of `∂F₀/∂\bar z_{v'}`. -/ +theorem dbarAlong_fderiv_dbarAlong_fderiv_symm {F₀ : E → F} {x : E} (hF : ContDiffAt ℝ 2 F₀ x) + (v v' : E) : + dbarAlong (fderiv ℝ (fun y => dbarAlong (fderiv ℝ F₀ y) v) x) v' = + dbarAlong (fderiv ℝ (fun y => dbarAlong (fderiv ℝ F₀ y) v') x) v := by + have hsymm : IsSymmSndFDerivAt ℝ F₀ x := hF.isSymmSndFDerivAt (by simp) + have hd : HasFDerivAt (fderiv ℝ F₀) (fderiv ℝ (fderiv ℝ F₀) x) x := + ((hF.fderiv_right (m := 1) le_rfl).differentiableAt one_ne_zero).hasFDerivAt + set D2 := fderiv ℝ (fderiv ℝ F₀) x with hD2 + have key : ∀ u : E, HasFDerivAt (fun y => dbarAlong (fderiv ℝ F₀ y) u) + ((2 : ℂ)⁻¹ • (D2.flip u + I • D2.flip (I • u))) x := by + intro u + have h1 : HasFDerivAt (fun y => fderiv ℝ F₀ y u) (D2.flip u) x := by + have := hd.clm_apply (hasFDerivAt_const u x) + simpa using this + have h2 : HasFDerivAt (fun y => fderiv ℝ F₀ y (I • u)) (D2.flip (I • u)) x := by + have := hd.clm_apply (hasFDerivAt_const (I • u) x) + simpa using this + exact (h1.add (h2.const_smul I)).const_smul (2 : ℂ)⁻¹ + rw [(key v).fderiv, (key v').fderiv] + simp only [dbarAlong, FunLike.coe_smul, FunLike.coe_add, Pi.smul_apply, Pi.add_apply, + ContinuousLinearMap.flip_apply] + rw [hsymm v' v, hsymm v' (I • v), hsymm (I • v') v, hsymm (I • v') (I • v)] + module + +end Symmetry + +section Cutoff + +variable {G F : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] [FiniteDimensional ℂ G] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +open scoped ContDiff + +/-- Cutoff data for a compact hole `K` in an open set `D`: a smooth function equal to one on an open +neighborhood of `K`, with open support `s` whose closure is compact in `D`. -/ +private structure HoleCutoffData (D K : Set (ℂ × G)) where + /-- The cutoff function. -/ + φ : ℂ × G → ℝ + /-- An open neighborhood of `K` on which the cutoff equals one. -/ + neighborhood : Set (ℂ × G) + /-- The support of the cutoff. -/ + s : Set (ℂ × G) + /-- The cutoff is smooth. -/ + contDiff : ContDiff ℝ ∞ φ + /-- The neighborhood on which the cutoff equals one is open. -/ + isOpen_neighborhood : IsOpen neighborhood + /-- The neighborhood contains the hole. -/ + subset_neighborhood : K ⊆ neighborhood + /-- The cutoff equals one on the neighborhood of the hole. -/ + eq_one : ∀ x ∈ neighborhood, φ x = 1 + /-- The support is open. -/ + isOpen_s : IsOpen s + /-- The specified support is the nonzero locus of the cutoff. -/ + support_eq : support φ = s + /-- The support has compact closure. -/ + isCompact_closure : IsCompact (closure s) + /-- The closure of the support lies in the original domain. -/ + closure_subset : closure s ⊆ D + +omit [NormedSpace ℂ F] [CompleteSpace F] in +/-- Existence of cutoff data, from a smooth Urysohn function on thickenings of `K`. -/ +private theorem nonempty_holeCutoffData {D K : Set (ℂ × G)} (hD : IsOpen D) (hK : IsCompact K) + (hKD : K ⊆ D) : Nonempty (HoleCutoffData D K) := by + obtain ⟨δ, hδ, hδD⟩ := hK.exists_cthickening_subset_open hD hKD + obtain ⟨φ, hφ, -, hsupp, hone⟩ := exists_contDiff_support_eq_eq_one_iff (n := ⊤) (E := ℂ × G) + (isOpen_thickening (δ := δ / 2) (E := K)) (isClosed_cthickening (δ := δ / 4) (E := K)) + (cthickening_subset_thickening' (by positivity) (by linarith) K) + refine ⟨⟨φ, thickening (δ / 4) K, thickening (δ / 2) K, hφ, isOpen_thickening, + self_subset_thickening (by positivity) K, + fun x hx => (hone x).mp (thickening_subset_cthickening _ _ hx), isOpen_thickening, hsupp, + ?_, ?_⟩⟩ + · exact (hK.cthickening (r := δ / 2)).of_isClosed_subset isClosed_closure + (closure_thickening_subset_cthickening _ _) + · exact (closure_thickening_subset_cthickening _ _).trans + ((cthickening_mono (by linarith) K).trans hδD) + +omit [FiniteDimensional ℂ G] [NormedSpace ℂ F] [CompleteSpace F] in +/-- The hole lies in the support of the cutoff. -/ +private theorem HoleCutoffData.subset_s {D K : Set (ℂ × G)} (h : HoleCutoffData D K) : K ⊆ h.s := + fun x hx => by + rw [← h.support_eq, mem_support, h.eq_one x (h.subset_neighborhood hx)] + exact one_ne_zero + +omit [FiniteDimensional ℂ G] [NormedSpace ℂ F] [CompleteSpace F] in +/-- The cutoff vanishes outside its support. -/ +private theorem HoleCutoffData.eq_zero_of_notMem {D K : Set (ℂ × G)} (h : HoleCutoffData D K) + {x : ℂ × G} (hx : x ∉ h.s) : h.φ x = 0 := by + rw [← h.support_eq] at hx + exact notMem_support.mp hx + +omit [FiniteDimensional ℂ G] [NormedSpace ℂ F] [CompleteSpace F] in +/-- Points outside the closure of the support are outside the hole. -/ +private theorem HoleCutoffData.notMem_hole_of_notMem_closure {D K : Set (ℂ × G)} + (h : HoleCutoffData D K) + {x : ℂ × G} (hx : x ∉ closure h.s) : x ∉ K := + fun hxK => hx (subset_closure (h.subset_s hxK)) + +open scoped Classical in +/-- The modification `(1 - φ) • f`, set to zero on the hole. -/ +private def holeCutoff (K : Set (ℂ × G)) (φ : ℂ × G → ℝ) (f : ℂ × G → F) (x : ℂ × G) : F := + if x ∈ K then 0 else (1 - φ x) • f x + +omit [NormedAddCommGroup G] [NormedSpace ℂ G] [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- The modified function vanishes where the cutoff equals one. -/ +private theorem holeCutoff_eq_zero_of_one {K : Set (ℂ × G)} {φ : ℂ × G → ℝ} {f : ℂ × G → F} + {x : ℂ × G} + (hx : φ x = 1) : holeCutoff K φ f x = 0 := by + unfold holeCutoff + split_ifs <;> simp [hx] + +omit [NormedAddCommGroup G] [NormedSpace ℂ G] [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- Off the hole and off the support of the cutoff, the modified function is `f`. -/ +private theorem holeCutoff_eq_of_zero {K : Set (ℂ × G)} {φ : ℂ × G → ℝ} {f : ℂ × G → F} {x : ℂ × G} + (hxK : x ∉ K) (hx : φ x = 0) : holeCutoff K φ f x = f x := by + simp [holeCutoff, hxK, hx] + +variable {D K : Set (ℂ × G)} {f : ℂ × G → F} + +omit [FiniteDimensional ℂ G] in +/-- The modified function is `C²` on `D`. -/ +private theorem contDiffAt_holeCutoff (h : HoleCutoffData D K) (hD : IsOpen D) (hKc : IsClosed K) + (hf : AnalyticOnNhd ℂ f (D \ K)) {x : ℂ × G} (hx : x ∈ D) : + ContDiffAt ℝ 2 (holeCutoff K h.φ f) x := by + by_cases hxU : x ∈ h.neighborhood + · have heq : holeCutoff K h.φ f =ᶠ[𝓝 x] fun _ => (0 : F) := + eventuallyEq_of_mem (h.isOpen_neighborhood.mem_nhds hxU) fun y hy => + holeCutoff_eq_zero_of_one (h.eq_one y hy) + exact contDiffAt_const.congr_of_eventuallyEq heq + · have hxK : x ∉ K := fun hxK => hxU (h.subset_neighborhood hxK) + have hmem : x ∈ D \ K := ⟨hx, hxK⟩ + have heq : holeCutoff K h.φ f =ᶠ[𝓝 x] fun y => (1 - h.φ y) • f y := + eventuallyEq_of_mem ((hD.sdiff hKc).mem_nhds hmem) fun y hy => by + simp [holeCutoff, hy.2] + have hfc : ContDiffAt ℝ 2 f x := (hf x hmem).contDiffAt.restrict_scalars ℝ + have hφc : ContDiffAt ℝ 2 h.φ x := h.contDiff.contDiffAt.of_le (by simp) + exact ((contDiffAt_const.sub hφc).smul hfc).congr_of_eventuallyEq heq + +omit [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- Away from the closure of the support of the cutoff, the modified function is `f`. -/ +private theorem holeCutoff_eventuallyEq (h : HoleCutoffData D K) (x : ℂ × G) (hx : x ∉ closure h.s) + : + holeCutoff K h.φ f =ᶠ[𝓝 x] f := + eventuallyEq_of_mem (isClosed_closure.isOpen_compl.mem_nhds hx) fun _ hy => + holeCutoff_eq_of_zero (h.notMem_hole_of_notMem_closure hy) + (h.eq_zero_of_notMem fun hs => hy (subset_closure hs)) + +open scoped Classical in +/-- The antiholomorphic derivative of a function on `D` along a direction, extended by zero. -/ +private def dbarExt (D : Set (ℂ × G)) (F₀ : ℂ × G → F) (v : ℂ × G) (x : ℂ × G) : F := + if x ∈ D then dbarAlong (fderiv ℝ F₀ x) v else 0 + +omit [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- On `D`, the extended derivative is the antiholomorphic derivative. -/ +private theorem dbarExt_eventuallyEq (hD : IsOpen D) {F₀ : ℂ × G → F} {v x : ℂ × G} (hx : x ∈ D) : + dbarExt D F₀ v =ᶠ[𝓝 x] fun y => dbarAlong (fderiv ℝ F₀ y) v := + eventuallyEq_of_mem (hD.mem_nhds hx) fun y hy => by simp [dbarExt, hy] + +omit [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- The value of the extended derivative at a point of `D`. -/ +private theorem dbarExt_of_mem {F₀ : ℂ × G → F} {v x : ℂ × G} (hx : x ∈ D) : + dbarExt D F₀ v x = dbarAlong (fderiv ℝ F₀ x) v := by simp [dbarExt, hx] + +omit [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- The extended antiholomorphic derivatives vanish outside the closure of the support. -/ +private theorem dbarExt_holeCutoff_eq_zero (h : HoleCutoffData D K) + (hf : AnalyticOnNhd ℂ f (D \ K)) (v : ℂ × G) {x : ℂ × G} + (hx : x ∉ closure h.s) : dbarExt D (holeCutoff K h.φ f) v x = 0 := by + by_cases hxD : x ∈ D + · rw [dbarExt_of_mem hxD, (holeCutoff_eventuallyEq h (f := f) x hx).fderiv_eq, + (hf x ⟨hxD, h.notMem_hole_of_notMem_closure hx⟩).differentiableAt.fderiv_restrictScalars ℝ, + dbarAlong_restrictScalars] + · simp [dbarExt, hxD] + +omit [FiniteDimensional ℂ G] in +/-- The extended antiholomorphic derivatives of the modified function are `C¹`. -/ +private theorem contDiff_dbarExt_holeCutoff (h : HoleCutoffData D K) (hD : IsOpen D) + (hKc : IsClosed K) + (hf : AnalyticOnNhd ℂ f (D \ K)) (v : ℂ × G) : + ContDiff ℝ 1 (dbarExt D (holeCutoff K h.φ f) v) := by + rw [contDiff_iff_contDiffAt] + intro x + by_cases hx : x ∈ D + · have hfd : ContDiffAt ℝ 1 (fderiv ℝ (holeCutoff K h.φ f)) x := + (contDiffAt_holeCutoff h hD hKc hf hx).fderiv_right (m := 1) le_rfl + have : ContDiffAt ℝ 1 (fun y => dbarAlong (fderiv ℝ (holeCutoff K h.φ f) y) v) x := by + unfold dbarAlong + exact contDiffAt_const.smul ((hfd.clm_apply contDiffAt_const).add + (contDiffAt_const.smul (hfd.clm_apply contDiffAt_const))) + exact this.congr_of_eventuallyEq (dbarExt_eventuallyEq hD hx) + · have hxs : x ∉ closure h.s := fun hc => hx (h.closure_subset hc) + have heq : dbarExt D (holeCutoff K h.φ f) v =ᶠ[𝓝 x] fun _ => (0 : F) := + eventuallyEq_of_mem (isClosed_closure.isOpen_compl.mem_nhds hxs) fun y hy => + dbarExt_holeCutoff_eq_zero h hf v hy + exact contDiffAt_const.congr_of_eventuallyEq heq + +omit [FiniteDimensional ℂ G] [CompleteSpace F] in +/-- The extended antiholomorphic derivatives of the modified function have compact support. -/ +private theorem hasCompactSupport_dbarExt_holeCutoff (h : HoleCutoffData D K) + (hf : AnalyticOnNhd ℂ f (D \ K)) (v : ℂ × G) : + HasCompactSupport (dbarExt D (holeCutoff K h.φ f) v) := + HasCompactSupport.intro h.isCompact_closure fun _ hx => dbarExt_holeCutoff_eq_zero h hf v hx + +omit [FiniteDimensional ℂ G] in +/-- Symmetry of the extended antiholomorphic derivatives. -/ +private theorem dbarAlong_fderiv_dbarExt_holeCutoff_symm (h : HoleCutoffData D K) (hD : IsOpen D) + (hKc : IsClosed K) + (hf : AnalyticOnNhd ℂ f (D \ K)) (y v v' : ℂ × G) : + dbarAlong (fderiv ℝ (dbarExt D (holeCutoff K h.φ f) v) y) v' = + dbarAlong (fderiv ℝ (dbarExt D (holeCutoff K h.φ f) v') y) v := by + by_cases hy : y ∈ D + · rw [(dbarExt_eventuallyEq hD hy).fderiv_eq, (dbarExt_eventuallyEq hD hy).fderiv_eq] + exact dbarAlong_fderiv_dbarAlong_fderiv_symm (contDiffAt_holeCutoff h hD hKc hf hy) v v' + · have hys : y ∉ closure h.s := fun hc => hy (h.closure_subset hc) + have hz : ∀ u : ℂ × G, fderiv ℝ (dbarExt D (holeCutoff K h.φ f) u) y = 0 := by + intro u + have heq : dbarExt D (holeCutoff K h.φ f) u =ᶠ[𝓝 y] fun _ => (0 : F) := + eventuallyEq_of_mem (isClosed_closure.isOpen_compl.mem_nhds hys) fun z hz => + dbarExt_holeCutoff_eq_zero h hf u hz + rw [heq.fderiv_eq, fderiv_const_apply] + rw [hz, hz, dbarAlong_zero, dbarAlong_zero] + +end Cutoff + +section Main + +variable {G F : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] [FiniteDimensional ℂ G] + [Nontrivial G] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- **Hartogs' compact-hole extension theorem in a product space.** For an open set +`D ⊆ ℂ × G` with `G` a nontrivial finite-dimensional complex normed space, a compact `K ⊆ D` +with `D \ K` connected, and `f` holomorphic on `D \ K`, there is a holomorphic function on `D` +agreeing with `f` on `D \ K`. -/ +theorem exists_analyticOnNhd_extension_of_isCompact_prod {D K : Set (ℂ × G)} (hD : IsOpen D) + (hK : IsCompact K) (hKD : K ⊆ D) (hconn : IsPreconnected (D \ K)) {f : ℂ × G → F} + (hf : AnalyticOnNhd ℂ f (D \ K)) : + ∃ g : ℂ × G → F, AnalyticOnNhd ℂ g D ∧ EqOn g f (D \ K) := by + rcases K.eq_empty_or_nonempty with hKe | hKne + · subst hKe + exact ⟨f, by simpa using hf, fun x _ => rfl⟩ + obtain ⟨h⟩ := nonempty_holeCutoffData hD hK hKD + have hKc : IsClosed K := hK.isClosed + set F₀ := holeCutoff K h.φ f with hF₀ + set e₁ : ℂ × G := ((1 : ℂ), (0 : G)) with he₁ + have hg1 : ∀ v, ContDiff ℝ 1 (dbarExt D F₀ v) := contDiff_dbarExt_holeCutoff h hD hKc hf + have hgs : ∀ v, HasCompactSupport (dbarExt D F₀ v) := hasCompactSupport_dbarExt_holeCutoff h hf + set u := cauchyTransformFst (dbarExt D F₀ e₁) with hu + set g : ℂ × G → F := fun x => F₀ x - u x with hg + have hdiff : DifferentiableOn ℂ g D := by + intro x hx + have hF₀d : HasFDerivAt F₀ (fderiv ℝ F₀ x) x := + ((contDiffAt_holeCutoff h hD hKc hf hx).differentiableAt (by norm_num)).hasFDerivAt + have hud : HasFDerivAt u (fderiv ℝ u x) x := + (hasFDerivAt_cauchyTransformFst (hg1 e₁) (hgs e₁) x).differentiableAt.hasFDerivAt + have hL : HasFDerivAt g (fderiv ℝ F₀ x - fderiv ℝ u x) x := hF₀d.sub hud + have hdbar : ∀ v, dbarAlong (fderiv ℝ F₀ x - fderiv ℝ u x) v = 0 := by + intro v + rw [dbarAlong_sub, dbarAlong_fderiv_cauchyTransformFst (hg1 e₁) (hgs e₁) x v] + have hsym : ∀ w : ℂ, dbarAlong (fderiv ℝ (dbarExt D F₀ e₁) (x - (w, 0))) v = + dbarAlong (fderiv ℝ (dbarExt D F₀ v) (x - (w, 0))) e₁ := fun w => + dbarAlong_fderiv_dbarExt_holeCutoff_symm h hD hKc hf _ e₁ v + simp_rw [hsym] + rw [integral_inv_smul_dbarAlong_fderiv_sub (hg1 v) (hgs v) x, smul_smul, + inv_mul_cancel₀ (by exact_mod_cast Real.pi_ne_zero), one_smul, dbarExt_of_mem hx, + sub_self] + exact (hasFDerivAt_of_restrictScalars ℝ hL + (restrictScalars_complexLinearOfDbar _ hdbar)).differentiableAt.differentiableWithinAt + have hga : AnalyticOnNhd ℂ g D := hdiff.analyticOnNhd_of_finiteDimensional hD + set T := Prod.snd '' closure h.s with hT + have hTc : IsCompact T := h.isCompact_closure.image continuous_snd + set V := D ∩ Prod.snd ⁻¹' Tᶜ with hV + have hVo : IsOpen V := hD.inter (hTc.isClosed.isOpen_compl.preimage continuous_snd) + have hVsub : V ⊆ D \ K := fun x hx => + ⟨hx.1, fun hxK => hx.2 (mem_image_of_mem _ (subset_closure (h.subset_s hxK)))⟩ + have hVne : V.Nonempty := by + by_contra hemp + rw [not_nonempty_iff_eq_empty] at hemp + have h1 : Prod.snd '' D ⊆ T := by + rintro _ ⟨x, hx, rfl⟩ + by_contra hxT + exact (eq_empty_iff_forall_notMem.mp hemp) x ⟨hx, hxT⟩ + have h2 : T ⊆ Prod.snd '' D := image_mono h.closure_subset + have heq : Prod.snd '' D = T := Subset.antisymm h1 h2 + have hopen : IsOpen (Prod.snd '' D) := isOpenMap_snd D hD + have hne : (Prod.snd '' D).Nonempty := (hKne.mono hKD).image _ + have hclopen : IsClopen (Prod.snd '' D) := ⟨by rw [heq]; exact hTc.isClosed, hopen⟩ + have huniv := hclopen.eq_univ hne + have hcpt : IsCompact (univ : Set G) := by + rw [← huniv, heq] + exact hTc + exact NoncompactSpace.noncompact_univ hcpt + obtain ⟨x₀, hx₀⟩ := hVne + have hgf : EqOn g f V := by + intro x hx + have hxs : x ∉ closure h.s := fun hc => hx.2 (mem_image_of_mem _ hc) + have hF : F₀ x = f x := + holeCutoff_eq_of_zero (h.notMem_hole_of_notMem_closure hxs) + (h.eq_zero_of_notMem fun hs => hxs (subset_closure hs)) + have hu0 : u x = 0 := by + have hz : ∀ z : ℂ, dbarExt D F₀ e₁ (z, x.2) = 0 := fun z => + dbarExt_holeCutoff_eq_zero h hf e₁ fun hc => hx.2 ⟨(z, x.2), hc, rfl⟩ + have := cauchyTransformFst_eq_zero hz x.1 + simpa using this + show F₀ x - u x = f x + rw [hF, hu0, sub_zero] + refine ⟨g, hga, ?_⟩ + exact (hga.mono sdiff_subset).eqOn_of_preconnected_of_eventuallyEq hf hconn (hVsub hx₀) + (eventuallyEq_of_mem (hVo.mem_nhds hx₀) hgf) + +end Main + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ContourIntegral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ContourIntegral.lean new file mode 100644 index 0000000000..dceb49d974 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ContourIntegral.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.CircleIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral + +/-! +# Holomorphic parameters in compact contour integrals + +A jointly holomorphic kernel can be integrated over a fixed compact parameter set, after a +continuous parametrization and multiplication by a fixed integrable weight. The weight need not +be holomorphic. In the circle specialization it includes the contour derivative and a continuous +boundary function. + +This is simplex-independent infrastructure for continued Cauchy representations. It does not +assert a Jordan-curve theorem or homotopy invariance of contours. + +## Main results + +`analyticOnNhd_integral_smul_compact_kernel` gives analytic dependence for Banach-valued kernels; +`analyticOnNhd_integral_mul_compact_kernel` is its scalar specialization. Compactness supplies +derivative bounds and separable images, with no second-countability assumption on the parameter +space. `analyticOnNhd_circleIntegral_kernel_mul` is the scalar circle specialization. +-/ + +open Complex MeasureTheory Filter Metric Set +open scoped Topology +public section +variable {E α : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [MeasurableSpace α] [TopologicalSpace α] + [BorelSpace α] [T2Space α] + +/-- A compact integral of a jointly analytic Banach-valued kernel, with a fixed integrable scalar +weight, is analytic in its parameters. -/ +theorem analyticOnNhd_integral_smul_compact_kernel + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {μ : Measure α} {K : Set α} (hK : IsCompact K) + {g : α → ℂ} (hg : IntegrableOn g K μ) + {γ : α → ℂ} (hγ : ContinuousOn γ K) + {U : Set E} (hU : IsOpen U) {W : Set (E × ℂ)} + {H : E × ℂ → F} (hH : AnalyticOnNhd ℂ H W) + (hW : ∀ x ∈ U, ∀ t ∈ K, (x, γ t) ∈ W) : + AnalyticOnNhd ℂ (fun x => ∫ t in K, g t • H (x, γ t) ∂μ) U := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + let D := fun (x : E) (t : α) => + (fderiv ℂ H (x, γ t)).comp (ContinuousLinearMap.inl ℂ E ℂ) + have hc : ContinuousOn (fun p : E × α => H (p.1, γ p.2)) (U ×ˢ K) := + hH.continuousOn.comp + (continuousOn_fst.prodMk (hγ.comp continuousOn_snd (fun _ hp => hp.2))) + (fun p hp => hW p.1 hp.1 p.2 hp.2) + have hD : ContinuousOn (fun p : E × α => D p.1 p.2) (U ×ˢ K) := + (hH.fderiv.continuousOn.comp + (continuousOn_fst.prodMk (hγ.comp continuousOn_snd (fun _ hp => hp.2))) + (fun p hp => hW p.1 hp.1 p.2 hp.2)).clm_comp continuousOn_const + have hslice {x : E} (hx : x ∈ U) : ContinuousOn (fun t => H (x, γ t)) K := + hc.comp (continuous_const.prodMk continuous_id).continuousOn (fun t ht => ⟨hx, ht⟩) + apply DifferentiableOn.analyticOnNhd_of_finiteDimensional _ hU + intro x hx + obtain ⟨r, hr, hball⟩ := nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hx) + obtain ⟨M, hM⟩ := ((isCompact_closedBall x r).prod hK).bddAbove_image + (hD.mono (Set.prod_mono hball Subset.rfl)).norm + apply (hasFDerivAt_integral_of_dominated_of_fderiv_le + (μ := μ.restrict K) (F := fun x t => g t • H (x, γ t)) + (F' := fun x t => g t • D x t) (bound := fun t => ‖g t‖ * M) + (closedBall_mem_nhds x hr) ?_ (hg.smul_continuousOn_of_isCompact (hslice hx) hK) ?_ ?_ + (hg.norm.mul_const M) ?_).differentiableAt.differentiableWithinAt + · filter_upwards [hU.mem_nhds hx] with y hy + exact (hg.smul_continuousOn_of_isCompact (hslice hy) hK).aestronglyMeasurable + · exact hg.aestronglyMeasurable.smul + ((hD.comp (continuous_const.prodMk continuous_id).continuousOn + (fun t ht => ⟨hx, ht⟩)).aestronglyMeasurable_of_isCompact hK hK.measurableSet) + · filter_upwards [ae_restrict_mem hK.measurableSet] with t ht + intro y hy + rw [norm_smul] + exact mul_le_mul_of_nonneg_left (hM ⟨(y, t), ⟨hy, ht⟩, rfl⟩) (norm_nonneg _) + · filter_upwards [ae_restrict_mem hK.measurableSet] with t ht + intro y hy + exact (((hH _ (hW y (hball hy) t ht)).differentiableAt.hasFDerivAt).comp y + (hasFDerivAt_prodMk_left (𝕜 := ℂ) y (γ t))).const_smul (g t) + +/-- Holomorphic dependence of a compact weighted integral of a jointly holomorphic kernel. Only the +parametrization, not the weight, must be continuous. -/ +theorem analyticOnNhd_integral_mul_compact_kernel + {μ : Measure α} {K : Set α} (hK : IsCompact K) + {g : α → ℂ} (hg : IntegrableOn g K μ) + {γ : α → ℂ} (hγ : ContinuousOn γ K) + {U : Set E} (hU : IsOpen U) {W : Set (E × ℂ)} + {H : E × ℂ → ℂ} (hH : AnalyticOnNhd ℂ H W) + (hW : ∀ x ∈ U, ∀ t ∈ K, (x, γ t) ∈ W) : + AnalyticOnNhd ℂ (fun x => ∫ t in K, g t * H (x, γ t) ∂μ) U := by + simpa only [smul_eq_mul] using + analyticOnNhd_integral_smul_compact_kernel hK hg hγ hU hH hW + +omit [MeasurableSpace α] [TopologicalSpace α] [BorelSpace α] [T2Space α] in +/-- Integrating a holomorphic parameter-dependent kernel against a continuous boundary function on a +fixed circle preserves holomorphy in all parameters. -/ +theorem analyticOnNhd_circleIntegral_kernel_mul + {U : Set E} (hU : IsOpen U) {W : Set (E × ℂ)} + {H : E × ℂ → ℂ} (hH : AnalyticOnNhd ℂ H W) + {c : ℂ} {R : ℝ} (hR : 0 ≤ R) {f : ℂ → ℂ} + (hf : ContinuousOn f (sphere c R)) + (hW : ∀ x ∈ U, ∀ s ∈ sphere c R, (x, s) ∈ W) : + AnalyticOnNhd ℂ (fun x => ∮ s in C(c, R), H (x, s) * f s) U := by + have hg : ContinuousOn (fun t : ℝ => deriv (circleMap c R) t * f (circleMap c R t)) + (Icc 0 (2 * Real.pi)) := by + apply ContinuousOn.mul + · change ContinuousOn (fun t : ℝ => deriv (circleMap c R) t) _ + simp only [deriv_circleMap] + fun_prop + · exact hf.comp (continuous_circleMap c R).continuousOn + (fun t _ => circleMap_mem_sphere c hR t) + have h := analyticOnNhd_integral_mul_compact_kernel (μ := volume) isCompact_Icc + (hg.integrableOn_compact isCompact_Icc) (continuous_circleMap c R).continuousOn hU hH + (fun x hx t _ => hW x hx _ (circleMap_mem_sphere c hR t)) + simpa only [circleIntegral_def_Icc, smul_eq_mul, mul_assoc, mul_left_comm, mul_comm] using h + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean new file mode 100644 index 0000000000..0cd799c6c5 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean @@ -0,0 +1,429 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.Deriv.Pi +public import Mathlib.Analysis.Calculus.FDeriv.Analytic +public import Mathlib.Analysis.Calculus.FDeriv.Symmetric +public import Mathlib.LinearAlgebra.Matrix.ToLin +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Coordinate derivatives of holomorphic functions + +Coordinate differentiation is defined using one-variable slices, and identified with evaluation +of the Fréchet derivative on a coordinate vector. Holomorphy of derivatives is inherited from +Mathlib's general Fréchet derivative theorem. Mixed derivatives can be indexed by coordinate +lists or multi-indices; permutation invariance identifies these forms. + +## Main results + +`partialDeriv` is the coordinate derivative of a map on `ι → 𝕜`, for any nontrivially normed field. + `partialDeriv_eq_fderiv` identifies +it with the Fréchet derivative on a coordinate vector. `iteratedPartialDeriv` and `multiIndexDeriv` +are mixed derivatives, identified by `iteratedPartialDeriv_eq_multiIndexDeriv`. +`iteratedPartialDeriv_perm` is permutation invariance. `complexJacobian` is the Jacobian matrix of +coordinate derivatives. +-/ + +public noncomputable section + +open Complex Filter Function Set +open scoped Topology + +namespace SeveralComplexVariables + +section General + +variable {𝕜 ι F : Type*} [NontriviallyNormedField 𝕜] [Fintype ι] [DecidableEq ι] + [NormedAddCommGroup F] [NormedSpace 𝕜 F] + +/-- Differentiate in coordinate `i`, holding all other coordinates fixed. The scalar field is any +nontrivially normed field; the several-complex-variables theory uses `𝕜 = ℂ`. -/ +@[expose] def partialDeriv (i : ι) (f : (ι → 𝕜) → F) (z : ι → 𝕜) : F := + deriv (fun w => f (update z i w)) (z i) + +/-- The derivative of a coordinate slice is the corresponding Fréchet derivative value. -/ +theorem hasDerivAt_update_of_differentiableAt {f : (ι → 𝕜) → F} {z : ι → 𝕜} + (hf : DifferentiableAt 𝕜 f z) (i : ι) : + HasDerivAt (fun w => f (update z i w)) (fderiv 𝕜 f z (Pi.single i 1)) (z i) := by + have hf' : HasFDerivAt f (fderiv 𝕜 f z) (update z i (z i)) := by simpa using hf.hasFDerivAt + exact hf'.comp_hasDerivAt (z i) (hasDerivAt_update z i (z i)) + +/-- Coordinate derivatives are Fréchet derivatives evaluated on coordinate vectors. -/ +theorem partialDeriv_eq_fderiv {f : (ι → 𝕜) → F} {z : ι → 𝕜} + (hf : DifferentiableAt 𝕜 f z) (i : ι) : + partialDeriv i f z = fderiv 𝕜 f z (Pi.single i 1) := + (hasDerivAt_update_of_differentiableAt hf i).deriv + +/-- A coordinate derivative only depends on the germ of the function. -/ +theorem partialDeriv_congr {f g : (ι → 𝕜) → F} {z : ι → 𝕜} + (hfg : f =ᶠ[𝓝 z] g) (i : ι) : partialDeriv i f z = partialDeriv i g z := by + apply Filter.EventuallyEq.deriv_eq + have ht : Tendsto (update z i) (𝓝 (z i)) (𝓝 z) := by + simpa using (hasDerivAt_update z i (z i)).continuousAt.tendsto + exact hfg.comp_tendsto ht + +/-- The Fréchet derivative is recovered from the coordinate derivatives. -/ +theorem fderiv_eq_sum_partialDeriv {f : (ι → 𝕜) → F} {z : ι → 𝕜} + (hf : DifferentiableAt 𝕜 f z) (v : ι → 𝕜) : + fderiv 𝕜 f z v = ∑ i, v i • partialDeriv i f z := by + simp_rw [partialDeriv_eq_fderiv hf, ← map_smul, ← map_sum] + congr 1 + ext j + simp [Pi.single_apply] + +/-- Coordinate differentiation respects subtraction at differentiability points. -/ +theorem partialDeriv_sub {f g : (ι → 𝕜) → F} {z : ι → 𝕜} + (hf : DifferentiableAt 𝕜 f z) (hg : DifferentiableAt 𝕜 g z) (i : ι) : + partialDeriv i (f - g) z = partialDeriv i f z - partialDeriv i g z := by + exact deriv_sub (hasDerivAt_update_of_differentiableAt hf i).differentiableAt + (hasDerivAt_update_of_differentiableAt hg i).differentiableAt + +/-- Coordinate differentiation of a product of scalar functions follows the ordinary product rule, +holding the other coordinates fixed. -/ +theorem partialDeriv_mul {f g : (ι → 𝕜) → 𝕜} {z : ι → 𝕜} + (hf : DifferentiableAt 𝕜 f z) (hg : DifferentiableAt 𝕜 g z) (i : ι) : + partialDeriv i (f * g) z = partialDeriv i f z * g z + f z * partialDeriv i g z := by + have hf' := hasDerivAt_update_of_differentiableAt hf i + have hg' := hasDerivAt_update_of_differentiableAt hg i + have h := deriv_fun_mul hf'.differentiableAt hg'.differentiableAt + simpa [partialDeriv, update_eq_self] using h + +/-- Coordinate differentiation commutes with a finite sum of differentiable functions. -/ +theorem partialDeriv_finset_sum {α : Type*} {f : α → (ι → 𝕜) → F} + (t : Finset α) {z : ι → 𝕜} (hf : ∀ a ∈ t, DifferentiableAt 𝕜 (f a) z) (i : ι) : + partialDeriv i (fun w => ∑ a ∈ t, f a w) z = ∑ a ∈ t, partialDeriv i (f a) z := by + exact deriv_fun_sum fun a ha => (hasDerivAt_update_of_differentiableAt (hf a ha) + i).differentiableAt + +end General + +variable {ι F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Holomorphy restricts to each coordinate slice. -/ +theorem _root_.AnalyticOnNhd.analyticAt_update {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) {z : ι → ℂ} (hz : z ∈ U) (i : ι) : + AnalyticAt ℂ (fun w => f (update z i w)) (z i) := by + have hu : AnalyticAt ℂ (update z i) (z i) := + analyticAt_iff_eventually_differentiableAt.mpr + (Eventually.of_forall fun w => (hasDerivAt_update z i w).differentiableAt) + exact (hf z hz).comp_of_eq hu (update_eq_self i z) + +variable [CompleteSpace F] + +/-- Every coordinate derivative of an analytic function is analytic. -/ +theorem _root_.AnalyticOnNhd.partialDeriv {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) (i : ι) : + AnalyticOnNhd ℂ (partialDeriv i f) U := by + intro z hz + have ha : AnalyticAt ℂ (fun w => fderiv ℂ f w (Pi.single i 1)) z := by + simpa only [Function.comp_def, ContinuousLinearMap.apply_apply] using! + ((ContinuousLinearMap.apply ℂ F (Pi.single i (1 : ℂ))).analyticAt + (fderiv ℂ f z)).comp_of_eq (hf z hz).fderiv rfl + apply ha.congr + filter_upwards [hU.eventually_mem hz] with w hw + exact (partialDeriv_eq_fderiv (hf w hw).differentiableAt i).symm + +/-- Repeated coordinate differentiation, with the leftmost coordinate acting last. -/ +@[expose] def iteratedPartialDeriv {𝕜 ι F : Type*} [NontriviallyNormedField 𝕜] [DecidableEq ι] + [NormedAddCommGroup F] [NormedSpace 𝕜 F] : List ι → ((ι → 𝕜) → F) → (ι → 𝕜) → F + | [], f => f + | i :: is, f => partialDeriv i (iteratedPartialDeriv is f) + +/-- Differentiate a coordinate derivative by composing the second Fréchet derivative with evaluation +on its coordinate vector. -/ +theorem hasFDerivAt_partialDeriv {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) {z : ι → ℂ} (hz : z ∈ U) (i : ι) : + HasFDerivAt (partialDeriv i f) + ((ContinuousLinearMap.apply ℂ F (Pi.single i 1)).comp + (fderiv ℂ (fderiv ℂ f) z)) z := by + have H := (ContinuousLinearMap.apply ℂ F (Pi.single i (1 : ℂ))).hasFDerivAt.comp z + (hf z hz).fderiv.differentiableAt.hasFDerivAt + apply H.congr_of_eventuallyEq + filter_upwards [hU.eventually_mem hz] with w hw + exact partialDeriv_eq_fderiv (hf w hw).differentiableAt i + +/-- Mixed coordinate derivatives commute for a holomorphic function. -/ +theorem partialDeriv_partialDeriv_comm {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) {z : ι → ℂ} (hz : z ∈ U) (i j : ι) : + partialDeriv i (partialDeriv j f) z = partialDeriv j (partialDeriv i f) z := by + rw [partialDeriv_eq_fderiv (hasFDerivAt_partialDeriv hf hU hz j).differentiableAt, + partialDeriv_eq_fderiv (hasFDerivAt_partialDeriv hf hU hz i).differentiableAt, + (hasFDerivAt_partialDeriv hf hU hz j).fderiv, + (hasFDerivAt_partialDeriv hf hU hz i).fderiv] + exact (hf z hz).contDiffAt.isSymmSndFDerivAt_of_omega (Pi.single i 1) (Pi.single j 1) + +/-- All iterated coordinate derivatives are holomorphic on the original open domain. -/ +theorem _root_.AnalyticOnNhd.iteratedPartialDeriv {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) (is : List ι) : + AnalyticOnNhd ℂ (iteratedPartialDeriv is f) U := by + induction is with + | nil => exact hf + | cons i is ih => exact ih.partialDeriv hU i + +/-- Iterated coordinate derivatives depend only on the multiplicity of each coordinate, not on their +order in the differentiation list. -/ +theorem iteratedPartialDeriv_perm {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) {is js : List ι} (h : is.Perm js) : + EqOn (iteratedPartialDeriv is f) (iteratedPartialDeriv js f) U := by + induction h with + | nil => intro z hz; rfl + | cons i h ih => + intro z hz + apply partialDeriv_congr + filter_upwards [hU.eventually_mem hz] with w hw + exact ih hw + | swap i j is => + intro z hz + exact partialDeriv_partialDeriv_comm (hf.iteratedPartialDeriv hU is) hU hz j i + | trans h₁ h₂ ih₁ ih₂ => exact ih₁.trans ih₂ + +omit [CompleteSpace F] in +/-- Iterated coordinate derivatives agree on an open set where the original functions agree. -/ +theorem iteratedPartialDeriv_congrOn {U : Set (ι → ℂ)} {f g : (ι → ℂ) → F} + (hU : IsOpen U) (hfg : EqOn f g U) (is : List ι) : + EqOn (iteratedPartialDeriv is f) (iteratedPartialDeriv is g) U := by + induction is with + | nil => exact hfg + | cons i is ih => + intro z hz + apply partialDeriv_congr + filter_upwards [hU.eventually_mem hz] with w hw + exact ih hw + +/-- Mixed coordinate differentiation commutes with finite sums of holomorphic functions. -/ +theorem iteratedPartialDeriv_finset_sum {α : Type*} {U : Set (ι → ℂ)} + {f : α → (ι → ℂ) → F} (t : Finset α) (hf : ∀ a ∈ t, AnalyticOnNhd ℂ (f a) U) + (hU : IsOpen U) (is : List ι) : + EqOn (iteratedPartialDeriv is (fun z => ∑ a ∈ t, f a z)) + (fun z => ∑ a ∈ t, iteratedPartialDeriv is (f a) z) U := by + induction is with + | nil => intro z hz; rfl + | cons i is ih => + intro z hz + change partialDeriv i (iteratedPartialDeriv is (fun w => ∑ a ∈ t, f a w)) z = _ + have heq : iteratedPartialDeriv is (fun w => ∑ a ∈ t, f a w) =ᶠ[𝓝 z] + (fun w => ∑ a ∈ t, iteratedPartialDeriv is (f a) w) := + (hU.eventually_mem hz).mono (fun w hw => ih hw) + rw [partialDeriv_congr heq i] + exact partialDeriv_finset_sum t + (fun a ha => ((hf a ha).iteratedPartialDeriv hU is z hz).differentiableAt) i + +/-- Pascal's rule reindexes a sum of consecutive terms into the next row of binomial coefficients: +the combinatorial core of the Leibniz rule for iterated derivatives. -/ +private theorem sum_choose_shift (k : ℕ) (X : ℕ → ℂ) : + (∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * (X (j + 1) + X j)) = + ∑ j ∈ Finset.range (k + 2), ((k + 1).choose j : ℂ) * X j := by + have hzero : (k.choose (k + 1) : ℂ) * X (k + 1) = 0 := by simp + have hstep1 : ∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * X j = + X 0 + ∑ j ∈ Finset.range (k + 1), (k.choose (j + 1) : ℂ) * X (j + 1) := by + rw [Finset.sum_range_succ' (fun j => (k.choose j : ℂ) * X j) k] + simp only [Nat.choose_zero_right, Nat.cast_one, one_mul] + rw [Finset.sum_range_succ (fun j => (k.choose (j + 1) : ℂ) * X (j + 1)) k, hzero, add_zero] + ring + have hpeel : ∑ j ∈ Finset.range (k + 2), ((k + 1).choose j : ℂ) * X j = + X 0 + ∑ j ∈ Finset.range (k + 1), ((k + 1).choose (j + 1) : ℂ) * X (j + 1) := by + rw [Finset.sum_range_succ' (fun j => ((k + 1).choose j : ℂ) * X j) (k + 1)] + simp only [Nat.choose_zero_right, Nat.cast_one, one_mul] + ring + rw [hpeel] + have hpascal : ∀ j ∈ Finset.range (k + 1), + ((k + 1).choose (j + 1) : ℂ) * X (j + 1) = + (k.choose j : ℂ) * X (j + 1) + (k.choose (j + 1) : ℂ) * X (j + 1) := by + intro j _ + rw [Nat.choose_succ_succ', Nat.cast_add, add_mul] + rw [Finset.sum_congr rfl hpascal, Finset.sum_add_distrib] + have hexpand : ∀ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * (X (j + 1) + X j) = + (k.choose j : ℂ) * X (j + 1) + (k.choose j : ℂ) * X j := fun j _ => by ring + rw [Finset.sum_congr rfl hexpand, Finset.sum_add_distrib, hstep1] + ring + +/-- Coordinate differentiation of a scalar multiple follows the ordinary constant-multiple rule, +holding the other coordinates fixed. -/ +theorem partialDeriv_const_mul {f : (ι → ℂ) → ℂ} {z : ι → ℂ} (c : ℂ) + (hf : DifferentiableAt ℂ f z) (i : ι) : + partialDeriv i (fun w => c * f w) z = c * partialDeriv i f z := + deriv_const_mul c (hasDerivAt_update_of_differentiableAt hf i).differentiableAt + +/-- Repeated differentiation of a product of scalar functions in a single coordinate follows the +ordinary Leibniz binomial rule, since each step is the ordinary product rule. -/ +theorem iteratedPartialDeriv_replicate_mul {U : Set (ι → ℂ)} {f g : (ι → ℂ) → ℂ} + (hf : AnalyticOnNhd ℂ f U) (hg : AnalyticOnNhd ℂ g U) (hU : IsOpen U) (i : ι) (k : ℕ) : + EqOn (iteratedPartialDeriv (List.replicate k i) (f * g)) + (fun z => ∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * + (iteratedPartialDeriv (List.replicate j i) f z * + iteratedPartialDeriv (List.replicate (k - j) i) g z)) U := by + induction k with + | zero => intro z hz; simp [iteratedPartialDeriv] + | succ k ih => + intro z hz + have hstep : iteratedPartialDeriv (List.replicate (k + 1) i) (f * g) z = + partialDeriv i (iteratedPartialDeriv (List.replicate k i) (f * g)) z := rfl + rw [hstep] + have heq : iteratedPartialDeriv (List.replicate k i) (f * g) =ᶠ[𝓝 z] + (fun z => ∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * + (iteratedPartialDeriv (List.replicate j i) f z * + iteratedPartialDeriv (List.replicate (k - j) i) g z)) := + (hU.eventually_mem hz).mono (fun w hw => ih hw) + rw [partialDeriv_congr heq i] + have hAdiff : ∀ j, DifferentiableAt ℂ (iteratedPartialDeriv (List.replicate j i) f) z := + fun j => (hf.iteratedPartialDeriv hU (List.replicate j i) z hz).differentiableAt + have hBdiff : ∀ j, DifferentiableAt ℂ (iteratedPartialDeriv (List.replicate j i) g) z := + fun j => (hg.iteratedPartialDeriv hU (List.replicate j i) z hz).differentiableAt + have hsum := partialDeriv_finset_sum (F := ℂ) + (f := fun j (w : ι → ℂ) => (k.choose j : ℂ) * + (iteratedPartialDeriv (List.replicate j i) f w * + iteratedPartialDeriv (List.replicate (k - j) i) g w)) + (Finset.range (k + 1)) (fun j _ => ((hAdiff j).mul (hBdiff (k - j))).const_mul _) i + rw [hsum] + have hterm : ∀ j ∈ Finset.range (k + 1), + partialDeriv i (fun z => (k.choose j : ℂ) * (iteratedPartialDeriv + (List.replicate j i) f z * iteratedPartialDeriv (List.replicate (k - j) i) g z)) z = + (k.choose j : ℂ) * (iteratedPartialDeriv (List.replicate (j + 1) i) f z * + iteratedPartialDeriv (List.replicate (k - j) i) g z + + iteratedPartialDeriv (List.replicate j i) f z * + iteratedPartialDeriv (List.replicate (k - j + 1) i) g z) := by + intro j _ + have hcm := partialDeriv_const_mul + (f := fun w => iteratedPartialDeriv (List.replicate j i) f w * + iteratedPartialDeriv (List.replicate (k - j) i) g w) + (k.choose j : ℂ) ((hAdiff j).mul (hBdiff (k - j))) i + rw [hcm] + have hpm : partialDeriv i (fun w => iteratedPartialDeriv (List.replicate j i) f w * + iteratedPartialDeriv (List.replicate (k - j) i) g w) z = + partialDeriv i (iteratedPartialDeriv (List.replicate j i) f) z * + iteratedPartialDeriv (List.replicate (k - j) i) g z + + iteratedPartialDeriv (List.replicate j i) f z * + partialDeriv i (iteratedPartialDeriv (List.replicate (k - j) i) g) z := + partialDeriv_mul (hAdiff j) (hBdiff (k - j)) i + rw [hpm] + congr 2 + rw [Finset.sum_congr rfl hterm] + set X : ℕ → ℂ := fun m => iteratedPartialDeriv (List.replicate m i) f z * + iteratedPartialDeriv (List.replicate (k + 1 - m) i) g z with hXdef + have hgoal : ∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * + (iteratedPartialDeriv (List.replicate (j + 1) i) f z * + iteratedPartialDeriv (List.replicate (k - j) i) g z + + iteratedPartialDeriv (List.replicate j i) f z * + iteratedPartialDeriv (List.replicate (k - j + 1) i) g z) = + ∑ j ∈ Finset.range (k + 1), (k.choose j : ℂ) * (X (j + 1) + X j) := by + apply Finset.sum_congr rfl + intro j hj + simp only [Finset.mem_range] at hj + have e1 : k - j = k + 1 - (j + 1) := by omega + have e3 : k + 1 - (j + 1) + 1 = k + 1 - j := by omega + simp only [hXdef, e1, e3] + rw [hgoal, sum_choose_shift] + +section MultiIndex + +variable {d : ℕ} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A canonical list containing coordinate `i` exactly `m i` times. -/ +@[expose] def multiIndexList (m : Fin d → ℕ) : List (Fin d) := + (List.ofFn (fun i => List.replicate (m i) i)).flatten + +/-- The canonical coordinate list has the prescribed multiplicities. -/ +@[simp] theorem count_multiIndexList (m : Fin d → ℕ) (i : Fin d) : + (multiIndexList m).count i = m i := by + simp [multiIndexList, List.count_flatten, List.map_ofFn, List.count_replicate, + List.sum_ofFn] + +/-- The mixed coordinate derivative of multi-index `m`, in canonical coordinate order. For +holomorphic maps, permutation invariance makes the choice of order immaterial. -/ +@[expose] def multiIndexDeriv (m : Fin d → ℕ) (f : (Fin d → ℂ) → E) : (Fin d → ℂ) → E := + iteratedPartialDeriv (multiIndexList m) f + +variable [CompleteSpace E] + +/-- The mixed derivative can be computed in any order with the prescribed multiplicities. -/ +theorem iteratedPartialDeriv_eq_multiIndexDeriv {U : Set (Fin d → ℂ)} + {f : (Fin d → ℂ) → E} (hf : AnalyticOnNhd ℂ f U) (hU : IsOpen U) + {z : Fin d → ℂ} (hz : z ∈ U) {is : List (Fin d)} {m : Fin d → ℕ} + (hm : ∀ i, is.count i = m i) : iteratedPartialDeriv is f z = multiIndexDeriv m f z := by + apply iteratedPartialDeriv_perm hf hU _ hz + apply List.perm_iff_count.mpr + simpa using hm + +end MultiIndex + +/-- The complex Jacobian in the standard coordinate bases. -/ +@[expose] def complexJacobian {κ : Type*} (f : (ι → ℂ) → (κ → ℂ)) (z : ι → ℂ) : Matrix κ ι ℂ := + fun j i => partialDeriv i (fun w => f w j) z + +/-- Entries of the complex Jacobian are the coordinate entries of the Fréchet derivative. -/ +theorem complexJacobian_apply {κ : Type*} [Fintype κ] + {f : (ι → ℂ) → (κ → ℂ)} {z : ι → ℂ} (hf : DifferentiableAt ℂ f z) + (j : κ) (i : ι) : complexJacobian f z j i = fderiv ℂ f z (Pi.single i 1) j := by + rw [complexJacobian, partialDeriv_eq_fderiv (differentiableAt_pi.mp hf j), fderiv_apply hf j] + rfl + +omit [CompleteSpace F] in +/-- The coordinate chain rule, with an arbitrary complex normed outer target. -/ +theorem partialDeriv_comp {κ : Type*} [Fintype κ] [DecidableEq κ] + {f : (ι → ℂ) → (κ → ℂ)} {g : (κ → ℂ) → F} {z : ι → ℂ} + (hg : DifferentiableAt ℂ g (f z)) (hf : DifferentiableAt ℂ f z) (i : ι) : + partialDeriv i (g ∘ f) z = ∑ j, complexJacobian f z j i • partialDeriv j g (f z) := by + rw [partialDeriv_eq_fderiv (hg.comp z hf), fderiv_comp z hg hf] + simp only [ContinuousLinearMap.comp_apply] + rw [fderiv_eq_sum_partialDeriv hg] + simp_rw [complexJacobian_apply hf] + +/-- Jacobians compose by matrix multiplication. -/ +theorem complexJacobian_comp {κ ν : Type*} [Fintype κ] [DecidableEq κ] [Fintype ν] + {f : (ι → ℂ) → (κ → ℂ)} {g : (κ → ℂ) → (ν → ℂ)} {z : ι → ℂ} + (hg : DifferentiableAt ℂ g (f z)) (hf : DifferentiableAt ℂ f z) : + complexJacobian (g ∘ f) z = complexJacobian g (f z) * complexJacobian f z := by + ext j i + change partialDeriv i ((fun w => g w j) ∘ f) z = _ + rw [partialDeriv_comp (differentiableAt_pi.mp hg j) hf] + simp [Matrix.mul_apply, complexJacobian, smul_eq_mul, mul_comm] + +/-- The complex Jacobian is Mathlib's matrix of the complex Fréchet derivative in the standard +coordinate bases. -/ +theorem complexJacobian_eq_toMatrix {κ : Type*} [Fintype κ] + {f : (ι → ℂ) → (κ → ℂ)} {z : ι → ℂ} (hf : DifferentiableAt ℂ f z) : + complexJacobian f z = LinearMap.toMatrix' (fderiv ℂ f z).toLinearMap := by + ext j i + exact complexJacobian_apply hf j i + +/-- The Jacobian of the identity map is the identity matrix, including with no coordinates. -/ +theorem complexJacobian_id (z : ι → ℂ) : complexJacobian id z = 1 := by + rw [complexJacobian_eq_toMatrix differentiableAt_id] + simp + +/-- The determinant form of the chain rule for maps between equal coordinate spaces. -/ +theorem det_complexJacobian_comp {f g : (ι → ℂ) → (ι → ℂ)} {z : ι → ℂ} + (hg : DifferentiableAt ℂ g (f z)) (hf : DifferentiableAt ℂ f z) : + (complexJacobian (g ∘ f) z).det = + (complexJacobian g (f z)).det * (complexJacobian f z).det := by + rw [complexJacobian_comp hg hf, Matrix.det_mul] + +/-- A square complex Jacobian has nonzero determinant exactly when the Fréchet derivative is +invertible. Differentiability is explicit because the derivative is otherwise totalized. -/ +theorem det_complexJacobian_ne_zero_iff {f : (ι → ℂ) → (ι → ℂ)} {z : ι → ℂ} + (hf : DifferentiableAt ℂ f z) : + (complexJacobian f z).det ≠ 0 ↔ (fderiv ℂ f z).IsInvertible := by + have hm : (complexJacobian f z).mulVec = fderiv ℂ f z := by + funext v + rw [complexJacobian_eq_toMatrix hf] + exact LinearMap.toMatrix'_mulVec _ v + have hi : Function.Injective (fderiv ℂ f z) ↔ (complexJacobian f z).det ≠ 0 := by + rw [← hm, Matrix.mulVec_injective_iff_isUnit, Matrix.isUnit_iff_isUnit_det, + isUnit_iff_ne_zero] + constructor + · intro h + have hinj := hi.mpr h + exact ⟨(LinearEquiv.ofBijective (fderiv ℂ f z).toLinearMap + ⟨hinj, LinearMap.surjective_of_injective hinj⟩).toContinuousLinearEquiv, rfl⟩ + · exact fun h => hi.mp h.injective + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean new file mode 100644 index 0000000000..c642bd59fe --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean @@ -0,0 +1,222 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension + +/-! +# Local continuation and domains of holomorphy + +Common continuation from `U` to `V` requires agreement only on a specified overlap `W`. It does +not require `U ⊆ V`, or agreement on every component of `U ∩ V`. `IsDomainOfHolomorphy` excludes +such a common continuation outside `U`. `IsDomainOfExistence` excludes continuation of one +specified scalar function. Openness and connectedness of `U` are separate; the predicates also +apply to disconnected open sets. The whole space and the empty set are included. + +References: [Jakóbczak–Jarnicki][JakobczakJarnicki2021] §2.7; [Scheidemann][Scheidemann2005] +§7.2; [Boas][Boas2013] §4.2.3. These definitions do not construct Riemann domains or envelopes +of holomorphy. + +## Main definitions + +* `HasCommonAnalyticContinuation`: All scalar analytic functions on `U` continue to `V`, with + agreement on `W`. +* `IsDomainOfHolomorphy`: No common continuation through a nonempty open overlap reaches outside + `U`. +* `IsDomainOfExistence`: A scalar function is analytic on `U` and has no continuation beyond it from + any nonempty open overlap. + +## Main results + +* `IsDomainOfExistence.isDomainOfHolomorphy`: The domain of existence of one function is a domain of + holomorphy. +* `IsDomainOfHolomorphy.eq_of_commonExtension`: A domain of holomorphy admits no proper connected + common extension containing it. +* `isDomainOfHolomorphy_of_entire_separators`: Entire functions vanishing at each exterior point but + nowhere on `U` obstruct all common continuation outside `U`, by applying the identity theorem to + their reciprocals. +* `isDomainOfHolomorphy_complex`: Every subset of the complex plane satisfies the analytic + continuation obstruction; in particular every planar open set is a domain of holomorphy. +* `isDomainOfHolomorphy_pi`: Finite products of planar open sets are domains of holomorphy. +* `isDomainOfHolomorphy_of_convex`: Every real-convex open subset of a finite-dimensional complex + normed space is a domain of holomorphy. +* `IsDomainOfHolomorphy.image_equiv`: The domain-of-holomorphy property is invariant under + continuous linear equivalences. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- All scalar analytic functions on `U` continue to `V`, with agreement on `W`. Containment and +topological assumptions are supplied separately. -/ +@[expose] def HasCommonAnalyticContinuation (U V W : Set E) : Prop := + ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → + ∃ g : E → ℂ, AnalyticOnNhd ℂ g V ∧ EqOn g f W + +/-- No common continuation through a nonempty open overlap reaches outside `U`. For open `U`, this +is the domain-of-holomorphy property, without imposing connectedness. -/ +@[expose] def IsDomainOfHolomorphy (U : Set E) : Prop := + ∀ V W : Set E, IsOpen V → IsConnected V → IsOpen W → W.Nonempty → + W ⊆ U → W ⊆ V → HasCommonAnalyticContinuation U V W → V ⊆ U + +/-- A scalar function is analytic on `U` and has no continuation beyond it from any nonempty open +overlap. This is the strong, local meaning of domain of existence. -/ +@[expose] def IsDomainOfExistence (U : Set E) (f : E → ℂ) : Prop := + AnalyticOnNhd ℂ f U ∧ + ∀ V W : Set E, IsOpen V → IsConnected V → IsOpen W → W.Nonempty → + W ⊆ U → W ⊆ V → (∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f W) → V ⊆ U + +/-- The domain-of-holomorphy property is invariant under continuous linear equivalences. -/ +theorem IsDomainOfHolomorphy.image_equiv {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + {U : Set E} (h : IsDomainOfHolomorphy U) (L : E ≃L[ℂ] F) : + IsDomainOfHolomorphy (L '' U) := by + intro V W hV hVc hW hWne hWU hWV hcont + have himg : ∀ z : F, z ∈ L '' U ↔ L.symm z ∈ U := fun z => by + constructor + · rintro ⟨x, hx, rfl⟩ + simpa using hx + · intro hz + exact ⟨L.symm z, hz, L.apply_symm_apply z⟩ + have hV' : IsOpen (L ⁻¹' V) := hV.preimage L.continuous + have hVc' : IsConnected (L ⁻¹' V) := by + rw [← L.image_symm_eq_preimage] + exact hVc.image _ L.symm.continuous.continuousOn + have hW' : IsOpen (L ⁻¹' W) := hW.preimage L.continuous + have hWne' : (L ⁻¹' W).Nonempty := by + obtain ⟨w, hw⟩ := hWne + exact ⟨L.symm w, by simpa using hw⟩ + have hWU' : L ⁻¹' W ⊆ U := fun z hz => by + have := (himg (L z)).mp (hWU hz) + simpa using this + have hWV' : L ⁻¹' W ⊆ L ⁻¹' V := fun z hz => hWV hz + have hcont' : HasCommonAnalyticContinuation U (L ⁻¹' V) (L ⁻¹' W) := by + intro f hf + have hf' : AnalyticOnNhd ℂ (f ∘ L.symm) (L '' U) := + hf.comp (L.symm.toContinuousLinearMap.analyticOnNhd _) fun z hz => (himg z).mp hz + obtain ⟨g, hg, hgf⟩ := hcont _ hf' + refine ⟨g ∘ L, hg.comp (L.toContinuousLinearMap.analyticOnNhd _) fun z hz => hz, + fun z hz => ?_⟩ + have := hgf hz + simpa using this + have hsub : L ⁻¹' V ⊆ U := h _ _ hV' hVc' hW' hWne' hWU' hWV' hcont' + intro z hz + rw [himg] + exact hsub (by simpa using hz) + +/-- A common extension to a containing set is a common continuation on any smaller overlap. -/ +theorem IsCommonAnalyticExtension.hasCommonAnalyticContinuation {U V W : Set E} + (h : IsCommonAnalyticExtension U V) (hWU : W ⊆ U) : + HasCommonAnalyticContinuation U V W := by + intro f hf + obtain ⟨g, hg, he⟩ := h.exists_extension hf + exact ⟨g, hg, he.mono hWU⟩ + +/-- The domain of existence of one function is a domain of holomorphy. -/ +theorem IsDomainOfExistence.isDomainOfHolomorphy {U : Set E} {f : E → ℂ} + (h : IsDomainOfExistence U f) : IsDomainOfHolomorphy U := + fun V W hV hc hW hn hWU hWV he => h.2 V W hV hc hW hn hWU hWV (he f h.1) + +/-- The whole ambient space is a domain of holomorphy. -/ +theorem isDomainOfHolomorphy_univ : IsDomainOfHolomorphy (univ : Set E) := + fun _ _ _ _ _ _ _ _ _ => subset_univ _ + +/-- The empty open set satisfies the domain-of-holomorphy property vacuously. -/ +theorem isDomainOfHolomorphy_empty : IsDomainOfHolomorphy (∅ : Set E) := by + intro V W _ _ _ hn hWU _ _ + obtain ⟨w, hw⟩ := hn + exact (hWU hw).elim + +/-- A function analytic on the whole space has that space as its domain of existence. -/ +theorem isDomainOfExistence_univ {f : E → ℂ} (hf : AnalyticOnNhd ℂ f univ) : + IsDomainOfExistence univ f := ⟨hf, fun _ _ _ _ _ _ _ _ _ => subset_univ _⟩ + +/-- A domain of holomorphy admits no proper connected common extension containing it. -/ +theorem IsDomainOfHolomorphy.eq_of_commonExtension {U V : Set E} + (h : IsDomainOfHolomorphy U) (hU : IsOpen U) (hn : U.Nonempty) + (hV : IsOpen V) (hc : IsConnected V) (he : IsCommonAnalyticExtension U V) : V = U := + Subset.antisymm + (h V U hV hc hU hn Subset.rfl he.subset + (he.hasCommonAnalyticContinuation Subset.rfl)) he.subset + +/-- Entire functions vanishing at each exterior point but nowhere on `U` obstruct all common +continuation outside `U`, by applying the identity theorem to their reciprocals. -/ +theorem isDomainOfHolomorphy_of_entire_separators {U : Set E} + (hsep : ∀ a ∉ U, ∃ q : E → ℂ, AnalyticOnNhd ℂ q univ ∧ + q a = 0 ∧ ∀ z ∈ U, q z ≠ 0) : IsDomainOfHolomorphy U := by + intro V W _ hc hW hn hWU hWV he a ha + by_contra hna + obtain ⟨q, hq, hqa, hqU⟩ := hsep a hna + have hi : AnalyticOnNhd ℂ (fun z => (q z)⁻¹) U := + fun z hz => (hq z (mem_univ z)).inv (hqU z hz) + obtain ⟨g, hg, hge⟩ := he _ hi + have hp : AnalyticOnNhd ℂ (fun z => q z * g z) V := (hq.mono (subset_univ V)).mul hg + obtain ⟨w, hw⟩ := hn + have hlocal : (fun z => q z * g z) =ᶠ[𝓝 w] (fun _ => (1 : ℂ)) := by + filter_upwards [hW.mem_nhds hw] with z hz + rw [hge hz, mul_inv_cancel₀ (hqU z (hWU hz))] + have heq := hp.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const + hc.isPreconnected (hWV hw) hlocal + have hbad := heq ha + simp [hqa] at hbad + +/-- Every subset of the complex plane satisfies the analytic continuation obstruction; in particular +every planar open set is a domain of holomorphy. -/ +theorem isDomainOfHolomorphy_complex (U : Set ℂ) : IsDomainOfHolomorphy U := by + apply isDomainOfHolomorphy_of_entire_separators + intro a ha + refine ⟨fun z => z - a, analyticOnNhd_id.sub analyticOnNhd_const, sub_self a, ?_⟩ + intro z hz he + exact ha (sub_eq_zero.mp he ▸ hz) + +/-- Finite products of planar open sets are domains of holomorphy. The continuation obstruction +itself holds for arbitrary planar factors and includes an empty index type. -/ +theorem isDomainOfHolomorphy_pi {ι : Type*} [Fintype ι] (S : ι → Set ℂ) : + IsDomainOfHolomorphy (Set.pi univ S) := by + apply isDomainOfHolomorphy_of_entire_separators + intro a ha + have hnot : ¬ ∀ i, a i ∈ S i := by + intro h + exact ha (fun i _ => h i) + obtain ⟨i, hi⟩ := not_forall.mp hnot + refine ⟨fun z => z i - a i, + ((ContinuousLinearMap.proj i : (ι → ℂ) →L[ℂ] ℂ).analyticOnNhd univ).sub + analyticOnNhd_const, sub_self _, ?_⟩ + intro z hz he + apply hi + rw [← sub_eq_zero.mp he] + exact hz i (mem_univ i) + +/-- Every real-convex open subset of a finite-dimensional complex normed space is a domain of +holomorphy. A separating real functional is complexified to give a pole. -/ +theorem isDomainOfHolomorphy_of_convex [FiniteDimensional ℂ E] {U : Set E} + (hU : Convex ℝ U) (ho : IsOpen U) : IsDomainOfHolomorphy U := by + apply isDomainOfHolomorphy_of_entire_separators + intro a ha + obtain ⟨l, hl⟩ := geometric_hahn_banach_open_point hU ho ha + let L : E →L[ℂ] ℂ := l.extendRCLike + refine ⟨fun z => L z - L a, (L.analyticOnNhd univ).sub analyticOnNhd_const, sub_self _, ?_⟩ + intro z hz he + have he' : l z = l a := by + simpa only [L, StrongDual.re_extendRCLike_apply] using + congrArg (RCLike.re : ℂ → ℝ) (sub_eq_zero.mp he) + exact (ne_of_lt (hl z hz)) he' + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DominatedIntegral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DominatedIntegral.lean new file mode 100644 index 0000000000..4d2507f38c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DominatedIntegral.lean @@ -0,0 +1,86 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Schwarz +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral + +/-! +# Locally dominated holomorphic integrals + +A locally uniform integrable bound on a holomorphic integrand also bounds its derivatives on +smaller balls, by the Schwarz estimate. This avoids explicit logarithmic estimates when the +parameters occur in complex powers. Measurability of the derivative is kept as a separate +hypothesis so that the integration space needs no topology. + +## Main results + +`analyticOnNhd_integral_of_locally_dominated` is holomorphy of a parameter-dependent integral +under a locally integrable dominant, without a logarithmic estimate on the parameter. +-/ + +open Complex MeasureTheory Filter Metric Set +open scoped Topology +public section +variable {α P E : Type*} [MeasurableSpace α] + [NormedAddCommGroup P] [NormedSpace ℂ P] [FiniteDimensional ℂ P] + [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-- A locally dominated holomorphic integrand has a holomorphic integral. The derivative +measurability assumption is often obtained from continuity on the integration domain. -/ +theorem analyticOnNhd_integral_of_locally_dominated + {μ : Measure α} {U : Set P} {F : P → α → E} + (hU : IsOpen U) + (hmeas : ∀ x ∈ U, AEStronglyMeasurable (F x) μ) + (hderivmeas : ∀ x ∈ U, + AEStronglyMeasurable (fun a => fderiv ℂ (F · a) x) μ) + (hhol : ∀ᵐ a ∂μ, AnalyticOnNhd ℂ (F · a) U) + (hdom : ∀ x ∈ U, ∃ (s : Set P) (bound : α → ℝ), + s ∈ nhds x ∧ Integrable bound μ ∧ + ∀ᵐ a ∂μ, ∀ y ∈ s, ‖F y a‖ ≤ bound a) : + AnalyticOnNhd ℂ (fun x => ∫ a, F x a ∂μ) U := by + apply analyticOnNhd_integral_of_dominated_of_fderiv_le hU + intro x hx + obtain ⟨s, bound, hs, hboundInt, hbound⟩ := hdom x hx + obtain ⟨ε, hε, hball⟩ := Metric.mem_nhds_iff.mp (inter_mem hs (hU.mem_nhds hx)) + have hsub : ball x ε ⊆ U := fun y hy => (hball hy).2 + have hbnd : ∀ᵐ a ∂μ, ∀ y ∈ ball x ε, ‖F y a‖ ≤ bound a := + hbound.mono fun a ha y hy => ha y (hball hy).1 + let r := ε / 2 + have hr : 0 < r := half_pos hε + have hsmall : ball x r ⊆ ball x ε := ball_subset_ball (half_le_self hε.le) + have hnear (y : P) (hy : y ∈ ball x r) : ball y r ⊆ ball x ε := by + intro w hw + rw [mem_ball] at * + calc + dist w x ≤ dist w y + dist y x := dist_triangle _ _ _ + _ < r + r := add_lt_add hw hy + _ = ε := by dsimp [r]; ring + refine ⟨ball x r, (fun a => (2 * bound a) / r), + (fun y a => fderiv ℂ (F · a) y), ball_mem_nhds x hr, ?_, ?_, + hderivmeas x hx, ?_, ?_, ?_⟩ + · filter_upwards [hU.mem_nhds hx] with y hy + exact hmeas y hy + · exact hboundInt.mono' (hmeas x hx) + (hbnd.mono fun a ha => ha x (mem_ball_self hε)) + · filter_upwards [hhol, hbnd] with a ha hba + intro y hy + apply norm_fderiv_le_div_of_mapsTo_ball + (ha.differentiableOn.mono ((hnear y hy).trans hsub)) ?_ hr + intro w hw + rw [mem_closedBall, dist_eq_norm] + calc + ‖F w a - F y a‖ ≤ ‖F w a‖ + ‖F y a‖ := norm_sub_le _ _ + _ ≤ bound a + bound a := add_le_add (hba w (hnear y hy hw)) (hba y (hsmall hy)) + _ = 2 * bound a := by ring + · exact (hboundInt.const_mul 2).div_const r + · filter_upwards [hhol] with a ha + intro y hy + exact (ha y (hsub (hsmall hy))).differentiableAt.hasFDerivAt + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace.lean new file mode 100644 index 0000000000..9e29d906df --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace.lean @@ -0,0 +1,210 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Algebra.UniformConvergence +public import Mathlib.Topology.ContinuousMap.Algebra +public import Mathlib.Topology.UniformSpace.CompactConvergence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Holomorphic maps with the compact-open topology + +Holomorphic maps on an open subset of a complex normed space form a complex submodule of +continuous maps. For finite-dimensional source spaces and Banach targets this submodule is +closed. The topology and uniformity are inherited from Mathlib's continuous-map space, not from +a global sup norm. In particular, the space is complete for Banach targets. + +The zero extension below is only a device for expressing `AnalyticOnNhd` on the ambient space. +No continuity or analyticity at the boundary of the domain is asserted. + +## Main definitions + +* `openExtension`: Extend a continuous map on an open domain by zero; used only for local analytic + predicates. +* `holomorphicSubmodule`: Holomorphic maps are a submodule of continuous maps on the open domain. +* `HolomorphicMap`: Holomorphic maps on an open domain, with the induced compact-open topology and + uniformity. +* `holomorphicRestrict`: Restriction to a smaller open domain preserves holomorphy. +* `holomorphicPartialDeriv`: Coordinate differentiation as an operator on holomorphic maps. + +## Main results + +* `isClosed_holomorphicSubmodule`: Weierstrass convergence makes the holomorphic submodule closed. +* `holomorphicMap_tendsto_iff`: The inherited topology on holomorphic maps is precisely locally + uniform convergence. +* `continuous_holomorphicRestrict`: Restriction is continuous for the compact-open topology. +* `continuous_holomorphicPartialDeriv`: Coordinate differentiation is continuous for the + compact-open topology. +-/ + +public noncomputable section + +open Filter Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [NormedAddCommGroup F] + [NormedSpace ℂ F] + +open scoped Classical in +/-- Extend a continuous map on an open domain by zero; used only for local analytic predicates. -/ +@[expose] def openExtension (U : TopologicalSpace.Opens E) (f : C(U, F)) (z : E) : F := + if hz : z ∈ U then f ⟨z, hz⟩ else 0 + +omit [NormedSpace ℂ E] [NormedSpace ℂ F] in +/-- The value of the extension by zero at a point of the open set. -/ +theorem openExtension_apply (U : TopologicalSpace.Opens E) + (f : C(U, F)) {z : E} (hz : z ∈ U) : openExtension U f z = f ⟨z, hz⟩ := + dite_eq_left hz + +omit [NormedSpace ℂ E] [NormedSpace ℂ F] in +/-- The extension by zero restricts to the original function. -/ +@[simp] theorem openExtension_coe (U : TopologicalSpace.Opens E) + (f : C(U, F)) (z : U) : openExtension U f z = f z := by + simp [openExtension, z.property] + +/-- Holomorphic maps are a submodule of continuous maps on the open domain. -/ +@[expose] def holomorphicSubmodule (U : TopologicalSpace.Opens E) : Submodule ℂ C(U, F) where + carrier := {f | AnalyticOnNhd ℂ (openExtension U f) U} + zero_mem' := by + change AnalyticOnNhd ℂ (openExtension U 0) U + have h : openExtension U (0 : C(U, F)) = fun _ => 0 := by + funext z + simp [openExtension] + rw [h] + exact analyticOnNhd_const + add_mem' := by + intro f g hf hg + change AnalyticOnNhd ℂ (openExtension U (f + g)) U + have h : openExtension U (f + g) = openExtension U f + openExtension U g := by + funext z + by_cases hz : z ∈ U <;> simp [openExtension, hz] + rw [h] + exact hf.add hg + smul_mem' := by + intro c f hf + change AnalyticOnNhd ℂ (openExtension U (c • f)) U + have h : openExtension U (c • f) = c • openExtension U f := by + funext z + by_cases hz : z ∈ U <;> simp [openExtension, hz] + rw [h] + exact hf.const_smul + +/-- Holomorphic maps on an open domain, with the induced compact-open topology and uniformity. -/ +abbrev HolomorphicMap (U : TopologicalSpace.Opens E) (F : Type*) + [NormedAddCommGroup F] [NormedSpace ℂ F] : Type _ := ↥(holomorphicSubmodule (F := F) U) + +/-- Subtraction is uniformly continuous for the compact-open uniformity on holomorphic maps. -/ +instance (U : TopologicalSpace.Opens E) : IsUniformAddGroup (HolomorphicMap U F) where + uniformContinuous_sub := by + apply isUniformEmbedding_subtype_val.uniformContinuous_iff.mpr + apply ContinuousMap.isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous_iff.mpr + have h : UniformContinuous (fun f : HolomorphicMap U F => + ContinuousMap.toUniformOnFunIsCompact f.val) := + ContinuousMap.isUniformEmbedding_toUniformOnFunIsCompact.uniformContinuous.comp + uniformContinuous_subtype_val + exact (h.comp uniformContinuous_fst).sub (h.comp uniformContinuous_snd) + +variable [CompleteSpace F] + +omit [NormedSpace ℂ E] [NormedSpace ℂ F] [CompleteSpace F] in +/-- Convergence in the continuous-map space is exactly locally uniform convergence of the ambient +extensions on the open domain. -/ +theorem tendsto_iff_openExtension [LocallyCompactSpace E] {U : TopologicalSpace.Opens E} + {κ : Type*} {l : Filter κ} {f : κ → C(U, F)} {g : C(U, F)} : + Tendsto f l (𝓝 g) ↔ + TendstoLocallyUniformlyOn (fun n => openExtension U (f n)) (openExtension U g) l U := by + let := U.isOpen.locallyCompactSpace + rw [ContinuousMap.tendsto_iff_tendstoLocallyUniformly, + tendstoLocallyUniformlyOn_iff_tendstoLocallyUniformly_comp_coe] + simp only [Function.comp_def, openExtension_coe] + rfl + +/-- Weierstrass convergence makes the holomorphic submodule closed. -/ +theorem isClosed_holomorphicSubmodule [FiniteDimensional ℂ E] (U : TopologicalSpace.Opens E) : + IsClosed (holomorphicSubmodule (F := F) U : Set C(U, F)) := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + rw [isClosed_iff_forall_filter] + intro f l hl hmem hlim + have hc : Tendsto (fun g : C(U, F) => g) l (𝓝 f) := hlim + exact (tendsto_iff_openExtension.mp hc).analyticOnNhd_of_finiteDimensional + (le_principal_iff.mp hmem) U.isOpen + +/-- The compact-open uniform space of holomorphic maps into a Banach space is complete. -/ +instance [FiniteDimensional ℂ E] (U : TopologicalSpace.Opens E) : CompleteSpace (HolomorphicMap U + F) := + (isClosed_holomorphicSubmodule (F := F) U).isComplete.completeSpace_coe + +omit [CompleteSpace F] in +/-- Evaluation at a point is continuous in the compact-open topology. -/ +theorem continuous_holomorphicMap_eval (U : TopologicalSpace.Opens E) (z : U) : + Continuous (fun f : HolomorphicMap U F => f.val z) := + (continuous_eval_const z).comp continuous_subtype_val + +omit [CompleteSpace F] in +/-- The inherited topology on holomorphic maps is precisely locally uniform convergence. -/ +theorem holomorphicMap_tendsto_iff [LocallyCompactSpace E] {U : TopologicalSpace.Opens E} + {κ : Type*} {l : Filter κ} {f : κ → HolomorphicMap U F} {g : HolomorphicMap U F} : + Tendsto f l (𝓝 g) ↔ TendstoLocallyUniformlyOn + (fun n => openExtension U (f n).val) (openExtension U g.val) l U := by + rw [tendsto_subtype_rng, tendsto_iff_openExtension] + +omit [CompleteSpace F] in +/-- Restriction to a smaller open domain preserves holomorphy. -/ +@[expose] def holomorphicRestrict {U V : TopologicalSpace.Opens E} (hVU : V ≤ U) + (f : HolomorphicMap U F) : HolomorphicMap V F := by + let inc : C(V, U) := ⟨fun z => ⟨z, hVU z.property⟩, + continuous_subtype_val.subtype_mk _⟩ + refine ⟨f.val.comp inc, ?_⟩ + apply AnalyticOnNhd.congr V.isOpen (f.property.mono hVU) + intro z hz + rw [openExtension_apply U _ (hVU hz), openExtension_apply V _ hz] + rfl + +omit [CompleteSpace F] in +/-- Restriction is continuous for the compact-open topology. -/ +theorem continuous_holomorphicRestrict {U V : TopologicalSpace.Opens E} + (hVU : V ≤ U) : Continuous (holomorphicRestrict (F := F) hVU) := by + apply Continuous.subtype_mk + exact (ContinuousMap.continuous_precomp + ⟨fun z : V => (⟨z, hVU z.property⟩ : U), continuous_subtype_val.subtype_mk _⟩).comp + continuous_subtype_val + +variable {ι : Type*} [Fintype ι] [DecidableEq ι] + +/-- Coordinate differentiation as an operator on holomorphic maps. -/ +def holomorphicPartialDeriv (U : TopologicalSpace.Opens (ι → ℂ)) (i : ι) + (f : HolomorphicMap U F) : HolomorphicMap U F := by + have ha := f.property.partialDeriv U.isOpen i + refine ⟨⟨fun z => partialDeriv i (openExtension U f.val) z, + ha.continuousOn.domRestrict⟩, ?_⟩ + apply AnalyticOnNhd.congr U.isOpen ha + intro z hz + rw [openExtension_apply U _ hz] + rfl + +/-- Coordinate differentiation is continuous for the compact-open topology. -/ +theorem continuous_holomorphicPartialDeriv (U : TopologicalSpace.Opens (ι → ℂ)) (i : ι) : + Continuous (holomorphicPartialDeriv (F := F) U i) := by + rw [continuous_iff_continuousAt] + intro f + change Tendsto _ (𝓝 f) _ + rw [holomorphicMap_tendsto_iff] + have hlim := (holomorphicMap_tendsto_iff (f := fun g : HolomorphicMap U F => g)).mp + (tendsto_id : Tendsto (fun g : HolomorphicMap U F => g) (𝓝 f) (𝓝 f)) + have hd := hlim.partialDeriv (Eventually.of_forall fun g => g.property) U.isOpen i + apply (hd.congr (fun g z hz => ?_)).congr_right (fun z hz => ?_) + all_goals + rw [openExtension_apply U _ hz] + rfl + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace/Extension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace/Extension.lean new file mode 100644 index 0000000000..a73fd29903 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/FunctionSpace/Extension.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple + +/-! +# Restriction and continuous extension of holomorphic maps + +Restriction is a continuous linear map, injective from a connected larger domain when the +smaller domain is nonempty. When it is surjective, its inverse is continuous for the +compact-open topology, by the Fréchet open-mapping argument for complete metrizable topological +vector spaces. Reference: [Scheidemann][Scheidemann2005] (2005), Proposition 2.1.3 and Exercise +2.1.13. + +## Main results + +`holomorphicRestrictCLM` is restriction as a continuous linear map. +`exists_holomorphicRestrictionEquiv` is a compact-open isomorphism when restriction is +bijective. `HolomorphicAlgebra` is the scalar holomorphic algebra, with +`holomorphicRestrictAlgHom` and `holomorphicRestrictionAlgEquiv` as the algebraic restriction +maps. `exists_holomorphicAlgebraEquiv_of_commonExtension` is an algebra isomorphism from a +common extension domain. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [NormedAddCommGroup F] + [NormedSpace ℂ F] + {U V : TopologicalSpace.Opens E} + +/-- Restriction as a continuous complex-linear operator between compact-open spaces. -/ +@[expose] def holomorphicRestrictCLM (hVU : V ≤ U) : HolomorphicMap U F →L[ℂ] HolomorphicMap V F + where + toFun := holomorphicRestrict hVU + map_add' := by intro f g; rfl + map_smul' := by intro c f; rfl + cont := continuous_holomorphicRestrict hVU + +/-- An ambient extension theorem makes restriction surjective on the bundled spaces. -/ +theorem holomorphicRestrict_surjective (hVU : V ≤ U) + (hext : ∀ f : E → F, AnalyticOnNhd ℂ f V → + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f V) : + Function.Surjective (holomorphicRestrict (F := F) hVU) := by + intro f + obtain ⟨g, hg, heq⟩ := hext (openExtension V f.val) f.property + let G : HolomorphicMap U F := ⟨⟨fun z => g z, hg.continuousOn.domRestrict⟩, + hg.congr U.isOpen (fun z hz => by rw [openExtension_apply U _ hz]; rfl)⟩ + refine ⟨G, ?_⟩ + apply Subtype.ext + apply ContinuousMap.ext + intro z + exact (heq z.property).trans (openExtension_coe V f.val z) + +/-- On a connected larger domain, restriction to a nonempty open subset is injective. -/ +theorem holomorphicRestrict_injective (hVU : V ≤ U) + (hc : IsPreconnected (U : Set E)) (hne : (V : Set E).Nonempty) : + Function.Injective (holomorphicRestrict (F := F) hVU) := by + intro f g he + have hEq : EqOn (openExtension U f.val) (openExtension U g.val) V := by + intro z hz + have h := congrArg (fun k : HolomorphicMap V F => k.val ⟨z, hz⟩) he + rw [openExtension_apply U _ (hVU hz), openExtension_apply U _ (hVU hz)] + exact h + obtain ⟨z, hz⟩ := hne + have hAll := f.property.eqOn_of_preconnected_of_eventuallyEq g.property hc (hVU hz) + (Filter.mem_of_superset (V.isOpen.mem_nhds hz) hEq) + apply Subtype.ext + apply ContinuousMap.ext + intro z + simpa only [openExtension_coe] using hAll z.property + +/-- Restriction to a dense open subset is injective, without connectedness or nonemptiness +assumptions on either domain. Continuity of the holomorphic representatives suffices. -/ +theorem holomorphicRestrict_injective_of_subset_closure (hVU : V ≤ U) + (hd : (U : Set E) ⊆ closure (V : Set E)) : + Function.Injective (holomorphicRestrict (F := F) hVU) := by + intro f g he + have hEq : EqOn (openExtension U f.val) (openExtension U g.val) V := by + intro z hz + have h := congrArg (fun k : HolomorphicMap V F => k.val ⟨z, hz⟩) he + rw [openExtension_apply U _ (hVU hz), openExtension_apply U _ (hVU hz)] + exact h + have hAll := hEq.of_subset_closure f.property.continuousOn g.property.continuousOn hVU hd + apply Subtype.ext + apply ContinuousMap.ext + intro z + simpa only [openExtension_coe] using hAll z.property + +/-- Surjective restriction is a continuous linear equivalence under the identity-theorem hypotheses, +by the open-mapping theorem for complete metrizable compact-open spaces. Banach-valued targets +need not be finite dimensional. -/ +theorem exists_holomorphicRestrictionEquiv [FiniteDimensional ℂ E] [CompleteSpace F] (hVU : V ≤ U) + (hc : IsPreconnected (U : Set E)) (hne : (V : Set E).Nonempty) + (hs : Function.Surjective (holomorphicRestrict (F := F) hVU)) : + ∃ e : HolomorphicMap U F ≃L[ℂ] HolomorphicMap V F, + (e : HolomorphicMap U F → HolomorphicMap V F) = holomorphicRestrict hVU := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + let : SecondCountableTopology E := (Module.finBasis ℂ + E).equivFunL.toHomeomorph.secondCountableTopology + let : LocallyCompactSpace U := U.isOpen.locallyCompactSpace + let : LocallyCompactSpace V := V.isOpen.locallyCompactSpace + have : (uniformity C(U, F)).IsCountablyGenerated := inferInstance + have : (uniformity C(V, F)).IsCountablyGenerated := inferInstance + have : (uniformity (HolomorphicMap U F)).IsCountablyGenerated := + Filter.comap.isCountablyGenerated _ _ + have : (uniformity (HolomorphicMap V F)).IsCountablyGenerated := + Filter.comap.isCountablyGenerated _ _ + let : PseudoMetricSpace (HolomorphicMap U F) := UniformSpace.pseudoMetricSpace _ + let : PseudoMetricSpace (HolomorphicMap V F) := UniformSpace.pseudoMetricSpace _ + let e := LinearEquiv.ofBijective (holomorphicRestrictCLM (F := F) hVU).toLinearMap + ⟨holomorphicRestrict_injective hVU hc hne, hs⟩ + have hopen := ContinuousLinearMap.isOpenMap_of_surjective_complete (holomorphicRestrictCLM (F := + F) hVU) hs + exact ⟨ContinuousLinearEquiv.ofIsHomeomorph e + ⟨continuous_holomorphicRestrict hVU, + hopen, e.bijective⟩, rfl⟩ + +/-- Scalar holomorphic functions form a subalgebra of continuous functions. -/ +@[expose, reducible] +def holomorphicSubalgebra (U : TopologicalSpace.Opens E) : Subalgebra ℂ C(U, ℂ) where + carrier := (holomorphicSubmodule (F := ℂ) U : Set C(U, ℂ)) + zero_mem' := (holomorphicSubmodule U).zero_mem + add_mem' := (holomorphicSubmodule U).add_mem + mul_mem' := by + intro f g hf hg + apply AnalyticOnNhd.congr U.isOpen (hf.mul hg) + intro z hz + simp [openExtension_apply U _ hz] + algebraMap_mem' := by + intro c + apply AnalyticOnNhd.congr U.isOpen (analyticOnNhd_const (v := c)) + intro z hz + simp [openExtension_apply U _ hz] + +/-- The scalar holomorphic algebra has the same underlying type as the holomorphic space. -/ +abbrev HolomorphicAlgebra (U : TopologicalSpace.Opens E) : Type _ := ↥(holomorphicSubalgebra U) + +/-- Restriction preserves multiplication and constants as well as linear operations. -/ +@[expose] def holomorphicRestrictAlgHom (hVU : V ≤ U) : HolomorphicAlgebra U →ₐ[ℂ] + HolomorphicAlgebra V where + toFun := holomorphicRestrict hVU + map_zero' := rfl + map_one' := rfl + map_add' := by intros; rfl + map_mul' := by intros; rfl + commutes' := by intros; rfl + +/-- The algebra homomorphism has the same underlying function as ordinary restriction. -/ +@[simp] theorem holomorphicRestrictAlgHom_coe (hVU : V ≤ U) : + (holomorphicRestrictAlgHom hVU : HolomorphicAlgebra U → HolomorphicAlgebra V) = + holomorphicRestrict hVU := rfl + +/-- The algebraic restriction equivalence associated to surjectivity. Its continuity in both +directions is supplied by `exists_holomorphicRestrictionEquiv`. -/ +@[expose] def holomorphicRestrictionAlgEquiv (hVU : V ≤ U) + (hc : IsPreconnected (U : Set E)) (hne : (V : Set E).Nonempty) + (hs : Function.Surjective (holomorphicRestrict (F := ℂ) hVU)) : + HolomorphicAlgebra U ≃ₐ[ℂ] HolomorphicAlgebra V := + AlgEquiv.ofBijective (holomorphicRestrictAlgHom hVU) + ⟨holomorphicRestrict_injective hVU hc hne, hs⟩ + +/-- The scalar algebra equivalence is continuous in both directions for the compact-open topology, +using the Fréchet open-mapping theorem for inverse continuity. -/ +theorem continuous_holomorphicRestrictionAlgEquiv [FiniteDimensional ℂ E] (hVU : V ≤ U) + (hc : IsPreconnected (U : Set E)) (hne : (V : Set E).Nonempty) + (hs : Function.Surjective (holomorphicRestrict (F := ℂ) hVU)) : + Continuous (holomorphicRestrictionAlgEquiv hVU hc hne hs) ∧ + Continuous (holomorphicRestrictionAlgEquiv hVU hc hne hs).symm := by + obtain ⟨e, he⟩ := exists_holomorphicRestrictionEquiv hVU hc hne hs + refine ⟨continuous_holomorphicRestrict hVU, ?_⟩ + have hsymm : (fun f : HolomorphicAlgebra V => + (holomorphicRestrictionAlgEquiv hVU hc hne hs).symm f) = + (fun f : HolomorphicAlgebra V => e.symm f) := by + funext f + apply e.injective + rw [ContinuousLinearEquiv.apply_symm_apply, he] + exact (holomorphicRestrictionAlgEquiv hVU hc hne hs).apply_symm_apply f + change Continuous (fun f : HolomorphicAlgebra V => + (holomorphicRestrictionAlgEquiv hVU hc hne hs).symm f) + rw [hsymm] + exact e.symm.continuous + +/-- A common scalar extension pair gives an isomorphism of topological holomorphic algebras. The +connected larger set and nonempty smaller set ensure uniqueness. -/ +theorem exists_holomorphicAlgebraEquiv_of_commonExtension [FiniteDimensional ℂ E] + (h : IsCommonAnalyticExtension (V : Set E) (U : Set E)) + (hc : IsPreconnected (U : Set E)) (hne : (V : Set E).Nonempty) : + ∃ e : HolomorphicAlgebra U ≃ₐ[ℂ] HolomorphicAlgebra V, + (e : HolomorphicAlgebra U → HolomorphicAlgebra V) = holomorphicRestrict (F := ℂ) h.subset ∧ + Continuous e ∧ Continuous e.symm := by + have hs := holomorphicRestrict_surjective h.subset (fun _ hf => h.exists_extension hf) + exact ⟨holomorphicRestrictionAlgEquiv h.subset hc hne hs, rfl, + continuous_holomorphicRestrictionAlgEquiv h.subset hc hne hs⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsContinuation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsContinuation.lean new file mode 100644 index 0000000000..5bd2e30519 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsContinuation.lean @@ -0,0 +1,125 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy + +/-! +# Hartogs continuation over an arbitrary connected base + +An analytic function on an annular cylinder together with full disc fibers over a nonempty open +part of the base extends to the full cylinder. No local boundedness near the missing part is +assumed. The proof uses a fixed circle integral and the identity principle in the base. +Reference: [Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Theorem 2.6.1. + +## Main results + +`hartogsCylinder` is an annular cylinder together with full disc fibers over part of the base. +`exists_extension_hartogsCylinder` is Hartogs continuation across that figure, without a local +boundedness hypothesis on the missing part. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- An annular cylinder supplemented by full disc fibers over part of the base. -/ +@[expose] def hartogsCylinder (D D₀ : Set E) (ρ R : ℝ) : Set (E × ℂ) := + (D ×ˢ (ball 0 R \ closedBall 0 ρ)) ∪ (D₀ ×ˢ ball 0 R) + +/-- **Hartogs' continuity theorem.** The smaller base need not be connected. Finite positive +outer radius is used; no positive-dimensional base assumption is required. -/ +theorem exists_extension_hartogsCylinder {D D₀ : Set E} + (hD : IsOpen D) (hc : IsPreconnected D) (hD₀ : IsOpen D₀) (hne : D₀.Nonempty) + (hsub : D₀ ⊆ D) {ρ R : ℝ} (hρ : 0 ≤ ρ) (hρR : ρ < R) + {f : E × ℂ → F} (hf : AnalyticOnNhd ℂ f (hartogsCylinder D D₀ ρ R)) : + ∃ g, AnalyticOnNhd ℂ g (D ×ˢ ball 0 R) ∧ EqOn g f (hartogsCylinder D D₀ ρ R) := by + classical + obtain ⟨r, hρr, hrR⟩ := exists_between hρR + have hr : 0 < r := hρ.trans_lt hρr + let W : Set ((E × ℂ) × ℂ) := {q | (q.1.1, q.2) ∈ hartogsCylinder D D₀ ρ R ∧ q.2 ≠ q.1.2} + let H : (E × ℂ) × ℂ → F := fun q => (q.2 - q.1.2)⁻¹ • f (q.1.1, q.2) + have hH : AnalyticOnNhd ℂ H W := by + intro q hq + have hmap : AnalyticAt ℂ (fun q : (E × ℂ) × ℂ => (q.1.1, q.2)) q := + (analyticAt_fst.comp analyticAt_fst).prod analyticAt_snd + exact ((analyticAt_snd.sub (analyticAt_snd.comp analyticAt_fst)).inv + (sub_ne_zero.mpr hq.2)).smul + ((hf _ hq.1).comp_of_eq hmap rfl) + let J : E × ℂ → F := fun p => (2 * Real.pi * I : ℂ)⁻¹ • ∮ t in C(0, r), H (p, t) + have hJ : AnalyticOnNhd ℂ J (D ×ˢ ball 0 r) := by + apply (analyticOnNhd_circleIntegral_kernel (hD.prod isOpen_ball) hH hr.le ?_).const_smul + intro p hp t ht + have htn : ‖t‖ = r := by simpa [mem_sphere, dist_zero_right] using ht + refine ⟨Or.inl ⟨hp.1, ?_, ?_⟩, ?_⟩ + · simpa [mem_ball, dist_zero_right, htn] using hrR + · simpa [mem_closedBall, dist_zero_right, htn] using not_le.mpr hρr + · change t ≠ p.2 + intro he + have hpw : ‖p.2‖ < r := by simpa [mem_ball, dist_zero_right] using hp.2 + rw [he] at htn + linarith + have hJ₀ : ∀ z ∈ D₀, ∀ w ∈ ball (0 : ℂ) r, J (z, w) = f (z, w) := by + intro z hz w hw + have hs : AnalyticOnNhd ℂ (fun t => f (z, t)) (ball 0 R) := by + intro t ht + exact (hf _ (Or.inr ⟨hz, ht⟩)).comp (analyticAt_const.prod analyticAt_id) + exact Complex.two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable + (f := fun t => f (z, t)) countable_empty hw + (hs.continuousOn.mono (closedBall_subset_ball hrR)) + (fun t ht => (hs t (ball_subset_ball hrR.le ht.1)).differentiableAt) + have hJa : ∀ z ∈ D, ∀ w ∈ ball (0 : ℂ) r \ closedBall 0 ρ, J (z, w) = f (z, w) := by + intro z hz w hw + have hj : AnalyticOnNhd ℂ (fun z => J (z, w)) D := + fun z hz => (hJ _ ⟨hz, hw.1⟩).comp (analyticAt_id.prod analyticAt_const) + have hh : AnalyticOnNhd ℂ (fun z => f (z, w)) D := + fun z hz => (hf _ (Or.inl ⟨hz, ball_subset_ball hrR.le hw.1, hw.2⟩)).comp + (analyticAt_id.prod analyticAt_const) + obtain ⟨a, ha⟩ := hne + exact hj.eqOn_of_preconnected_of_eventuallyEq hh hc (hsub ha) + (Filter.mem_of_superset (hD₀.mem_nhds ha) (fun y hy => hJ₀ y hy w hw.1)) hz + let g : E × ℂ → F := fun p => if ‖p.2‖ < r then J p else f p + have hgf : EqOn g f (D ×ˢ (ball 0 R \ closedBall 0 ρ)) := by + intro p hp + dsimp [g] + split_ifs with hw + · exact hJa p.1 hp.1 p.2 ⟨by simpa [mem_ball, dist_zero_right] using hw, hp.2.2⟩ + · rfl + refine ⟨g, ?_, ?_⟩ + · intro p hp + by_cases hw : ‖p.2‖ < r + · have he : g =ᶠ[𝓝 p] J := by + filter_upwards [(isOpen_lt continuous_snd.norm continuous_const).mem_nhds hw] with q hq + simp [g, hq] + exact (analyticAt_congr he).mpr (hJ p ⟨hp.1, by simpa [mem_ball, dist_zero_right] using hw⟩) + · have hp' : p ∈ D ×ˢ (ball 0 R \ closedBall 0 ρ) := + ⟨hp.1, hp.2, by simpa [mem_closedBall, dist_zero_right] using (not_le.mpr + (hρr.trans_le (not_lt.mp hw)))⟩ + have he : g =ᶠ[𝓝 p] f := Filter.mem_of_superset + ((hD.prod (isOpen_ball.sdiff isClosed_closedBall)).mem_nhds hp') hgf + exact (analyticAt_congr he).mpr (hf p (Or.inl hp')) + · intro p hp + rcases hp with hp | hp + · exact hgf hp + · dsimp [g] + split_ifs with hw + · exact hJ₀ p.1 hp.1 p.2 (by simpa [mem_ball, dist_zero_right] using hw) + · rfl + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsDomain.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsDomain.lean new file mode 100644 index 0000000000..92b251a85f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsDomain.lean @@ -0,0 +1,260 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt + +/-! +# Hartogs sets and their fibers + +The product `E × ℂ` specifies a base and a distinguished complex fiber coordinate. `IsHartogs` +is rotational invariance in that coordinate; `IsCompleteHartogs` also allows contraction toward +zero. Openness, nonemptiness and connectedness of the total set are separate assumptions. +`HasPreconnectedFibers` is a further, independent property: empty fibers are allowed, and every +nonempty fiber is then connected. + +Complete Hartogs sets have star-convex, hence preconnected, fibers. Their base is exactly their +zero section. No symmetry or contraction in the base is required. To change the fiber center to +`a`, apply the predicates to `{p | (p.1, a + p.2) ∈ U}`. + +References: [Shabat][Shabat1991] (1991), I §1.2, pp. 9–10; [Range][Range1986] (1986), Chapter I, +E.1.10 and E.5.5. Hartogs series are treated separately in `HartogsSeries`. + +## Main definitions + +* `hartogsFiber`: The complex fiber of a set over a specified base point. +* `hartogsBase`: The base consists of the points with nonempty fiber. +* `IsHartogs`: Hartogs symmetry is invariance under rotations of the fiber coordinate about zero. +* `IsCompleteHartogs`: Complete Hartogs sets also contain every smaller fiber modulus, including + zero. +* `HasPreconnectedFibers`: Each fiber is preconnected. + +## Main results + +* `IsCompleteHartogs.isHartogs`: Complete Hartogs sets have Hartogs symmetry. +* `IsCompleteHartogs.hasPreconnectedFibers`: Complete Hartogs sets have preconnected fibers; empty + fibers need no exception. +* `hasPreconnectedFibers_iff`: Preconnected fibers are equivalently connected fibers at every point + of the base. +* `IsReinhardt.isHartogs_option`: Selecting the `none` coordinate in a Reinhardt set gives Hartogs + symmetry. +* `IsCompleteReinhardt.isCompleteHartogs_option`: Selecting the `none` coordinate in a complete + Reinhardt set gives complete Hartogs. +* `isOpen_hartogsBase`: The base of an open set in a product is open. +* `isPreconnected_hartogsBase`: The base of a preconnected set is preconnected. + +## References + +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [B. V. Shabat, *Introduction to Complex Analysis, Part II: Functions of Several + Variables*][Shabat1991] +-/ + +public section + +open Set + +namespace SeveralComplexVariables + +variable {E E' : Type*} {U V : Set (E × ℂ)} + +/-- The complex fiber of a set over a specified base point. -/ +@[expose] def hartogsFiber (U : Set (E × ℂ)) (z : E) : Set ℂ := + {w | (z, w) ∈ U} + +/-- The base consists of the points with nonempty fiber. -/ +@[expose] def hartogsBase (U : Set (E × ℂ)) : Set E := Prod.fst '' U + +/-- Hartogs symmetry is invariance under rotations of the fiber coordinate about zero. -/ +@[expose] def IsHartogs (U : Set (E × ℂ)) : Prop := + ∀ ⦃z w⦄, (z, w) ∈ U → ∀ ⦃v⦄, ‖v‖ = ‖w‖ → (z, v) ∈ U + +/-- Complete Hartogs sets also contain every smaller fiber modulus, including zero. -/ +@[expose] def IsCompleteHartogs (U : Set (E × ℂ)) : Prop := + ∀ ⦃z w⦄, (z, w) ∈ U → ∀ ⦃v⦄, ‖v‖ ≤ ‖w‖ → (z, v) ∈ U + +/-- Each fiber is preconnected. Equivalently, every nonempty fiber is connected. This does not +require Hartogs symmetry, openness, or connectedness of the total set. -/ +@[expose] def HasPreconnectedFibers (U : Set (E × ℂ)) : Prop := + ∀ z, IsPreconnected (hartogsFiber U z) + +/-- Membership in the base is equivalent to nonemptiness of the fiber. -/ +theorem mem_hartogsBase_iff {z : E} : z ∈ hartogsBase U ↔ (hartogsFiber U z).Nonempty := by + constructor + · rintro ⟨⟨x, w⟩, hw, rfl⟩ + exact ⟨w, hw⟩ + · rintro ⟨w, hw⟩ + exact ⟨(z, w), hw, rfl⟩ + +/-- The empty set has Hartogs symmetry. -/ +@[simp] theorem isHartogs_empty : IsHartogs (∅ : Set (E × ℂ)) := + fun _ _ h => h.elim + +/-- The whole product has Hartogs symmetry. -/ +@[simp] theorem isHartogs_univ : IsHartogs (univ : Set (E × ℂ)) := + fun _ _ _ _ _ => mem_univ _ + +/-- The empty set is complete Hartogs. -/ +@[simp] theorem isCompleteHartogs_empty : IsCompleteHartogs (∅ : Set (E × ℂ)) := + fun _ _ h => h.elim + +/-- The whole product is complete Hartogs. -/ +@[simp] theorem isCompleteHartogs_univ : IsCompleteHartogs (univ : Set (E × ℂ)) := + fun _ _ _ _ _ => mem_univ _ + +/-- Complete Hartogs sets have Hartogs symmetry. -/ +theorem IsCompleteHartogs.isHartogs (hU : IsCompleteHartogs U) : IsHartogs U := + fun _ _ hw _ hv => hU hw hv.le + +/-- Intersections preserve Hartogs symmetry. -/ +theorem IsHartogs.inter (hU : IsHartogs U) (hV : IsHartogs V) : IsHartogs (U ∩ V) := + fun _ _ hw _ hv => ⟨hU hw.1 hv, hV hw.2 hv⟩ + +/-- Unions preserve Hartogs symmetry, without requiring connected fibers. -/ +theorem IsHartogs.union (hU : IsHartogs U) (hV : IsHartogs V) : IsHartogs (U ∪ V) := + fun _ _ hw _ hv => hw.elim (fun h => Or.inl (hU h hv)) (fun h => Or.inr (hV h hv)) + +/-- Intersections preserve the complete Hartogs property. -/ +theorem IsCompleteHartogs.inter (hU : IsCompleteHartogs U) (hV : IsCompleteHartogs V) : + IsCompleteHartogs (U ∩ V) := + fun _ _ hw _ hv => ⟨hU hw.1 hv, hV hw.2 hv⟩ + +/-- Unions preserve the complete Hartogs property. -/ +theorem IsCompleteHartogs.union (hU : IsCompleteHartogs U) (hV : IsCompleteHartogs V) : + IsCompleteHartogs (U ∪ V) := + fun _ _ hw _ hv => hw.elim (fun h => Or.inl (hU h hv)) (fun h => Or.inr (hV h hv)) + +/-- Any change of base preserves Hartogs symmetry. -/ +theorem IsHartogs.preimage_base (hU : IsHartogs U) (g : E' → E) : + IsHartogs {p : E' × ℂ | (g p.1, p.2) ∈ U} := + fun _ _ hw _ hv => hU hw hv + +/-- Any change of base preserves the complete Hartogs property. -/ +theorem IsCompleteHartogs.preimage_base (hU : IsCompleteHartogs U) (g : E' → E) : + IsCompleteHartogs {p : E' × ℂ | (g p.1, p.2) ∈ U} := + fun _ _ hw _ hv => hU hw hv + +/-- Multiplication of a fiber coordinate by a unit-modulus scalar preserves membership. -/ +theorem IsHartogs.mul_mem (hU : IsHartogs U) {z : E} {w a : ℂ} + (hw : (z, w) ∈ U) (ha : ‖a‖ = 1) : (z, a * w) ∈ U := + hU hw (by simp [ha]) + +/-- Multiplication of a fiber coordinate by a complex contraction preserves membership. -/ +theorem IsCompleteHartogs.mul_mem (hU : IsCompleteHartogs U) {z : E} {w a : ℂ} + (hw : (z, w) ∈ U) (ha : ‖a‖ ≤ 1) : (z, a * w) ∈ U := by + apply hU hw + rw [norm_mul] + exact mul_le_of_le_one_left (norm_nonneg _) ha + +/-- Every nonempty fiber of a complete Hartogs set contains zero. -/ +theorem IsCompleteHartogs.zero_mem_fiber (hU : IsCompleteHartogs U) {z : E} + (hz : z ∈ hartogsBase U) : (z, 0) ∈ U := by + obtain ⟨w, hw⟩ := mem_hartogsBase_iff.mp hz + exact hU hw (by simp) + +/-- The base of a complete Hartogs set equals its zero section. -/ +theorem IsCompleteHartogs.mem_base_iff (hU : IsCompleteHartogs U) {z : E} : + z ∈ hartogsBase U ↔ (z, 0) ∈ U := + ⟨hU.zero_mem_fiber, fun hz => mem_hartogsBase_iff.mpr ⟨0, hz⟩⟩ + +/-- Fibers of a complete Hartogs set are star-convex about zero, including empty fibers. -/ +theorem IsCompleteHartogs.starConvex_fiber (hU : IsCompleteHartogs U) (z : E) : + StarConvex ℝ 0 (hartogsFiber U z) := by + intro w hw a b ha hb hab + simp only [smul_zero, zero_add] + apply hU hw + rw [norm_smul, Real.norm_eq_abs, abs_of_nonneg hb] + exact mul_le_of_le_one_left (norm_nonneg _) (by linarith) + +/-- Nonempty fibers of complete Hartogs sets are path connected. -/ +theorem IsCompleteHartogs.isPathConnected_fiber (hU : IsCompleteHartogs U) {z : E} + (hz : z ∈ hartogsBase U) : IsPathConnected (hartogsFiber U z) := + (hU.starConvex_fiber z).isPathConnected (hU.zero_mem_fiber hz) + +/-- Complete Hartogs sets have preconnected fibers; empty fibers need no exception. -/ +theorem IsCompleteHartogs.hasPreconnectedFibers (hU : IsCompleteHartogs U) : + HasPreconnectedFibers U := by + intro z + rcases (hartogsFiber U z).eq_empty_or_nonempty with h | h + · rw [h] + exact isPreconnected_empty + · exact (hU.isPathConnected_fiber (mem_hartogsBase_iff.mpr h)).isConnected.isPreconnected + +/-- Fiber preconnectedness gives connectedness at every point of the projected base. -/ +theorem HasPreconnectedFibers.isConnected_fiber (hU : HasPreconnectedFibers U) {z : E} + (hz : z ∈ hartogsBase U) : IsConnected (hartogsFiber U z) := + ⟨mem_hartogsBase_iff.mp hz, hU z⟩ + +/-- Preconnected fibers are equivalently connected fibers at every point of the base. -/ +theorem hasPreconnectedFibers_iff : HasPreconnectedFibers U ↔ + ∀ z ∈ hartogsBase U, IsConnected (hartogsFiber U z) := by + constructor + · exact fun h _ hz => h.isConnected_fiber hz + · intro h z + rcases (hartogsFiber U z).eq_empty_or_nonempty with hz | hz + · rw [hz] + exact isPreconnected_empty + · exact (h z (mem_hartogsBase_iff.mpr hz)).isPreconnected + +/-- Products with centered discs are complete Hartogs, with no condition on the base. -/ +theorem isCompleteHartogs_prod_ball (B : Set E) (r : ℝ) : + IsCompleteHartogs (B ×ˢ Metric.ball (0 : ℂ) r) := by + intro z w hw v hv + refine ⟨hw.1, ?_⟩ + simpa only [Metric.mem_ball, dist_zero_right] using + hv.trans_lt (by simpa only [Metric.mem_ball, dist_zero_right] using hw.2) + +/-- Products with centered annuli have Hartogs symmetry, including degenerate annuli. -/ +theorem isHartogs_prod_annulus (B : Set E) (r R : ℝ) : + IsHartogs (B ×ˢ {w : ℂ | r < ‖w‖ ∧ ‖w‖ < R}) := by + intro z w hw v hv + exact ⟨hw.1, by simpa only [mem_ofPred_eq, hv] using hw.2⟩ + +/-- Selecting the `none` coordinate in a Reinhardt set gives Hartogs symmetry. -/ +theorem IsReinhardt.isHartogs_option {ι : Type*} {S : Set (Option ι → ℂ)} + (hS : IsReinhardt S) : + IsHartogs {p : (ι → ℂ) × ℂ | (fun i => i.elim p.2 p.1) ∈ S} := by + intro z w hw v hv + apply hS hw + intro i + cases i with + | none => exact hv + | some i => rfl + +/-- Selecting the `none` coordinate in a complete Reinhardt set gives complete Hartogs. -/ +theorem IsCompleteReinhardt.isCompleteHartogs_option {ι : Type*} + {S : Set (Option ι → ℂ)} (hS : IsCompleteReinhardt S) : + IsCompleteHartogs {p : (ι → ℂ) × ℂ | (fun i => i.elim p.2 p.1) ∈ S} := by + intro z w hw v hv + apply hS hw + intro i + cases i with + | none => exact hv + | some i => exact le_rfl + +section Topology + +variable [TopologicalSpace E] + +/-- The base of an open set in a product is open. -/ +theorem isOpen_hartogsBase (hU : IsOpen U) : IsOpen (hartogsBase U) := + isOpenMap_fst U hU + +/-- Fibers of an open set in a product are open. -/ +theorem isOpen_hartogsFiber (hU : IsOpen U) (z : E) : IsOpen (hartogsFiber U z) := + hU.preimage (continuous_const.prodMk continuous_id) + +/-- The base of a preconnected set is preconnected. -/ +theorem isPreconnected_hartogsBase (hU : IsPreconnected U) : + IsPreconnected (hartogsBase U) := + hU.image _ continuous_fst.continuousOn + +end Topology + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean new file mode 100644 index 0000000000..da43984173 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean @@ -0,0 +1,189 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Module.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain + +/-! +# Hartogs extension + +This file develops the geometry of a standard Hartogs figure and uniqueness of its analytic +extensions. Extension from the figure follows from Hartogs continuation over a connected base. +Extension across general compact holes is deduced from the product-space theorem of +`CompactHole`, proved by Ehrenpreis' method, by a choice of linear coordinates. Separate +analyticity is treated in `SeparateAnalytic`. + +References: [Boas][Boas2013] (2013), Section 2.7; [Scheidemann][Scheidemann2005] (2005), +Exercise 2.1.7 and Section 2.3; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Corollary +2.1.2. + +All extension targets are subsets of finite-dimensional complex normed spaces. Coordinate balls +use the supremum norm, so the figure is built from polydiscs. Extension means agreement on the +old domain; functions outside the new domain are unrestricted. + +## Main definitions + +* `hartogsFigure`: A standard Hartogs figure: a thin full cylinder together with an outer annular + cylinder in the last coordinate. + +## Main results + +* `exists_analyticOnNhd_extension_hartogsFigure`: **Extension from a Hartogs figure.** A + Banach-valued holomorphic function on the figure extends to its full unit polydisc, by Hartogs + continuation in the last coordinate. +* `exists_analyticOnNhd_extension_of_isCompact`: **Hartogs' compact-hole extension theorem.** In + complex dimension at least two, a holomorphic function extends across a compact subset if its + complement in the domain is connected. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +section Figure + +variable {ι : Type*} [Fintype ι] + +/-- A standard Hartogs figure: a thin full cylinder together with an outer annular cylinder in the +last coordinate. The intended parameters satisfy `0 < r < 1` and `0 < s < 1`. -/ +@[expose] def hartogsFigure (r s : ℝ) : Set ((ι → ℂ) × ℂ) := + (ball 0 r ×ˢ ball 0 1) ∪ (ball 0 1 ×ˢ (ball 0 1 \ closedBall 0 s)) + +/-- The standard Hartogs figure has rotational symmetry in its fiber coordinate, including for +degenerate parameters and an empty base coordinate type. -/ +theorem isHartogs_hartogsFigure (r s : ℝ) : IsHartogs (hartogsFigure (ι := ι) r s) := by + unfold hartogsFigure + apply (isCompleteHartogs_prod_ball _ _).isHartogs.union + intro z w hw v hv + refine ⟨hw.1, ?_⟩ + simpa only [mem_sdiff, mem_ball, mem_closedBall, dist_zero_right, hv] using hw.2 + +/-- The standard Hartogs figure is open, even for an empty coordinate index type. -/ +theorem isOpen_hartogsFigure (r s : ℝ) : IsOpen (hartogsFigure (ι := ι) r s) := + (isOpen_ball.prod isOpen_ball).union + (isOpen_ball.prod (isOpen_ball.sdiff isClosed_closedBall)) + +/-- The Hartogs figure lies in the full unit polydisc when its inner base radius is at most one. -/ +theorem hartogsFigure_subset {r : ℝ} (hr : r ≤ 1) (s : ℝ) : + hartogsFigure (ι := ι) r s ⊆ ball 0 1 ×ˢ ball 0 1 := by + rintro z (hz | hz) + · exact ⟨ball_subset_ball hr hz.1, hz.2⟩ + · exact ⟨hz.1, hz.2.1⟩ + +/-- A positive inner base radius makes the Hartogs figure contain the origin. -/ +theorem zero_mem_hartogsFigure {r : ℝ} (hr : 0 < r) (s : ℝ) : + (0 : (ι → ℂ) × ℂ) ∈ hartogsFigure r s := + Or.inl ⟨mem_ball_self hr, mem_ball_self zero_lt_one⟩ + +/-- With no base coordinates, a positive-radius Hartogs figure is already the full disk. Thus the +figure-extension statement needs no positive-dimensional base assumption. -/ +theorem hartogsFigure_eq_of_isEmpty [IsEmpty ι] {r : ℝ} (hr : 0 < r) (s : ℝ) : + hartogsFigure (ι := ι) r s = ball 0 1 ×ˢ ball 0 1 := by + ext z + simp [hartogsFigure, Subsingleton.elim z.1 (0 : ι → ℂ), hr] + exact fun h _ => h + +omit [CompleteSpace F] in +/-- Two analytic extensions from a Hartogs figure agree throughout the full unit polydisc. This +uniqueness theorem is proved independently of the extension-existence theorem. -/ +theorem eqOn_of_eqOn_hartogsFigure {r : ℝ} (hr : 0 < r) (s : ℝ) + {f g : ((ι → ℂ) × ℂ) → F} + (hf : AnalyticOnNhd ℂ f (ball 0 1 ×ˢ ball 0 1)) + (hg : AnalyticOnNhd ℂ g (ball 0 1 ×ˢ ball 0 1)) + (heq : EqOn f g (hartogsFigure r s)) : EqOn f g (ball 0 1 ×ˢ ball 0 1) := by + apply hf.eqOn_of_preconnected_of_eventuallyEq hg + (isPreconnected_ball.prod isPreconnected_ball) + (show (0 : (ι → ℂ) × ℂ) ∈ ball 0 1 ×ˢ ball 0 1 from + ⟨mem_ball_self zero_lt_one, mem_ball_self zero_lt_one⟩) + exact Filter.mem_of_superset + ((isOpen_hartogsFigure r s).mem_nhds (zero_mem_hartogsFigure hr s)) heq + +/-- **Extension from a Hartogs figure.** A Banach-valued holomorphic function on the figure +extends to its full unit polydisc, by Hartogs continuation in the last coordinate. -/ +theorem exists_analyticOnNhd_extension_hartogsFigure + {r s : ℝ} (hr : 0 < r) (hr1 : r < 1) (hs : 0 < s) (hs1 : s < 1) + {f : ((ι → ℂ) × ℂ) → F} (hf : AnalyticOnNhd ℂ f (hartogsFigure r s)) : + ∃ g : ((ι → ℂ) × ℂ) → F, + AnalyticOnNhd ℂ g (ball 0 1 ×ˢ ball 0 1) ∧ EqOn g f (hartogsFigure r s) := by + obtain ⟨g, hg, he⟩ := exists_extension_hartogsCylinder + (D := ball (0 : ι → ℂ) 1) (D₀ := ball 0 r) isOpen_ball isPreconnected_ball + isOpen_ball ⟨0, mem_ball_self hr⟩ (ball_subset_ball hr1.le) hs.le hs1 + (by simpa only [hartogsCylinder, hartogsFigure, union_comm] using hf) + exact ⟨g, hg, by simpa only [hartogsCylinder, hartogsFigure, union_comm] using he⟩ + +end Figure + +/-- **Hartogs' compact-hole extension theorem.** In complex dimension at least two, a +holomorphic function extends across a compact subset if its complement in the domain is +connected. No boundedness of the function near the hole is required, and the domain itself +need not be connected. + +The dimension and connected-complement hypotheses are essential. The open domain itself need not +be bounded, and an empty domain or empty compact set is allowed. -/ +theorem exists_analyticOnNhd_extension_of_isCompact + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + (hdim : 2 ≤ Module.finrank ℂ E) {U K : Set E} + (hU : IsOpen U) (hK : IsCompact K) (hKU : K ⊆ U) + (hcompl : IsPreconnected (U \ K)) {f : E → F} + (hf : AnalyticOnNhd ℂ f (U \ K)) : + ∃ g : E → F, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ K) := by + obtain ⟨k, hk⟩ : ∃ k, Module.finrank ℂ E = k + 2 := ⟨Module.finrank ℂ E - 2, by omega⟩ + let b := Module.finBasisOfFinrankEq ℂ E hk + let e₂ : (Fin (k + 2) → ℂ) ≃L[ℂ] ℂ × (Fin (k + 1) → ℂ) := + (Fin.consLinearEquiv ℂ (fun _ : Fin (k + 1).succ => ℂ)).symm.toContinuousLinearEquiv + let e : E ≃L[ℂ] ℂ × (Fin (k + 1) → ℂ) := b.equivFunL.trans e₂ + set D' : Set (ℂ × (Fin (k + 1) → ℂ)) := e.symm ⁻¹' U with hD' + set K' : Set (ℂ × (Fin (k + 1) → ℂ)) := e.symm ⁻¹' K with hK' + have himg : ∀ s : Set E, e.symm ⁻¹' s = e '' s := fun s => by + ext w + constructor + · intro hw + exact ⟨e.symm w, hw, e.apply_symm_apply w⟩ + · rintro ⟨z, hz, rfl⟩ + simpa using hz + have hD'o : IsOpen D' := hU.preimage e.symm.continuous + have hK'c : IsCompact K' := by + rw [hK', himg] + exact hK.image e.continuous + have hK'D' : K' ⊆ D' := fun w hw => hKU hw + have hconn' : IsPreconnected (D' \ K') := by + have : D' \ K' = e '' (U \ K) := by rw [← himg]; rfl + rw [this] + exact hcompl.image e e.continuous.continuousOn + have hf' : AnalyticOnNhd ℂ (f ∘ e.symm) (D' \ K') := + hf.comp (e.symm.toContinuousLinearMap.analyticOnNhd _) fun w hw => hw + obtain ⟨g', hg', hg'f⟩ := + exists_analyticOnNhd_extension_of_isCompact_prod hD'o hK'c hK'D' hconn' hf' + refine ⟨g' ∘ e, hg'.comp (e.toContinuousLinearMap.analyticOnNhd _) fun z hz => ?_, ?_⟩ + · show e.symm (e z) ∈ U + simpa using hz + · intro z hz + have hz' : e z ∈ D' \ K' := by + refine ⟨?_, ?_⟩ <;> simp only [hD', hK', mem_preimage, e.symm_apply_apply] + · exact hz.1 + · exact hz.2 + have := hg'f hz' + simpa using this + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsLaurent.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsLaurent.lean new file mode 100644 index 0000000000..d57c7a29a8 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsLaurent.lean @@ -0,0 +1,212 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Algebra.InfiniteSum.NatInt +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Local estimates for Hartogs–Laurent series + +Compact circles inside a Hartogs set give uniform bounds for nearby fibers. Two such circles +bound the positive and negative Laurent terms by geometric series. At the zero section the +negative coefficients vanish. These estimates upgrade a pointwise fiber expansion to locally +uniform convergence. + +## Main results + +`IsHartogs.exists_circle_bound` is a uniform bound on nearby fibers from a compact circle in a +Hartogs set. `hasSumLocallyUniformlyOn_hartogsLaurent` upgrades a pointwise fiber expansion to +locally uniform convergence on the Hartogs set. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {U : Set (E × ℂ)} + +omit [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- Each fiber point of an open Hartogs set has a larger positive radius in the same fiber. -/ +theorem IsHartogs.exists_larger_radius (hH : IsHartogs U) (hU : IsOpen U) + {p : E × ℂ} (hp : p ∈ U) : ∃ R : ℝ, ‖p.2‖ < R ∧ (p.1, (R : ℂ)) ∈ U := by + have hreal : (p.1, (‖p.2‖ : ℂ)) ∈ U := hH hp (by simp) + obtain ⟨ε, hε, hball⟩ := Metric.isOpen_iff.mp hU _ hreal + refine ⟨‖p.2‖ + ε / 2, by linarith, hball ?_⟩ + rw [mem_ball, Prod.dist_eq, max_lt_iff] + refine ⟨by simpa using hε, ?_⟩ + rw [dist_eq_norm, ← Complex.ofReal_sub, Complex.norm_real] + simp only [Real.norm_eq_abs, add_sub_cancel_left, abs_of_pos (half_pos hε)] + exact half_lt_self hε + +omit [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- A nonzero fiber point has a smaller positive radius in the same open Hartogs fiber. -/ +theorem IsHartogs.exists_smaller_radius (hH : IsHartogs U) (hU : IsOpen U) + {p : E × ℂ} (hp : p ∈ U) (hp0 : p.2 ≠ 0) : + ∃ r : ℝ, 0 < r ∧ r < ‖p.2‖ ∧ (p.1, (r : ℂ)) ∈ U := by + have hreal : (p.1, (‖p.2‖ : ℂ)) ∈ U := hH hp (by simp) + obtain ⟨ε, hε, hball⟩ := Metric.isOpen_iff.mp hU _ hreal + let t := min ε ‖p.2‖ / 2 + have ht : 0 < t := half_pos (lt_min hε (norm_pos_iff.mpr hp0)) + have htε : t < ε := (half_lt_self (lt_min hε (norm_pos_iff.mpr hp0))).trans_le (min_le_left _ _) + have htn : t < ‖p.2‖ := + (half_lt_self (lt_min hε (norm_pos_iff.mpr hp0))).trans_le (min_le_right _ _) + refine ⟨‖p.2‖ - t, sub_pos.mpr htn, by linarith, hball ?_⟩ + rw [mem_ball, Prod.dist_eq, max_lt_iff] + refine ⟨by simpa using hε, ?_⟩ + rw [dist_eq_norm, ← Complex.ofReal_sub, Complex.norm_real] + simpa only [Real.norm_eq_abs, sub_sub_cancel_left, abs_neg, abs_of_pos ht] using htε + +omit [NormedSpace ℂ F] [CompleteSpace F] in +/-- A compact fiber circle has a common bound for the function on all nearby fibers. -/ +theorem IsHartogs.exists_circle_bound (hH : IsHartogs U) (hU : IsOpen U) + {f : E × ℂ → F} (hf : ContinuousOn f U) {z : E} {r : ℝ} (hr : 0 < r) + (hz : (z, (r : ℂ)) ∈ U) : + ∃ δ M : ℝ, 0 < δ ∧ 0 ≤ M ∧ ∀ y ∈ ball z δ, ∀ w ∈ sphere (0 : ℂ) r, + (y, w) ∈ U ∧ ‖f (y, w)‖ ≤ M := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + have hnear : ∀ᶠ y in 𝓝 z, ∀ w ∈ sphere (0 : ℂ) r, (y, w) ∈ U := by + apply (isCompact_sphere (0 : ℂ) r).eventually_forall_of_forall_eventually + intro w hw + exact hU.eventually_mem (hH hz (by + rw [mem_sphere_zero_iff_norm.mp hw, Complex.norm_of_nonneg hr.le])) + obtain ⟨δ, hδ, hδsub⟩ := nhds_basis_closedBall.mem_iff.mp hnear + let K := closedBall z δ ×ˢ sphere (0 : ℂ) r + have hKU : K ⊆ U := fun p hp => hδsub hp.1 p.2 hp.2 + obtain ⟨M, hM⟩ := ((isCompact_closedBall z δ).prod (isCompact_sphere (0 : ℂ) r)).bddAbove_image + (hf.mono hKU).norm + exact ⟨δ, max M 0, hδ, le_max_right _ _, fun y hy w hw => + ⟨hδsub (ball_subset_closedBall hy) w hw, + (hM (mem_image_of_mem _ ⟨ball_subset_closedBall hy, hw⟩)).trans (le_max_left _ _)⟩⟩ + +omit [NormedSpace ℂ F] in +/-- Two geometric majorants, one for each half of the integers, give uniform convergence. -/ +private theorem hasSumUniformlyOn_of_geometric_int_bounds {X : Type*} {N : Set X} + {u : ℤ → X → F} {f : X → F} {M₁ M₂ q₁ q₂ : ℝ} + (hq₁ : 0 ≤ q₁) (hq₁1 : q₁ < 1) (hq₂ : 0 ≤ q₂) (hq₂1 : q₂ < 1) + (hsum : ∀ x ∈ N, HasSum (fun k => u k x) (f x)) + (hpos : ∀ n : ℕ, ∀ x ∈ N, ‖u n x‖ ≤ M₁ * q₁ ^ n) + (hneg : ∀ n : ℕ, ∀ x ∈ N, ‖u (Int.negSucc n) x‖ ≤ M₂ * q₂ ^ (n + 1)) : + HasSumUniformlyOn u f N := by + have hs₁ := (summable_geometric_of_lt_one hq₁ hq₁1).mul_left M₁ + have hs₂ : Summable (fun n : ℕ => M₂ * q₂ ^ (n + 1)) := by + simpa only [pow_succ, mul_assoc] using + ((summable_geometric_of_lt_one hq₂ hq₂1).mul_left M₂).mul_right q₂ + have hbound (k : ℤ) (x : X) (hx : x ∈ N) : + ‖u k x‖ ≤ Int.rec (fun n => M₁ * q₁ ^ n) (fun n => M₂ * q₂ ^ (n + 1)) k := by + cases k with + | ofNat n => exact hpos n x hx + | negSucc n => exact hneg n x hx + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + exact (tendstoUniformlyOn_tsum (hs₁.int_rec hs₂) hbound).congr_right + (fun x hx => (hsum x hx).tsum_eq) + +variable {f : E × ℂ → F} {a : ℤ → E → F} + +/-- Near the zero section the positive terms have a common geometric bound and all negative terms +vanish. -/ +private theorem exists_uniform_laurent_neighborhood_zero (hH : IsHartogs U) (hU : IsOpen U) + (hf : ContinuousOn f U) + (hcoeff : ∀ (z : E) (r : ℝ), 0 < r → (z, (r : ℂ)) ∈ U → + ∀ k, a k z = circleLaurentCoeff (fun w => f (z, w)) r k) + (hzero : ∀ z, (z, 0) ∈ U → ∀ k : ℤ, k < 0 → a k z = 0) + (hsum : ∀ p ∈ U, HasSum (fun k : ℤ => p.2 ^ k • a k p.1) (f p)) + {z : E} (hz : (z, (0 : ℂ)) ∈ U) : + ∃ N ∈ 𝓝[U] (z, (0 : ℂ)), HasSumUniformlyOn (fun k p => p.2 ^ k • a k p.1) f N := by + obtain ⟨R, hR', hzR⟩ := hH.exists_larger_radius hU hz + have hR : 0 < R := by simpa using hR' + obtain ⟨δ, M, hδ, _, hcircle⟩ := hH.exists_circle_bound hU hf hR hzR + have hsection : Continuous (fun y : E => (y, (0 : ℂ))) := + continuous_id.prodMk continuous_const + obtain ⟨ε, hε, hεsub⟩ := Metric.mem_nhds_iff.mp ((hU.preimage hsection).mem_nhds hz) + let N := (ball z (min δ ε) ×ˢ ball (0 : ℂ) (R / 2)) ∩ U + have hN : N ∈ 𝓝[U] (z, (0 : ℂ)) := mem_nhdsWithin_of_mem_nhds + (((isOpen_ball.prod isOpen_ball).inter hU).mem_nhds + ⟨⟨mem_ball_self (lt_min hδ hε), mem_ball_self (half_pos hR)⟩, hz⟩) + refine ⟨N, hN, ?_⟩ + apply hasSumUniformlyOn_of_geometric_int_bounds + (M₁ := M) (q₁ := (R / 2) / R) (M₂ := 0) (q₂ := 0) + (by positivity) ((div_lt_one hR).mpr (half_lt_self hR)) le_rfl zero_lt_one + (fun p hp => hsum p hp.2) + · intro n p hp + have hc := hcircle p.1 ((ball_subset_ball (min_le_left δ ε)) hp.1.1) + have hpr : (p.1, (R : ℂ)) ∈ U := (hc (R : ℂ) (by simp [hR.le])).1 + rw [hcoeff p.1 R hR hpr] + exact norm_circleLaurentTerm_nat_le hR (fun w hw => (hc w hw).2) + (mem_ball_zero_iff.mp hp.1.2).le n + · intro n p hp + have hp0 := hεsub ((ball_subset_ball (min_le_right δ ε)) hp.1.1) + simp [hzero p.1 hp0 (Int.negSucc n) (by omega)] + +/-- Away from zero, circles on either side of the fiber modulus give geometric majorants for both +halves of the Laurent series. -/ +private theorem exists_uniform_laurent_neighborhood_ne_zero (hH : IsHartogs U) (hU : IsOpen U) + (hf : ContinuousOn f U) + (hcoeff : ∀ (z : E) (r : ℝ), 0 < r → (z, (r : ℂ)) ∈ U → + ∀ k, a k z = circleLaurentCoeff (fun w => f (z, w)) r k) + (hsum : ∀ p ∈ U, HasSum (fun k : ℤ => p.2 ^ k • a k p.1) (f p)) + {p : E × ℂ} (hp : p ∈ U) (hp0 : p.2 ≠ 0) : + ∃ N ∈ 𝓝[U] p, HasSumUniformlyOn (fun k q => q.2 ^ k • a k q.1) f N := by + obtain ⟨R, hpR, hzR⟩ := hH.exists_larger_radius hU hp + obtain ⟨r, hr, hrp, hzr⟩ := hH.exists_smaller_radius hU hp hp0 + have hR : 0 < R := (norm_nonneg _).trans_lt hpR + obtain ⟨δ₁, M₁, hδ₁, _, hc₁⟩ := hH.exists_circle_bound hU hf hR hzR + obtain ⟨δ₂, M₂, hδ₂, _, hc₂⟩ := hH.exists_circle_bound hU hf hr hzr + let t := (r + ‖p.2‖) / 2 + let T := (‖p.2‖ + R) / 2 + have ht : 0 < t := by dsimp [t]; positivity + have hrt : r < t := by dsimp [t]; linarith + have htp : t < ‖p.2‖ := by dsimp [t]; linarith + have hpT : ‖p.2‖ < T := by dsimp [T]; linarith + have hTR : T < R := by dsimp [T]; linarith + let V : Set ℂ := {w | t < ‖w‖ ∧ ‖w‖ < T} + have hV : IsOpen V := + (isOpen_lt continuous_const continuous_norm).inter (isOpen_lt continuous_norm continuous_const) + let N := (ball p.1 (min δ₁ δ₂) ×ˢ V) ∩ U + refine ⟨N, mem_nhdsWithin_of_mem_nhds + (((isOpen_ball.prod hV).inter hU).mem_nhds + ⟨⟨mem_ball_self (lt_min hδ₁ hδ₂), htp, hpT⟩, hp⟩), ?_⟩ + apply hasSumUniformlyOn_of_geometric_int_bounds + (M₁ := M₁) (q₁ := T / R) (M₂ := M₂) (q₂ := r / t) + (by dsimp [T]; positivity) ((div_lt_one hR).mpr hTR) + (by positivity) ((div_lt_one ht).mpr hrt) (fun q hq => hsum q hq.2) + · intro n q hq + have hc := hc₁ q.1 ((ball_subset_ball (min_le_left δ₁ δ₂)) hq.1.1) + have hqR : (q.1, (R : ℂ)) ∈ U := (hc (R : ℂ) (by simp [hR.le])).1 + rw [hcoeff q.1 R hR hqR] + exact norm_circleLaurentTerm_nat_le hR (fun w hw => (hc w hw).2) hq.1.2.2.le n + · intro n q hq + have hc := hc₂ q.1 ((ball_subset_ball (min_le_right δ₁ δ₂)) hq.1.1) + have hqr : (q.1, (r : ℂ)) ∈ U := (hc (r : ℂ) (by simp [hr.le])).1 + rw [hcoeff q.1 r hr hqr] + exact norm_circleLaurentTerm_negSucc_le hr ht (fun w hw => (hc w hw).2) hq.1.2.1.le n + +/-- A pointwise Hartogs–Laurent expansion with circle coefficients converges locally uniformly. This +estimate is independent of Laurent expansion existence. -/ +theorem hasSumLocallyUniformlyOn_hartogsLaurent (hH : IsHartogs U) (hU : IsOpen U) + (hf : ContinuousOn f U) + (hcoeff : ∀ (z : E) (r : ℝ), 0 < r → (z, (r : ℂ)) ∈ U → + ∀ k, a k z = circleLaurentCoeff (fun w => f (z, w)) r k) + (hzero : ∀ z, (z, 0) ∈ U → ∀ k : ℤ, k < 0 → a k z = 0) + (hsum : ∀ p ∈ U, HasSum (fun k : ℤ => p.2 ^ k • a k p.1) (f p)) : + HasSumLocallyUniformlyOn (fun k p => p.2 ^ k • a k p.1) f U := by + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + rintro ⟨z, w⟩ hp + by_cases hp0 : w = 0 + · subst w + exact exists_uniform_laurent_neighborhood_zero hH hU hf hcoeff hzero hsum hp + · exact exists_uniform_laurent_neighborhood_ne_zero hH hU hf hcoeff hsum hp hp0 + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsSeries.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsSeries.lean new file mode 100644 index 0000000000..8b0d67abda --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsSeries.lean @@ -0,0 +1,298 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.IteratedDeriv.Defs +public import Mathlib.Analysis.Complex.Liouville +public import Mathlib.Analysis.Complex.TaylorSeries +public import Mathlib.Topology.Algebra.InfiniteSum.UniformOn +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent + +/-! +# Hartogs–Taylor and Hartogs–Laurent expansions + +Functions take values in a complex Banach space, and the base is a finite-dimensional complex +normed space (possibly zero dimensional). Taylor coefficients are the normalized iterated +derivatives in the fiber variable at zero. On an open complete Hartogs set these coefficients +are holomorphic on the base and the expansion converges locally uniformly. + +The Laurent theorem assumes Hartogs symmetry and, separately, preconnected fibers. Its +coefficients are single-valued holomorphic functions on the projected base. Without the fiber +assumption, coefficients need only be locally functions of the base variable; connectedness of +the total set does not repair that issue. Thus we make explicit the hypothesis needed for the +global-base interpretation of [Range][Range1986]'s Exercise E.1.10. Negative coefficients vanish +on fibers containing zero. Integer powers in Lean are totalized at zero, so this vanishing is +recorded as part of the Laurent statement. + +`HasSumLocallyUniformlyOn` uses finite subsets of the index type, including for the +integer-indexed Laurent series. It gives unconditional pointwise convergence and uniform +convergence on compact subsets. We use `ℤ → E → F`, rather than the algebraic `LaurentSeries`, +whose support must be bounded below and therefore excludes general essential singularities. +Neither theorem needs the base or the total set to be connected or nonempty. The Taylor theorem +is proved by fiber differentiation and uniform Cauchy estimates on local product neighborhoods. +The Laurent theorem uses the one-variable annular Cauchy formula, holomorphic dependence of +circle coefficients, and geometric bounds from `LaurentSeries.OneVariable` and `HartogsLaurent`. +Neither expansion depends on the multivariable Laurent theorem. + +References: [Shabat][Shabat1991] (1991), I §3.8, Theorem 1 and the Hartogs–Laurent expansion, +pp. 34–36; [Range][Range1986] (1986), Chapter I, E.1.9–E.1.10. + +## Main definitions + +* `hartogsTaylorCoeff`: The Taylor coefficient in the distinguished fiber coordinate, centered at + zero. + +## Main results + +* `differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn`: **Hartogs–Taylor expansion.** + Holomorphic functions on open complete Hartogs sets have holomorphic Taylor coefficients on the + base and a locally uniformly convergent fiber expansion. +* `exists_hartogsLaurent_expansion`: **Hartogs–Laurent expansion with connected nonempty fibers.** + The coefficients are holomorphic on the whole projected base, the series converges locally + uniformly, and negative coefficients vanish on every fiber containing zero. + +## References + +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [B. V. Shabat, *Introduction to Complex Analysis, Part II: Functions of Several + Variables*][Shabat1991] +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The Taylor coefficient in the distinguished fiber coordinate, centered at zero. -/ +@[expose] def hartogsTaylorCoeff (f : E × ℂ → F) (k : ℕ) (z : E) : F := + ((k.factorial : ℂ)⁻¹) • iteratedDeriv k (fun w => f (z, w)) 0 + +/-- The constant coefficient is restriction to the zero section. -/ +@[simp] theorem hartogsTaylorCoeff_zero (f : E × ℂ → F) (z : E) : + hartogsTaylorCoeff f 0 z = f (z, 0) := by + simp [hartogsTaylorCoeff] + +variable [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [CompleteSpace F] {U : Set (E × ℂ)} {f : E × ℂ → F} + +omit [FiniteDimensional ℂ E] in +/-- All derivatives in the fiber variable remain jointly analytic on an open set. -/ +theorem analyticOnNhd_iteratedDeriv_fiber (hU : IsOpen U) (hf : AnalyticOnNhd ℂ f U) + (k : ℕ) : AnalyticOnNhd ℂ (fun p : E × ℂ => + iteratedDeriv k (fun w => f (p.1, w)) p.2) U := by + induction k with + | zero => simpa using hf + | succ k ih => + let g : E × ℂ → F := fun p => iteratedDeriv k (fun w => f (p.1, w)) p.2 + intro p hp + have hA : AnalyticAt ℂ (fun q => fderiv ℂ g q (0, 1)) p := by + exact ((ContinuousLinearMap.apply ℂ F (0, 1)).analyticAt _).comp (ih p hp).fderiv + apply hA.congr + filter_upwards [hU.eventually_mem hp] with q hq + have hs : HasDerivAt (fun w : ℂ => (q.1, w)) (0, 1) q.2 := + (hasDerivAt_const q.2 q.1).prodMk (hasDerivAt_id q.2) + have hd := (ih q hq).differentiableAt.hasFDerivAt.comp_hasDerivAt q.2 hs + simpa only [iteratedDeriv_succ, g, Function.comp_def] using hd.deriv.symm + +omit [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- Around each point of an open complete Hartogs set there is a product neighborhood whose closed +fiber disc has strictly larger radius than the given fiber coordinate. -/ +theorem IsCompleteHartogs.exists_product_closedBall (hH : IsCompleteHartogs U) + (hU : IsOpen U) {p : E × ℂ} (hp : p ∈ U) : + ∃ δ R : ℝ, 0 < δ ∧ ‖p.2‖ < R ∧ + ball p.1 δ ×ˢ closedBall (0 : ℂ) R ⊆ U := by + have hq : (p.1, (‖p.2‖ : ℂ)) ∈ U := + hH hp (by simp) + obtain ⟨ε, hε, hball⟩ := Metric.isOpen_iff.mp hU _ hq + refine ⟨ε / 2, ‖p.2‖ + ε / 2, half_pos hε, by linarith, ?_⟩ + rintro ⟨z, w⟩ ⟨hz, hw⟩ + have hR : 0 ≤ ‖p.2‖ + ε / 2 := by positivity + apply hH (hball (show (z, ((‖p.2‖ + ε / 2 : ℝ) : ℂ)) ∈ + ball (p.1, (‖p.2‖ : ℂ)) ε from ?_)) + · simpa only [mem_closedBall, dist_zero_right, Complex.norm_of_nonneg hR] using hw + · rw [mem_ball, Prod.dist_eq, max_lt_iff] + refine ⟨(mem_ball.mp hz).trans (half_lt_self hε), ?_⟩ + rw [dist_eq_norm, ← Complex.ofReal_sub, Complex.norm_real] + simp only [Real.norm_eq_abs, add_sub_cancel_left, abs_of_pos (half_pos hε)] + exact half_lt_self hε + +/-- **Hartogs–Taylor expansion.** Holomorphic functions on open complete Hartogs sets +have holomorphic Taylor coefficients on the base and a locally uniformly convergent +fiber expansion. Local product neighborhoods and Cauchy estimates give a summable +geometric majorant; the one-variable Taylor theorem identifies the sum. -/ +theorem differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn (hU : IsOpen U) + (hH : IsCompleteHartogs U) + (hf : DifferentiableOn ℂ f U) : + (∀ k, DifferentiableOn ℂ (hartogsTaylorCoeff f k) (hartogsBase U)) ∧ + HasSumLocallyUniformlyOn + (fun k (p : E × ℂ) => p.2 ^ k • hartogsTaylorCoeff f k p.1) f U := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + have hA := hf.analyticOnNhd_of_finiteDimensional hU + constructor + · intro k z hz + have ha := (analyticOnNhd_iteratedDeriv_fiber hU hA k) (z, 0) (hH.zero_mem_fiber hz) + have hc : AnalyticAt ℂ (fun z => iteratedDeriv k (fun w => f (z, w)) 0) z := + ha.comp (f := fun z : E => (z, (0 : ℂ))) (analyticAt_id.prod analyticAt_const) + exact (analyticAt_const.smul hc).differentiableAt.differentiableWithinAt + · apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro p hp + obtain ⟨δ, R, hδ, hpR, hsub⟩ := hH.exists_product_closedBall hU hp + have hR : 0 < R := (norm_nonneg _).trans_lt hpR + let r := (‖p.2‖ + R) / 2 + have hr : 0 < r := by dsimp [r]; positivity + have hrR : r < R := by dsimp [r]; linarith + have hpr : ‖p.2‖ < r := by dsimp [r]; linarith + let N := ball p.1 (δ / 2) ×ˢ ball (0 : ℂ) r + let K := closedBall p.1 (δ / 2) ×ˢ closedBall (0 : ℂ) R + have hKU : K ⊆ U := + (Set.prod_mono (closedBall_subset_ball (half_lt_self hδ)) Subset.rfl).trans hsub + have hK : IsCompact K := (isCompact_closedBall _ _).prod (isCompact_closedBall _ _) + obtain ⟨M, hM⟩ := hK.bddAbove_image (hf.continuousOn.mono hKU).norm + let C := max M 0 + have hC : 0 ≤ C := le_max_right _ _ + have hbound : ∀ q ∈ K, ‖f q‖ ≤ C := + fun q hq => (hM (mem_image_of_mem _ hq)).trans (le_max_left _ _) + have hslice (z : E) (hz : z ∈ closedBall p.1 (δ / 2)) : + DifferentiableOn ℂ (fun w => f (z, w)) (closedBall 0 R) := by + apply hf.comp ((differentiable_const z).prodMk differentiable_id).differentiableOn + intro w hw + exact hKU ⟨hz, hw⟩ + have hsum (q : E × ℂ) (hq : q ∈ N) : + HasSum (fun k => q.2 ^ k • hartogsTaylorCoeff f k q.1) (f q) := by + have hs := Complex.hasSum_taylorSeries_on_ball + ((hslice q.1 (ball_subset_closedBall hq.1)).mono ball_subset_closedBall) + ((ball_subset_ball hrR.le) hq.2) + convert hs using 1 + funext k + simp only [sub_zero, hartogsTaylorCoeff] + exact smul_comm _ _ _ + have hterm (k : ℕ) (q : E × ℂ) (hq : q ∈ N) : + ‖q.2 ^ k • hartogsTaylorCoeff f k q.1‖ ≤ C * (r / R) ^ k := by + have hd := Complex.norm_iteratedDeriv_le_of_forall_mem_sphere_norm_le k hR + ((hslice q.1 (ball_subset_closedBall hq.1)).mono + closure_ball_subset_closedBall).diffContOnCl + (fun w hw => hbound (q.1, w) ⟨ball_subset_closedBall hq.1, sphere_subset_closedBall hw⟩) + have hfact : (k.factorial : ℝ) ≠ 0 := by positivity + have hc : ‖hartogsTaylorCoeff f k q.1‖ ≤ C / R ^ k := by + rw [hartogsTaylorCoeff, norm_smul, norm_inv, Complex.norm_natCast] + calc + (k.factorial : ℝ)⁻¹ * ‖iteratedDeriv k (fun w => f (q.1, w)) 0‖ ≤ + (k.factorial : ℝ)⁻¹ * (k.factorial * C / R ^ k) := + mul_le_mul_of_nonneg_left hd (by positivity) + _ = C / R ^ k := by field_simp + rw [norm_smul, norm_pow] + calc + ‖q.2‖ ^ k * ‖hartogsTaylorCoeff f k q.1‖ ≤ r ^ k * (C / R ^ k) := by + gcongr + exact (mem_ball_zero_iff.mp hq.2).le + _ = C * (r / R) ^ k := by simp only [div_eq_mul_inv, mul_pow, inv_pow]; ac_rfl + have hsummable : Summable (fun k : ℕ => C * (r / R) ^ k) := + (summable_geometric_of_lt_one (div_nonneg hr.le hR.le) ((div_lt_one hR).mpr hrR)).mul_left C + refine ⟨N, mem_nhdsWithin_of_mem_nhds ((isOpen_ball.prod isOpen_ball).mem_nhds + ⟨mem_ball_self (half_pos hδ), mem_ball_zero_iff.mpr hpr⟩), ?_⟩ + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + exact (tendstoUniformlyOn_tsum hsummable hterm).congr_right + (fun q hq => (hsum q hq).tsum_eq) + +/-- The Hartogs–Taylor expansion converges locally uniformly on an open complete Hartogs set. -/ +theorem hasSumLocallyUniformlyOn_hartogsTaylor (hU : IsOpen U) (hH : IsCompleteHartogs U) + (hf : DifferentiableOn ℂ f U) : + HasSumLocallyUniformlyOn + (fun k (p : E × ℂ) => p.2 ^ k • hartogsTaylorCoeff f k p.1) f U := + (differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn hU hH hf).2 + +/-- The canonical Hartogs–Taylor coefficients are holomorphic on the projected base. This follows +from the Taylor expansion theorem. -/ +theorem differentiableOn_hartogsTaylorCoeff (hU : IsOpen U) (hH : IsCompleteHartogs U) + (hf : DifferentiableOn ℂ f U) (k : ℕ) : + DifferentiableOn ℂ (hartogsTaylorCoeff f k) (hartogsBase U) := + (differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn hU hH hf).1 k + +/-- The Hartogs–Taylor series sums to the function at every point of the set. This follows from the +Taylor expansion theorem. -/ +theorem hasSum_hartogsTaylor (hU : IsOpen U) (hH : IsCompleteHartogs U) + (hf : DifferentiableOn ℂ f U) {p : E × ℂ} (hp : p ∈ U) : + HasSum (fun k => p.2 ^ k • hartogsTaylorCoeff f k p.1) (f p) := + (differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn hU hH hf).2.hasSum hp + +/-- Hartogs–Taylor sums converge uniformly on each compact subset of the set. This follows from the +Taylor expansion theorem. -/ +theorem tendstoUniformlyOn_hartogsTaylor (hU : IsOpen U) (hH : IsCompleteHartogs U) + (hf : DifferentiableOn ℂ f U) {K : Set (E × ℂ)} (hK : IsCompact K) (hKU : K ⊆ U) : + TendstoUniformlyOn + (fun s : Finset ℕ => fun p : E × ℂ => ∑ k ∈ s, p.2 ^ k • hartogsTaylorCoeff f k p.1) + f Filter.atTop K := + (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK).mp + ((differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn hU hH hf).2.mono hKU) + +/-- **Hartogs–Laurent expansion with connected nonempty fibers.** The coefficients are +holomorphic on the whole projected base, the series converges locally uniformly, and +negative coefficients vanish on every fiber containing zero. The one-variable Laurent +expansion follows from Cauchy’s formula on an annulus; fixed-circle integrals +give local holomorphic coefficients and geometric bounds give local uniform convergence. +The independent fiber hypothesis is essential for this global-base formulation. -/ +theorem exists_hartogsLaurent_expansion (hU : IsOpen U) (hH : IsHartogs U) + (hfib : HasPreconnectedFibers U) (hf : DifferentiableOn ℂ f U) : + ∃ a : ℤ → E → F, + (∀ k, DifferentiableOn ℂ (a k) (hartogsBase U)) ∧ + (∀ z, (z, 0) ∈ U → ∀ k : ℤ, k < 0 → a k z = 0) ∧ + HasSumLocallyUniformlyOn (fun k (p : E × ℂ) => p.2 ^ k • a k p.1) f U := by + classical + have hA := hf.analyticOnNhd_of_finiteDimensional hU + have hrad : ∀ z : E, ∃ r : ℝ, 0 < r ∧ (z ∈ hartogsBase U → (z, (r : ℂ)) ∈ U) := by + intro z + by_cases hz : z ∈ hartogsBase U + · obtain ⟨w, hw⟩ := mem_hartogsBase_iff.mp hz + obtain ⟨r, hwr, hrU⟩ := hH.exists_larger_radius hU hw + exact ⟨r, (norm_nonneg _).trans_lt hwr, fun _ => hrU⟩ + · exact ⟨1, zero_lt_one, fun h => (hz h).elim⟩ + choose R hR hRU using hrad + let a : ℤ → E → F := fun k z => circleLaurentCoeff (fun w => f (z, w)) (R z) k + have hLaurent (z : E) (hz : z ∈ hartogsBase U) := circleLaurent_expansion + (isOpen_hartogsFiber hU z) ⟨mem_hartogsBase_iff.mp hz, hfib z⟩ + (fun w hw v hv => hH hw hv) + (fun w hw => (hA (z, w) hw).comp (analyticAt_const.prod analyticAt_id)) + (hR z) (hRU z hz) + have hcoeff (z : E) (r : ℝ) (hr : 0 < r) (hzr : (z, (r : ℂ)) ∈ U) (k : ℤ) : + a k z = circleLaurentCoeff (fun w => f (z, w)) r k := by + exact (congrFun ((hLaurent z ⟨(z, (r : ℂ)), hzr, rfl⟩).2.1 r hr hzr) k).symm + have hzero (z : E) (hz : (z, 0) ∈ U) (k : ℤ) (hk : k < 0) : a k z = 0 := + (hLaurent z ⟨(z, 0), hz, rfl⟩).2.2 hz k hk + have hsum (p : E × ℂ) (hp : p ∈ U) : + HasSum (fun k : ℤ => p.2 ^ k • a k p.1) (f p) := + (hLaurent p.1 ⟨p, hp, rfl⟩).1 p.2 hp + refine ⟨a, ?_, hzero, hasSumLocallyUniformlyOn_hartogsLaurent hH hU hf.continuousOn + hcoeff hzero hsum⟩ + intro k z hz + obtain ⟨δ, _, hδ, _, hc⟩ := hH.exists_circle_bound hU hf.continuousOn (hR z) (hRU z hz) + have hcoeffA := analyticOnNhd_circleLaurentCoeff isOpen_ball hA (hR z) + (fun y hy w hw => (hc y hy w hw).1) k + have heq : (fun y => circleLaurentCoeff (fun w => f (y, w)) (R z) k) =ᶠ[𝓝 z] a k := by + filter_upwards [ball_mem_nhds z hδ] with y hy + exact (hcoeff y (R z) (hR z) (hc y hy (R z : ℂ) (by simp [(hR z).le])).1 k).symm + exact ((hcoeffA z (mem_ball_self hδ)).congr heq).differentiableAt.differentiableWithinAt + +/-- A pointwise version of the Hartogs–Laurent expansion, retaining global holomorphic coefficients +and their vanishing at the zero section. -/ +theorem exists_hasSum_hartogsLaurent (hU : IsOpen U) (hH : IsHartogs U) + (hfib : HasPreconnectedFibers U) (hf : DifferentiableOn ℂ f U) : + ∃ a : ℤ → E → F, + (∀ k, DifferentiableOn ℂ (a k) (hartogsBase U)) ∧ + (∀ z, (z, 0) ∈ U → ∀ k : ℤ, k < 0 → a k z = 0) ∧ + ∀ p ∈ U, HasSum (fun k => p.2 ^ k • a k p.1) (f p) := by + obtain ⟨a, ha, hzero, hsum⟩ := exists_hartogsLaurent_expansion hU hH hfib hf + exact ⟨a, ha, hzero, fun _ hp => hsum.hasSum hp⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean new file mode 100644 index 0000000000..f60646268c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/BoundaryDistance.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/BoundaryDistance.lean new file mode 100644 index 0000000000..7821b14c17 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/BoundaryDistance.lean @@ -0,0 +1,129 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.MetricSpace.Thickening +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull + +/-! +# Boundary distance and compactness of holomorphic hulls + +Distance is taken to the complement and valued in `ℝ≥0∞`. In particular, `boundaryEDistance U ∅ += ∞` and `boundaryEDistance univ K = ∞`. On finite complex coordinate spaces the norm is the +supremum norm, so the balls here are equal-radius polydiscs. + +The radius formulation of hull-distance preservation implies holomorphic convexity by relative +closedness, boundedness, and positive distance from the complement. These purely topological +implications do not depend on Cartan–Thullen or Taylor continuation. + +## Main results + +`HasHolomorphicHullRadiusProperty` is uniform polydisc-radius preservation on hulls. +`HasHolomorphicHullDistanceProperty` is exact preservation of extended boundary distance. Each +implies the other, and each implies `IsHolomorphicallyConvex`. +-/ + +public noncomputable section + +open Set Metric +open scoped ENNReal + +namespace SeveralComplexVariables + +/-- The extended distance of a set to the complement of an ambient set. -/ +@[expose] noncomputable def boundaryEDistance {X : Type*} [PseudoMetricSpace X] (U K : Set X) + : ℝ≥0∞ := + ⨅ x ∈ K, infEDist x Uᶜ + +/-- Empty compact sets have infinite boundary distance. -/ +@[simp] theorem boundaryEDistance_empty {X : Type*} [PseudoMetricSpace X] (U : Set X) : + boundaryEDistance U ∅ = ⊤ := by simp [boundaryEDistance] + +/-- In the whole ambient space every set has infinite boundary distance. -/ +@[simp] theorem boundaryEDistance_univ {X : Type*} [PseudoMetricSpace X] (K : Set X) : + boundaryEDistance univ K = ⊤ := by simp [boundaryEDistance] + +/-- Enlarging a set decreases its distance to the complement. -/ +theorem boundaryEDistance_anti {X : Type*} [PseudoMetricSpace X] {U K L : Set X} + (hKL : K ⊆ L) : boundaryEDistance U L ≤ boundaryEDistance U K := by + exact le_iInf fun x => le_iInf fun hx => iInf₂_le x (hKL hx) + +/-- A lower bound for boundary distance means that all corresponding open balls stay inside the +ambient set. This formulation includes nonpositive radii and empty sets. -/ +theorem ofReal_le_boundaryEDistance_iff {X : Type*} [PseudoMetricSpace X] + {U K : Set X} {r : ℝ} : + ENNReal.ofReal r ≤ boundaryEDistance U K ↔ ∀ x ∈ K, ball x r ⊆ U := by + simp only [boundaryEDistance, le_iInf_iff, le_infEDist] + constructor + · intro h x hx y hy + by_contra hn + have hle := h x hx y hn + have hlt : edist x y < ENNReal.ofReal r := edist_lt_ofReal.mpr + (by simpa only [mem_ball, dist_comm] using hy) + exact (not_lt_of_ge hle) hlt + · intro h x hx y hy + apply le_of_not_gt + intro hlt + exact hy (h x hx (by simpa only [mem_ball, dist_comm] using edist_lt_ofReal.mp hlt)) + +variable {ι : Type*} [Fintype ι] + +/-- Uniform polydisc radii available on a compact set remain available on its holomorphic hull. +Openness is separate from this property. -/ +@[expose] def HasHolomorphicHullRadiusProperty (U : Set (ι → ℂ)) : Prop := + ∀ K, IsCompact K → K ⊆ U → ∀ r : ℝ, 0 < r → + (∀ x ∈ K, ball x r ⊆ U) → ∀ a ∈ holomorphicHull U K, ball a r ⊆ U + +/-- Preservation of the extended boundary distance under taking holomorphic hulls. -/ +@[expose] def HasHolomorphicHullDistanceProperty (U : Set (ι → ℂ)) : Prop := + ∀ K, IsCompact K → K ⊆ U → + boundaryEDistance U (holomorphicHull U K) = boundaryEDistance U K + +/-- The radius property implies exact boundary-distance preservation. -/ +theorem HasHolomorphicHullRadiusProperty.hasHolomorphicHullDistanceProperty {U : Set (ι → ℂ)} + (h : HasHolomorphicHullRadiusProperty U) : HasHolomorphicHullDistanceProperty U := by + intro K hK hKU + apply le_antisymm (boundaryEDistance_anti (subset_holomorphicHull hKU)) + apply ENNReal.le_of_forall_pos_nnreal_lt + intro r hr hrK + have hball : ∀ x ∈ K, ball x (r : ℝ) ⊆ U := + ofReal_le_boundaryEDistance_iff.mp (by simpa using hrK.le) + have hh := h K hK hKU r hr hball + simpa using ofReal_le_boundaryEDistance_iff.mpr hh + +/-- Boundary-distance preservation implies the uniform radius property. -/ +theorem HasHolomorphicHullDistanceProperty.hasHolomorphicHullRadiusProperty {U : Set (ι → ℂ)} + (h : HasHolomorphicHullDistanceProperty U) : HasHolomorphicHullRadiusProperty U := by + intro K hK hKU r _ hr + apply ofReal_le_boundaryEDistance_iff.mp + rw [h K hK hKU] + exact ofReal_le_boundaryEDistance_iff.mpr hr + +/-- Uniform preservation of positive hull radii makes every compact hull compact. -/ +theorem HasHolomorphicHullRadiusProperty.isHolomorphicallyConvex + {U : Set (ι → ℂ)} (h : HasHolomorphicHullRadiusProperty U) (ho : IsOpen U) : + IsHolomorphicallyConvex U := by + intro K hK hKU + obtain ⟨r, hr, hthick⟩ := hK.exists_thickening_subset_open ho hKU + have hb : ∀ x ∈ K, ball x r ⊆ U := by + intro x hx y hy + exact hthick (mem_thickening_iff.mpr ⟨x, hx, hy⟩) + have hH := h K hK hKU r hr hb + have hcl : closure (holomorphicHull U K) ⊆ U := by + intro a ha + obtain ⟨z, hz, hza⟩ := Metric.mem_closure_iff.mp ha r hr + exact hH z hz (by simpa only [mem_ball, dist_comm] using hza) + exact isCompact_holomorphicHull_of_subset_compact + (isBounded_holomorphicHull U hK.isBounded).isCompact_closure hcl subset_closure + +/-- The boundary-distance characterization implies holomorphic convexity. -/ +theorem HasHolomorphicHullDistanceProperty.isHolomorphicallyConvex + {U : Set (ι → ℂ)} (h : HasHolomorphicHullDistanceProperty U) (ho : IsOpen U) : + IsHolomorphicallyConvex U := h.hasHolomorphicHullRadiusProperty.isHolomorphicallyConvex ho + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Exhaustion.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Exhaustion.lean new file mode 100644 index 0000000000..a024810306 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Exhaustion.lean @@ -0,0 +1,264 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Baire.CompleteMetrizable +public import Mathlib.Topology.Baire.Lemmas +public import Mathlib.Topology.Compactness.SigmaCompact +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Holomorphically convex exhaustions and escaping sequences + +Separation outside a hull can be amplified by powers to make a function arbitrarily small on the +original set and arbitrarily large at the chosen point. This step is proved. The compact +exhaustion is constructed by repeatedly enlarging compact sets and taking their holomorphic +hulls. The escaping-sequence characterization follows from Baire's theorem in the complete space +of holomorphic functions. Exhaustions use Mathlib's `CompactExhaustion` on the open subtype, +rather than a new topological structure. + +References: [Range][Range1986] II §3.2; [Fritzsche–Grauert][FritzscheGrauert2002] II §6; +[Scheidemann][Scheidemann2005] §7.1. + +## Main results + +`IsHolomorphicallyConvex.exists_compactExhaustion` produces a compact exhaustion by hull-fixed +sets. `isHolomorphicallyConvex_iff_unbounded_on_escaping_sequences` is the escaping-sequence +characterization. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Powers of a separating function give arbitrary smallness on the set and an arbitrary large value +at an exterior hull point. Empty sets are included. -/ +theorem exists_small_large_separator {U K : Set E} {a : E} + (ha : a ∈ U) (hn : a ∉ holomorphicHull U K) {ε : ℝ} (hε : 0 < ε) (R : ℝ) : + ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ (∀ z ∈ K, ‖f z‖ < ε) ∧ R < ‖f a‖ := by + let A : ℝ := max R 0 + 1 + have hA : 0 < A := by dsimp [A]; positivity + have hRA : R < A := by dsimp [A]; linarith [le_max_left R 0] + rcases K.eq_empty_or_nonempty with hK | hK + · subst K + exact ⟨fun _ => (A : ℂ), analyticOnNhd_const, by simp, + by simpa only [Complex.norm_of_nonneg hA.le] using hRA⟩ + obtain ⟨f, hf, M, hM, hMa⟩ := exists_separator_of_notMem_holomorphicHull ha hn + obtain ⟨z₀, hz₀⟩ := hK + have hM0 : 0 ≤ M := (norm_nonneg _).trans (hM z₀ hz₀) + have hfa : 0 < ‖f a‖ := hM0.trans_lt hMa + have hq : M / ‖f a‖ < 1 := (div_lt_one hfa).mpr hMa + obtain ⟨k, hk⟩ := exists_pow_lt_of_lt_one (div_pos hε hA) hq + refine ⟨fun z => (A : ℂ) * (f z / f a) ^ k, + analyticOnNhd_const.mul (hf.div_const.pow k), ?_, ?_⟩ + · intro z hz + rw [norm_mul, Complex.norm_of_nonneg hA.le, norm_pow, norm_div] + calc + A * (‖f z‖ / ‖f a‖) ^ k ≤ A * (M / ‖f a‖) ^ k := by + gcongr + exact hM z hz + _ < ε := (lt_div_iff₀ hA).mp hk |> (by simpa [mul_comm] using ·) + · simpa [div_self (norm_pos_iff.mp hfa), Complex.norm_of_nonneg hA.le, abs_of_pos hA] using hRA + +variable [FiniteDimensional ℂ E] + +/-- Finite-dimensional source spaces are proper. -/ +local instance : ProperSpace E := FiniteDimensional.proper ℂ E + +/-- Finite-dimensional source spaces have countable bases. -/ +local instance : SecondCountableTopology E := + (Module.finBasis ℂ E).equivFunL.toHomeomorph.secondCountableTopology + +/-- A holomorphically convex open set has a compact exhaustion by sets fixed by the relative +holomorphic hull, by recursive refinement of a compact exhaustion. -/ +theorem IsHolomorphicallyConvex.exists_compactExhaustion {U : Set E} + (hU : IsHolomorphicallyConvex U) (ho : IsOpen U) : + ∃ K : CompactExhaustion U, ∀ j, + IsHolomorphicallyConvexIn U ((Subtype.val : U → E) '' K j) := by + let : LocallyCompactSpace U := ho.locallyCompactSpace + let B := CompactExhaustion.choice U + let H (S : Set U) : Set U := + (Subtype.val : U → E) ⁻¹' holomorphicHull U (Subtype.val '' S) + have himage (S : Set U) : Subtype.val '' H S = holomorphicHull U (Subtype.val '' S) := by + apply image_preimage_eq_of_subset + intro z hz + exact ⟨⟨z, hz.1⟩, rfl⟩ + have hcompact (S : Set U) (hS : IsCompact S) : IsCompact (H S) := by + apply Topology.IsEmbedding.subtypeVal.isCompact_iff.mpr + rw [himage] + exact hU _ (hS.image continuous_subtype_val) (by rintro _ ⟨z, _, rfl⟩; exact z.property) + have hsubset (S : Set U) : S ⊆ H S := by + intro z hz + exact subset_holomorphicHull (by rintro _ ⟨w, _, rfl⟩; exact w.property) ⟨z, hz, rfl⟩ + have hfixed (S : Set U) : IsHolomorphicallyConvexIn U (Subtype.val '' H S) := by + rw [himage] + exact isHolomorphicallyConvexIn_holomorphicHull _ _ + let enlarge (S : {S : Set U // IsCompact S}) : {S : Set U // IsCompact S} := + ⟨(exists_compact_superset S.property).choose, (exists_compact_superset + S.property).choose_spec.1⟩ + have henlarge (S : {S : Set U // IsCompact S}) : S.val ⊆ interior (enlarge S).val := + (exists_compact_superset S.property).choose_spec.2 + let K : ℕ → {S : Set U // IsCompact S} := fun j => + Nat.recOn j ⟨H (B 0), hcompact _ (B.isCompact 0)⟩ fun j S => + ⟨H ((enlarge S).val ∪ B (j + 1)), hcompact _ ((enlarge S).property.union (B.isCompact _))⟩ + have hBK (j : ℕ) : B j ⊆ (K j).val := by + cases j with + | zero => exact hsubset _ + | succ j => exact subset_union_right.trans (hsubset _) + refine ⟨{ toFun := fun j => (K j).val + isCompact' := fun j => (K j).property + subset_interior_succ' := ?_ + iUnion_eq' := ?_ }, ?_⟩ + · intro j + exact (henlarge (K j)).trans (interior_mono (subset_union_left.trans (hsubset _))) + · apply iUnion_eq_univ_iff.mpr + intro z + obtain ⟨j, hj⟩ := B.exists_mem z + exact ⟨j, hBK j hj⟩ + · intro j + cases j with + | zero => exact hfixed _ + | succ j => exact hfixed _ + +/-- A sequence escapes compact subsets when it eventually leaves every compact set in the ambient +domain. Its membership in the domain is a separate hypothesis. -/ +@[expose] def EscapesCompactSubsets (U : Set E) (p : ℕ → E) : Prop := + ∀ K : Set E, IsCompact K → K ⊆ U → ∀ᶠ j in atTop, p j ∉ K + +/-- A Baire argument turns functions tending to zero in the compact-open topology, but arbitrarily +large somewhere on a sequence, into one function unbounded there. -/ +private theorem exists_unbounded_of_small_functions + (V : TopologicalSpace.Opens E) (p : ℕ → V) + (hsmall : ∀ M : ℝ, ∃ F : ℕ → HolomorphicMap V ℂ, + Tendsto F atTop (𝓝 0) ∧ ∀ n, ∃ j, M < ‖(F n).val (p j)‖) : + ∃ f : HolomorphicMap V ℂ, ¬ BddAbove (range (fun j => ‖f.val (p j)‖)) := by + let : LocallyCompactSpace V := V.isOpen.locallyCompactSpace + have : (uniformity C(V, ℂ)).IsCountablyGenerated := inferInstance + have : (uniformity (HolomorphicMap V ℂ)).IsCountablyGenerated := + Filter.comap.isCountablyGenerated _ _ + have : TopologicalSpace.IsCompletelyPseudoMetrizableSpace (HolomorphicMap V ℂ) := + .of_completeSpace_pseudometrizable + let : BaireSpace (HolomorphicMap V ℂ) := BaireSpace.of_completelyPseudoMetrizable + by_contra! hb + let A (n : ℕ) : Set (HolomorphicMap V ℂ) := {f | ∀ j, ‖f.val (p j)‖ ≤ n} + have hclosed (n : ℕ) : IsClosed (A n) := by + simp only [A, ofPred_forall] + exact isClosed_iInter fun j => isClosed_le + (continuous_holomorphicMap_eval V (p j)).norm continuous_const + have hcover : ⋃ n, A n = univ := by + apply iUnion_eq_univ_iff.mpr + intro f + obtain ⟨M, hM⟩ := hb f + obtain ⟨n, hn⟩ := exists_nat_ge M + exact ⟨n, fun j => (hM (mem_range_self j)).trans hn⟩ + obtain ⟨N, g, hg⟩ := nonempty_interior_of_iUnion_of_closed hclosed hcover + have hgA : g ∈ A N := interior_subset hg + obtain ⟨F, hlim, hlarge⟩ := hsmall (2 * (N : ℝ)) + have hlim' : Tendsto (fun n => g + F n) atTop (𝓝 g) := by + simpa only [add_zero] using tendsto_const_nhds.add hlim + obtain ⟨n, hn⟩ := (hlim'.eventually (mem_interior_iff_mem_nhds.mp hg)).exists + obtain ⟨j, hj⟩ := hlarge n + have hsum : ‖g.val (p j) + (F n).val (p j)‖ ≤ N := hn j + have hgn := hgA j + have hnorm := norm_sub_le (g.val (p j) + (F n).val (p j)) (g.val (p j)) + simp only [add_sub_cancel_left] at hnorm + linarith + +/-- **Escaping-sequence characterization of holomorphic convexity.** Baire's theorem +and small separating functions give an unbounded holomorphic function on any escaping +sequence; conversely, a noncompact hull contains an escaping sequence. -/ +theorem isHolomorphicallyConvex_iff_unbounded_on_escaping_sequences + {U : Set E} (ho : IsOpen U) : + IsHolomorphicallyConvex U ↔ + ∀ p : ℕ → E, (∀ j, p j ∈ U) → EscapesCompactSubsets U p → + ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ + ¬ BddAbove (Set.range (fun j => ‖f (p j)‖)) := by + classical + let V : TopologicalSpace.Opens E := ⟨U, ho⟩ + let : LocallyCompactSpace V := ho.locallyCompactSpace + let K := CompactExhaustion.choice V + let C (n : ℕ) : Set E := Subtype.val '' K n + have hC (n : ℕ) : IsCompact (C n) := (K.isCompact n).image continuous_subtype_val + have hCU (n : ℕ) : C n ⊆ U := by + rintro _ ⟨z, _, rfl⟩ + exact z.property + have hcofinal {S : Set E} (hS : IsCompact S) (hSU : S ⊆ U) : + ∃ n, S ⊆ C n := by + have he : Subtype.val '' ((Subtype.val : V → E) ⁻¹' S) = S := + image_preimage_eq_of_subset (by intro z hz; exact ⟨⟨z, hSU hz⟩, rfl⟩) + have hc : IsCompact ((Subtype.val : V → E) ⁻¹' S) := + Topology.IsEmbedding.subtypeVal.isCompact_iff.mpr (he.symm ▸ hS) + obtain ⟨n, hn⟩ := K.exists_superset_of_isCompact hc + exact ⟨n, fun z hz => ⟨⟨z, hSU hz⟩, hn hz, rfl⟩⟩ + constructor + · intro hconv p hp hescape + obtain ⟨g, hg⟩ := exists_unbounded_of_small_functions V (fun j => ⟨p j, hp j⟩) (by + intro M + have hsep (n : ℕ) : ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ + (∀ z ∈ C n, ‖f z‖ < 1 / ((n : ℝ) + 1)) ∧ ∃ j, M < ‖f (p j)‖ := by + obtain ⟨j, hj⟩ := (hescape (holomorphicHull U (C n)) + (hconv _ (hC n) (hCU n)) (holomorphicHull_subset _ _)).exists + obtain ⟨f, hf, hs, hl⟩ := exists_small_large_separator (hp j) hj + (by positivity : 0 < 1 / ((n : ℝ) + 1)) (M) + exact ⟨f, hf, hs, j, hl⟩ + choose f hf hs j hj using hsep + let F (n : ℕ) : HolomorphicMap V ℂ := + ⟨⟨fun z => f n z, (hf n).continuousOn.domRestrict⟩, + (hf n).congr ho (fun z hz => by rw [openExtension_apply V _ hz]; rfl)⟩ + have hlim : Tendsto F atTop (𝓝 0) := by + rw [holomorphicMap_tendsto_iff, tendstoLocallyUniformlyOn_iff_forall_isCompact V.isOpen] + intro S hSU hS + obtain ⟨m, hm⟩ := hcofinal hS hSU + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + have ht := (tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℝ)).eventually + (gt_mem_nhds hε) + filter_upwards [eventually_ge_atTop m, ht] with n hn hεn + intro z hz + rw [openExtension_apply V _ (hSU hz), openExtension_apply V _ (hSU hz)] + change dist (0 : ℂ) (f n z) < ε + rw [dist_zero_left] + exact (hs n z (image_mono (K.subset hn) (hm hz))).trans hεn + exact ⟨F, hlim, fun n => ⟨j n, hj n⟩⟩) + refine ⟨openExtension V g.val, g.property, ?_⟩ + simpa only [openExtension_apply V _ (hp _)] using hg + · intro hseq S hS hSU + by_contra hn + have hex (n : ℕ) : ∃ z ∈ holomorphicHull U S, z ∉ C n := by + by_contra hh + apply hn + apply isCompact_holomorphicHull_of_subset_compact (hC n) (hCU n) + simpa only [not_exists, not_and, not_not, subset_def] using hh + choose p hp hnC using hex + have hpU (n : ℕ) : p n ∈ U := (hp n).1 + have he : EscapesCompactSubsets U p := by + intro T hT hTU + obtain ⟨n, hn⟩ := hcofinal hT hTU + filter_upwards [eventually_ge_atTop n] with m hm hpm + exact hnC m (image_mono (K.subset hm) (hn hpm)) + obtain ⟨f, hf, hnf⟩ := hseq p hpU he + obtain ⟨M, hM⟩ := hS.exists_bound_of_continuousOn (hf.continuousOn.mono hSU) + apply hnf + exact ⟨M, by rintro _ ⟨n, rfl⟩; exact (hp n).2 f hf M hM⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Hull.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Hull.lean new file mode 100644 index 0000000000..07d4d0bac3 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Hull.lean @@ -0,0 +1,266 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Group.Bounded +public import Mathlib.Analysis.Normed.Module.HahnBanach +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Holomorphic hulls relative to an ambient set + +The hull is tested by scalar analytic functions on the ambient set. On open sets these are +precisely holomorphic functions. The formulation uses all real upper bounds rather than a real +supremum, so empty sets and unbounded functions have the intended behavior. In particular the +empty hull is empty. Relative closedness is expressed on the ambient subtype; no ambient +closedness or compactness of the hull is assumed. + +References: [Range][Range1986] II §3.2; [Scheidemann][Scheidemann2005] §6.2; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] §2.7. + +## Main results + +`holomorphicHull` is the scalar hull relative to an ambient set, tested by all real modulus +bounds. `IsHolomorphicallyConvex` is the property that compact subsets of an open set have +compact hulls in that set. `exists_separator_of_notMem_holomorphicHull` separates a point +outside the hull. `holomorphicHull_idem` is idempotence. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The scalar holomorphic hull of `K` relative to `U`, using all real modulus bounds. -/ +@[expose] def holomorphicHull (U K : Set E) : Set E := + {z | z ∈ U ∧ ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → + ∀ M : ℝ, (∀ w ∈ K, ‖f w‖ ≤ M) → ‖f z‖ ≤ M} + +/-- On an open finite-dimensional domain, the hull may equivalently be tested by complex +Fréchet-differentiable scalar functions. -/ +theorem mem_holomorphicHull_iff_differentiableOn [FiniteDimensional ℂ E] + {U K : Set E} (ho : IsOpen U) {z : E} : + z ∈ holomorphicHull U K ↔ z ∈ U ∧ + ∀ f : E → ℂ, DifferentiableOn ℂ f U → + ∀ M : ℝ, (∀ w ∈ K, ‖f w‖ ≤ M) → ‖f z‖ ≤ M := by + constructor + · intro hz + exact ⟨hz.1, fun f hf => hz.2 f (hf.analyticOnNhd_of_finiteDimensional ho)⟩ + · intro hz + exact ⟨hz.1, fun f hf => hz.2 f hf.differentiableOn⟩ + +/-- A holomorphic hull is contained in its ambient set. -/ +theorem holomorphicHull_subset (U K : Set E) : holomorphicHull U K ⊆ U := + fun _ hz => hz.1 + +/-- A set contained in the ambient set is contained in its holomorphic hull. -/ +theorem subset_holomorphicHull {U K : Set E} (hKU : K ⊆ U) : K ⊆ holomorphicHull U K := + fun z hz => ⟨hKU hz, fun _ _ _ h => h z hz⟩ + +/-- Modulus bounds transfer from a set to its holomorphic hull. -/ +theorem norm_le_on_holomorphicHull {U K : Set E} {f : E → ℂ} + (hf : AnalyticOnNhd ℂ f U) {M : ℝ} (hM : ∀ w ∈ K, ‖f w‖ ≤ M) : + ∀ z ∈ holomorphicHull U K, ‖f z‖ ≤ M := + fun _ hz => hz.2 f hf M hM + +/-- Norm bounds transfer from a set to its scalar holomorphic hull for Banach-valued holomorphic +maps, by norming functionals. -/ +theorem norm_le_on_holomorphicHull_vector {U K : Set E} {G : E → F} + (hG : AnalyticOnNhd ℂ G U) {M : ℝ} (hM : ∀ w ∈ K, ‖G w‖ ≤ M) : + ∀ z ∈ holomorphicHull U K, ‖G z‖ ≤ M := by + intro z hz + obtain ⟨ℓ, hℓ, hℓz⟩ := exists_dual_vector'' ℂ (G z) + have hcomp : AnalyticOnNhd ℂ (fun w => ℓ (G w)) U := + (ℓ.analyticOnNhd univ).comp hG (mapsTo_univ _ _) + have := hz.2 _ hcomp M fun w hw => + calc ‖ℓ (G w)‖ ≤ ‖ℓ‖ * ‖G w‖ := ℓ.le_opNorm _ + _ ≤ 1 * M := by + gcongr + exact hM w hw + _ = M := one_mul M + rwa [hℓz, RCLike.norm_ofReal, abs_norm] at this + +/-- Holomorphic hulls are monotone in the set being tested. -/ +theorem holomorphicHull_mono {U K L : Set E} (hKL : K ⊆ L) : + holomorphicHull U K ⊆ holomorphicHull U L := + fun _ hz => ⟨hz.1, fun f hf M h => hz.2 f hf M (fun w hw => h w (hKL hw))⟩ + +/-- Enlarging the ambient set enlarges its relative holomorphic hull. -/ +theorem holomorphicHull_mono_ambient {U V K : Set E} (hUV : U ⊆ V) : + holomorphicHull U K ⊆ holomorphicHull V K := + fun _ hz => ⟨hUV hz.1, fun f hf M h => hz.2 f (hf.mono hUV) M h⟩ + +/-- Taking a holomorphic hull twice has no further effect. -/ +@[simp] theorem holomorphicHull_idem (U K : Set E) : + holomorphicHull U (holomorphicHull U K) = holomorphicHull U K := by + apply Subset.antisymm + · intro z hz + exact ⟨hz.1, fun f hf M h => hz.2 f hf M (norm_le_on_holomorphicHull hf h)⟩ + · exact subset_holomorphicHull (holomorphicHull_subset U K) + +/-- The empty set has empty holomorphic hull, in every ambient set. -/ +@[simp] theorem holomorphicHull_empty (U : Set E) : holomorphicHull U ∅ = ∅ := by + apply eq_empty_iff_forall_notMem.mpr + intro z hz + have h := hz.2 (fun _ => 0) analyticOnNhd_const (-1) (by simp) + norm_num at h + +/-- The ambient set is fixed by its holomorphic hull. -/ +@[simp] theorem holomorphicHull_self (U : Set E) : holomorphicHull U U = U := + Subset.antisymm (holomorphicHull_subset _ _) (subset_holomorphicHull Subset.rfl) + +/-- The holomorphic hull is closed relative to its ambient set. -/ +theorem isClosed_holomorphicHull_preimage (U K : Set E) : + IsClosed ((Subtype.val : U → E) ⁻¹' holomorphicHull U K) := by + have he : (Subtype.val : U → E) ⁻¹' holomorphicHull U K = + ⋂ (f : E → ℂ) (hf : AnalyticOnNhd ℂ f U) (M : ℝ) + (_ : ∀ w ∈ K, ‖f w‖ ≤ M), {z : U | ‖f z‖ ≤ M} := by + ext z + simp [holomorphicHull] + rw [he] + exact isClosed_iInter fun f => isClosed_iInter fun hf => + isClosed_iInter fun M => isClosed_iInter fun _ => + isClosed_le (continuousOn_iff_continuous_domRestrict.mp hf.continuousOn).norm continuous_const + +/-- A point of the ambient set outside the hull is separated by a scalar holomorphic function and a +strict modulus bound. -/ +theorem exists_separator_of_notMem_holomorphicHull {U K : Set E} {z : E} + (hz : z ∈ U) (hn : z ∉ holomorphicHull U K) : + ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ ∃ M : ℝ, + (∀ w ∈ K, ‖f w‖ ≤ M) ∧ M < ‖f z‖ := by + simpa only [holomorphicHull, mem_ofPred_eq, hz, true_and, not_forall, not_le, + exists_prop] using hn + +/-- Holomorphic maps carry relative hulls into relative hulls. -/ +theorem mapsTo_holomorphicHull {U K : Set E} {V : Set F} {g : E → F} + (hg : AnalyticOnNhd ℂ g U) (hgV : MapsTo g U V) : + MapsTo g (holomorphicHull U K) (holomorphicHull V (g '' K)) := by + intro z hz + refine ⟨hgV hz.1, fun f hf M hM => ?_⟩ + exact hz.2 (f ∘ g) (hf.comp hg hgV) M (fun w hw => hM (g w) ⟨w, hw, rfl⟩) + +/-- A set is holomorphically convex relative to `U` when its hull equals itself. -/ +@[expose] def IsHolomorphicallyConvexIn (U K : Set E) : Prop := holomorphicHull U K = K + +/-- Every holomorphic hull is holomorphically convex relative to its ambient set. -/ +theorem isHolomorphicallyConvexIn_holomorphicHull (U K : Set E) : + IsHolomorphicallyConvexIn U (holomorphicHull U K) := holomorphicHull_idem U K + +/-- Holomorphic convexity of an ambient set means compactness of the hull of each compact subset. +Openness and connectedness are separate hypotheses. -/ +@[expose] def IsHolomorphicallyConvex (U : Set E) : Prop := + ∀ K : Set E, IsCompact K → K ⊆ U → IsCompact (holomorphicHull U K) + +/-- The empty ambient set is holomorphically convex. -/ +theorem isHolomorphicallyConvex_empty : IsHolomorphicallyConvex (∅ : Set E) := by + intro K _ _ + have : holomorphicHull (∅ : Set E) K = ∅ := + subset_empty_iff.mp (holomorphicHull_subset _ _) + rw [this] + exact isCompact_empty + +/-- A relative holomorphic hull contained in a compact subset of its ambient set is compact. -/ +theorem isCompact_holomorphicHull_of_subset_compact {U K C : Set E} + (hC : IsCompact C) (hCU : C ⊆ U) (hHC : holomorphicHull U K ⊆ C) : + IsCompact (holomorphicHull U K) := by + obtain ⟨S, hS, he⟩ := isClosed_induced_iff.mp (isClosed_holomorphicHull_preimage U K) + have heq : holomorphicHull U K = C ∩ S := by + ext z + constructor + · intro hz + refine ⟨hHC hz, ?_⟩ + have h := Set.ext_iff.mp he ⟨z, (holomorphicHull_subset U K) hz⟩ + exact h.mpr hz + · rintro ⟨hzC, hzS⟩ + have h := Set.ext_iff.mp he ⟨z, hCU hzC⟩ + exact h.mp hzS + rw [heq] + exact hC.inter_right hS + +/-- Finite intersections preserve holomorphic convexity of ambient sets. -/ +theorem IsHolomorphicallyConvex.inter {U V : Set E} + (hU : IsHolomorphicallyConvex U) (hV : IsHolomorphicallyConvex V) : + IsHolomorphicallyConvex (U ∩ V) := by + intro K hK hKU + apply isCompact_holomorphicHull_of_subset_compact + ((hU K hK (hKU.trans inter_subset_left)).inter + (hV K hK (hKU.trans inter_subset_right))) + · rintro z ⟨hzU, hzV⟩ + exact ⟨hzU.1, hzV.1⟩ + · intro z hz + exact ⟨holomorphicHull_mono_ambient inter_subset_left hz, + holomorphicHull_mono_ambient inter_subset_right hz⟩ + +/-- In finite coordinate spaces, the hull of a bounded set is bounded. -/ +theorem isBounded_holomorphicHull {ι : Type*} [Fintype ι] + (U : Set (ι → ℂ)) {K : Set (ι → ℂ)} (hK : Bornology.IsBounded K) : + Bornology.IsBounded (holomorphicHull U K) := by + obtain ⟨M, hM⟩ := hK.exists_norm_le + apply (isBounded_iff_forall_norm_le).mpr + refine ⟨max M 0, fun z hz => (pi_norm_le_iff_of_nonneg (le_max_right _ _)).mpr fun i => ?_⟩ + exact (hz.2 (fun w => w i) ((ContinuousLinearMap.proj i : (ι → ℂ) →L[ℂ] ℂ).analyticOnNhd U) M + (fun w hw => (norm_le_pi_norm w i).trans (hM w hw))).trans (le_max_left _ _) + +/-- A singleton has no additional hull points; if it lies outside the ambient set, its relative hull +is empty. Empty coordinate types are included. -/ +@[simp] theorem holomorphicHull_singleton {ι : Type*} [Fintype ι] + (U : Set (ι → ℂ)) (a : ι → ℂ) : holomorphicHull U {a} = U ∩ {a} := by + ext z + constructor + · intro hz + refine ⟨hz.1, ?_⟩ + have he : z = a := by + ext i + have hf : AnalyticOnNhd ℂ (fun w : ι → ℂ => w i - a i) U := + ((ContinuousLinearMap.proj i : (ι → ℂ) →L[ℂ] ℂ).analyticOnNhd U).sub analyticOnNhd_const + have h := hz.2 _ hf 0 (by simp) + exact sub_eq_zero.mp (norm_le_zero_iff.mp h) + exact mem_singleton_iff.mpr he + · rintro ⟨hz, rfl⟩ + exact ⟨hz, fun f hf M hM => hM z (mem_singleton z)⟩ + +/-- The full finite-dimensional coordinate space is holomorphically convex. -/ +theorem isHolomorphicallyConvex_univ {ι : Type*} [Fintype ι] : + IsHolomorphicallyConvex (univ : Set (ι → ℂ)) := by + intro K hK _ + obtain ⟨r, hr⟩ := (Metric.isBounded_iff_subset_closedBall (0 : ι → ℂ)).mp + (isBounded_holomorphicHull univ hK.isBounded) + exact isCompact_holomorphicHull_of_subset_compact (isCompact_closedBall 0 r) + (subset_univ _) hr + +/-- Continuous complex-linear equivalences preserve holomorphic convexity. -/ +theorem IsHolomorphicallyConvex.image_equiv {U : Set E} + (hU : IsHolomorphicallyConvex U) (L : E ≃L[ℂ] F) : + IsHolomorphicallyConvex (L '' U) := by + intro K hK hKU + have hmap : MapsTo L.symm (L '' U) U := by + rintro _ ⟨z, hz, rfl⟩ + simpa using hz + have hc := hU (L.symm '' K) (hK.image L.symm.continuous) + (by rintro _ ⟨z, hz, rfl⟩; exact hmap (hKU hz)) + apply isCompact_holomorphicHull_of_subset_compact (hc.image L.continuous) + · rintro _ ⟨z, hz, rfl⟩ + exact ⟨z, hz.1, rfl⟩ + · intro z hz + exact ⟨L.symm z, + mapsTo_holomorphicHull (L.symm.toContinuousLinearMap.analyticOnNhd _) hmap hz, + L.apply_symm_apply z⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Thullen.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Thullen.lean new file mode 100644 index 0000000000..dbaf7ab88d --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Thullen.lean @@ -0,0 +1,328 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Module.Ball.Pointwise +public import Mathlib.Analysis.Normed.Module.Connected +public import Mathlib.Analysis.Normed.Module.HahnBanach +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic + +/-! +# Thullen's lemma and the boundary distance of holomorphic hulls + +Cauchy bounds on compact families of smaller balls control Taylor coefficients weighted by +powers of a scalar holomorphic radius. These bounds transfer to the holomorphic hull, for +Banach-valued functions by norming functionals, and give Taylor continuation on the indicated +polydisc. Agreement is asserted near the center, not on unrelated components of the overlap. +This proves radius preservation, exact hull boundary distance, and holomorphic convexity for +domains of holomorphy. + +References: [Scheidemann][Scheidemann2005] §6.2 and §7.3; [Hörmander][Hormander1973] §2.5; +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] §6.4. + +## Main results + +`taylor_continuation_on_holomorphicHull` is Thullen's Taylor continuation lemma for +Banach-valued functions. `IsDomainOfHolomorphy.holomorphic_radius_bound` is the weighted radius +bound. `IsDomainOfHolomorphy.hasHolomorphicHullRadiusProperty` and +`hasHolomorphicHullDistanceProperty` are the hull-radius and boundary-distance forms. +`IsDomainOfHolomorphy.isHolomorphicallyConvex` is the forward Cartan–Thullen implication. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology ENNReal Pointwise + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Mixed derivative bounds transfer to the holomorphic hull of the set on which they hold, for +Banach-valued functions. This elementary step is independent of the Taylor continuation theorem. -/ +theorem norm_multiIndexDeriv_le_on_holomorphicHull {U K : Set (Fin n → ℂ)} + (ho : IsOpen U) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + (m : Fin n → ℕ) {M : ℝ} (hM : ∀ z ∈ K, ‖multiIndexDeriv m f z‖ ≤ M) : + ∀ z ∈ holomorphicHull U K, ‖multiIndexDeriv m f z‖ ≤ M := + norm_le_on_holomorphicHull_vector (hf.iteratedPartialDeriv ho (multiIndexList m)) hM + +/-- The Taylor sum of a Banach-valued function centered at an arbitrary point, using the normalized +multivariate Taylor coefficients. -/ +@[expose] def taylorSumAt (f : (Fin n → ℂ) → F) (a z : Fin n → ℂ) : F := + powerSeriesSum (holomorphicTaylorSeries f a) (z - a) + +omit [CompleteSpace F] in +/-- Separate analyticity on a closed polydisc from joint analyticity. -/ +theorem analyticAt_update_of_analyticOnNhd_closedPolydisc {f : (Fin n → ℂ) → F} + {a : Fin n → ℂ} {r : ℝ} (hA : AnalyticOnNhd ℂ f (closedPolydisc a (fun _ => r))) : + ∀ z ∈ closedPolydisc a (fun _ => r), ∀ i, + AnalyticAt ℂ (fun v => f (Function.update z i v)) (z i) := by + intro z hz i + exact hA.analyticAt_update hz i + +/-- A bound on a closed coordinate ball bounds each normalized Taylor coefficient. -/ +theorem norm_taylorCoeff_le {U : Set (Fin n → ℂ)} + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {a : Fin n → ℂ} {r M : ℝ} (hr : 0 < r) (hball : closedBall a r ⊆ U) + (hM : ∀ z ∈ closedBall a r, ‖f z‖ ≤ M) (m : Fin n →₀ ℕ) : + ‖holomorphicTaylorSeries f a m‖ ≤ M * ∏ i, r⁻¹ ^ m i := by + have he : closedPolydisc a (fun _ => r) = closedBall a r := by + rw [closedPolydisc_eq_closedBall hr.le] + have hA : AnalyticOnNhd ℂ f (closedPolydisc a (fun _ => r)) := + hf.mono (he ▸ hball) + rw [coeff_holomorphicTaylorSeries (fun _ => hr) hA.continuousOn + (analyticAt_update_of_analyticOnNhd_closedPolydisc hA)] + exact norm_polydiscCauchyCoeffWithRadii_le (fun _ => hr) (he ▸ hM) m + +/-- The normalized Taylor sum of an analytic germ agrees with its representative nearby. -/ +theorem taylorSumAt_eventuallyEq {f : (Fin n → ℂ) → F} {a : Fin n → ℂ} + (hf : AnalyticAt ℂ f a) : taylorSumAt f a =ᶠ[𝓝 a] f := by + classical + have hb := hf.continuousAt.norm.eventually_lt_const + (show ‖f a‖ < ‖f a‖ + 1 by linarith) + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hf.eventually_analyticAt.and hb) + have hr₂ : 0 < r / 2 := half_pos hr + have hsub : closedPolydisc a (fun _ => r / 2) ⊆ ball a r := by + rw [closedPolydisc_eq_closedBall hr₂.le] + exact closedBall_subset_ball (half_lt_self hr) + have hA : AnalyticOnNhd ℂ f (closedPolydisc a (fun _ => r / 2)) := + fun z hz => (hball (hsub hz)).1 + have hs := analyticAt_update_of_analyticOnNhd_closedPolydisc hA + filter_upwards [ball_mem_nhds a hr₂] with z hz + have hh : ∀ i, ‖(z - a) i‖ < r / 2 := fun i => + (norm_le_pi_norm (z - a) i).trans_lt (by simpa only [mem_ball, dist_eq_norm] using hz) + have hsum := hasSum_polydiscTaylor (fun _ => hr₂) hh hA.continuousOn hs + (fun z hz => (hball (hsub hz)).2.le) + have hc (m : Fin n →₀ ℕ) : + polydiscCauchyCoeffWithRadii f a (fun _ => r / 2) (Finsupp.equivFunOnFinite m) = + holomorphicTaylorSeries f a m := + (coeff_holomorphicTaylorSeries (fun _ => hr₂) hA.continuousOn hs m).symm + have H := (Finsupp.equivFunOnFinite.hasSum_iff).mpr hsum + simpa only [taylorSumAt, powerSeriesSum, Pi.sub_apply, hc, + add_sub_cancel, Function.comp_apply, Finsupp.equivFunOnFinite_apply] using H.tsum_eq + +/-- Shrinking a continuous radius on a compact set gives uniform weighted Cauchy bounds. -/ +private theorem exists_bound_taylorCoeff_mul_radius {U K : Set (Fin n → ℂ)} + (hK : IsCompact K) (hKU : K ⊆ U) + {q : (Fin n → ℂ) → ℂ} {f : (Fin n → ℂ) → F} (hq : AnalyticOnNhd ℂ q U) + (hf : AnalyticOnNhd ℂ f U) + (hr : ∀ w ∈ K, ball w ‖q w‖ ⊆ U) {t : ℝ} (ht : 0 < t) (ht1 : t < 1) : + ∃ M : ℝ, 0 ≤ M ∧ ∀ (m : Fin n →₀ ℕ) w, w ∈ K → + ‖holomorphicTaylorSeries f w m‖ * (t * ‖q w‖) ^ (∑ i, m i) ≤ M := by + classical + let T := (fun p : (Fin n → ℂ) × (Fin n → ℂ) => p.1 + ((t : ℂ) * q p.1) • p.2) '' + (K ×ˢ closedBall 0 1) + have hTc : IsCompact T := (hK.prod (isCompact_closedBall _ _)).image_of_continuousOn + (continuous_fst.continuousOn.add ((continuousOn_const.mul + (hq.continuousOn.comp continuous_fst.continuousOn (fun _ h => hKU h.1))).smul + continuous_snd.continuousOn)) + have hTU : T ⊆ U := by + rintro _ ⟨⟨w, v⟩, ⟨hw, hv⟩, rfl⟩ + by_cases hq0 : q w = 0 + · simpa [hq0] using hKU hw + apply hr w hw + rw [mem_ball, dist_eq_norm, add_sub_cancel_left, norm_smul, norm_mul, + Complex.norm_of_nonneg ht.le] + have hv' : ‖v‖ ≤ 1 := by simpa only [mem_closedBall, dist_zero_right] using hv + calc + t * ‖q w‖ * ‖v‖ ≤ t * ‖q w‖ * 1 := mul_le_mul_of_nonneg_left hv' (by positivity) + _ < ‖q w‖ := by nlinarith [norm_pos_iff.mpr hq0] + have hballT (w) (hw : w ∈ K) : closedBall w (t * ‖q w‖) ⊆ T := by + intro z hz + have hz' : z - w ∈ ((t : ℂ) * q w) • closedBall (0 : Fin n → ℂ) 1 := by + rw [smul_unitClosedBall, norm_mul, Complex.norm_of_nonneg ht.le] + simpa only [mem_closedBall, dist_zero_right, dist_eq_norm, sub_zero] using hz + obtain ⟨v, hv, he⟩ := hz' + dsimp only at he + exact ⟨(w, v), ⟨hw, hv⟩, by dsimp; rw [he]; abel⟩ + obtain ⟨M, hM⟩ := hTc.exists_bound_of_continuousOn (hf.continuousOn.mono hTU) + refine ⟨max M 0, le_max_right _ _, fun m w hw => ?_⟩ + by_cases hq0 : q w = 0 + · by_cases hm : m = 0 + · subst m + simpa [holomorphicTaylorSeries, multiIndexDeriv, multiIndexList, iteratedPartialDeriv] + using (hM w (hballT w hw (mem_closedBall_self (by positivity)))).trans (le_max_left M 0) + · have hmpos : 0 < ∑ i, m i := by + obtain ⟨i, hi⟩ := Finsupp.ne_iff.mp hm + exact (Nat.pos_of_ne_zero hi).trans_le (Finset.single_le_sum (fun _ _ => Nat.zero_le _) + (Finset.mem_univ i)) + simp [hq0, zero_pow hmpos.ne'] + · have hR : 0 < t * ‖q w‖ := mul_pos ht (norm_pos_iff.mpr hq0) + have hb := norm_taylorCoeff_le hf hR ((hballT w hw).trans hTU) + (fun z hz => hM z (hballT w hw hz)) m + have hp : (∏ i, (t * ‖q w‖)⁻¹ ^ m i) * (t * ‖q w‖) ^ (∑ i, m i) = 1 := by + rw [Finset.prod_pow_eq_pow_sum, ← mul_pow, inv_mul_cancel₀ hR.ne', one_pow] + calc + _ ≤ (M * ∏ i, (t * ‖q w‖)⁻¹ ^ m i) * (t * ‖q w‖) ^ (∑ i, m i) := by + gcongr + _ = M := by rw [mul_assoc, hp, mul_one] + _ ≤ max M 0 := le_max_left _ _ + +/-- **Thullen's lemma, with a holomorphic radius bound.** For a Banach-valued function, +the Taylor series centered at a hull point converges locally uniformly on the indicated +polydisc and continues the original germ. The proof transfers uniform weighted Cauchy bounds +from compact families of smaller balls to the hull, then compares with a product of geometric +series. -/ +theorem taylor_continuation_on_holomorphicHull {U K : Set (Fin n → ℂ)} + (ho : IsOpen U) (hK : IsCompact K) (hKU : K ⊆ U) + {q : (Fin n → ℂ) → ℂ} {f : (Fin n → ℂ) → F} (hq : AnalyticOnNhd ℂ q U) + (hf : AnalyticOnNhd ℂ f U) + (hr : ∀ w ∈ K, ball w ‖q w‖ ⊆ U) {a : Fin n → ℂ} (ha : a ∈ holomorphicHull U K) : + AnalyticOnNhd ℂ (taylorSumAt f a) (ball a ‖q a‖) ∧ + taylorSumAt f a =ᶠ[𝓝 a] f ∧ + HasSumLocallyUniformlyOn + (fun (m : Fin n →₀ ℕ) z => (∏ i, (z i - a i) ^ m i) • holomorphicTaylorSeries f a m) + (taylorSumAt f a) (ball a ‖q a‖) := by + classical + have hbound {t : ℝ} (ht : 0 < t) (ht1 : t < 1) : + ∃ M : ℝ, 0 ≤ M ∧ ∀ m : Fin n →₀ ℕ, + ‖holomorphicTaylorSeries f a m‖ * (t * ‖q a‖) ^ (∑ i, m i) ≤ M := by + obtain ⟨M, hM0, hM⟩ := exists_bound_taylorCoeff_mul_radius hK hKU hq hf hr ht ht1 + refine ⟨M, hM0, fun m => ?_⟩ + have hg : AnalyticOnNhd ℂ + (fun w => ((t : ℂ) * q w) ^ (∑ i, m i) • holomorphicTaylorSeries f w m) U := + ((analyticOnNhd_const.mul hq).pow _).smul + (analyticOnNhd_const.smul (hf.iteratedPartialDeriv ho (multiIndexList m))) + have hnorm (w) : + ‖((t : ℂ) * q w) ^ (∑ i, m i) • holomorphicTaylorSeries f w m‖ = + ‖holomorphicTaylorSeries f w m‖ * (t * ‖q w‖) ^ (∑ i, m i) := by + rw [norm_smul, norm_pow, norm_mul, Complex.norm_of_nonneg ht.le, mul_comm] + exact (hnorm a) ▸ norm_le_on_holomorphicHull_vector hg + (fun w hw => (hnorm w).symm ▸ hM m w hw) a ha + have habs : ball (0 : Fin n → ℂ) ‖q a‖ ⊆ + powerSeriesAbsConvergenceSet (holomorphicTaylorSeries f a) := by + intro z hz + have hzq : ‖z‖ < ‖q a‖ := by simpa only [mem_ball, dist_zero_right] using hz + obtain ⟨r, hzr, hrq⟩ := exists_between hzq + have hr0 : 0 < r := (norm_nonneg z).trans_lt hzr + have hq0 : 0 < ‖q a‖ := hr0.trans hrq + obtain ⟨M, hM0, hM⟩ := hbound (div_pos hr0 hq0) ((div_lt_one hq0).mpr hrq) + simp only [div_mul_cancel₀ _ hq0.ne'] at hM + have hratio : ‖‖z‖ / r‖ < 1 := by + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (norm_nonneg _) hr0.le)] + exact (div_lt_one hr0).mpr hzr + have hsum := ((hasSum_pi_geometric (fun _ : Fin n => ‖z‖ / r) + (fun _ => hratio)).summable.mul_left M).comp_injective Finsupp.equivFunOnFinite.injective + apply hsum.of_nonneg_of_le (fun _ => by positivity) + intro m + calc + ‖holomorphicTaylorSeries f a m‖ * ∏ i, ‖z i‖ ^ m i ≤ + ‖holomorphicTaylorSeries f a m‖ * ∏ i, ‖z‖ ^ m i := by + gcongr + exact norm_le_pi_norm z _ + _ = (‖holomorphicTaylorSeries f a m‖ * r ^ (∑ i, m i)) * + ∏ i, (‖z‖ / r) ^ m i := by + rw [Finset.prod_pow_eq_pow_sum, Finset.prod_pow_eq_pow_sum, div_pow] + field_simp + _ ≤ M * ∏ i, (‖z‖ / r) ^ m i := by + apply mul_le_mul_of_nonneg_right (hM m) + positivity + have hdom : ball (0 : Fin n → ℂ) ‖q a‖ ⊆ + powerSeriesConvergenceDomain (holomorphicTaylorSeries f a) := + isOpen_ball.subset_interior_iff.mpr habs + have hmaps : MapsTo (fun z => z - a) (ball a ‖q a‖) + (powerSeriesConvergenceDomain (holomorphicTaylorSeries f a)) := by + intro z hz + apply hdom + simpa only [mem_ball, dist_zero_right, dist_eq_norm, sub_zero] using hz + refine ⟨(analyticOnNhd_powerSeriesSum _).comp + (analyticOnNhd_id.sub analyticOnNhd_const) hmaps, + taylorSumAt_eventuallyEq (hf a ha.1), ?_⟩ + have hs := (hasSumLocallyUniformlyOn_powerSeries (holomorphicTaylorSeries f a)).comp + (fun z => z - a) hmaps (continuous_id.sub continuous_const).continuousOn + unfold taylorSumAt + simpa only [HasSumLocallyUniformlyOn, Function.comp_def, Pi.sub_apply, + Finset.sum_apply] using hs + +/-- The constant-radius form of Thullen's continuation lemma, for Banach-valued functions. -/ +theorem exists_continuation_ball_of_mem_holomorphicHull {U K : Set (Fin n → ℂ)} + (ho : IsOpen U) (hK : IsCompact K) (hKU : K ⊆ U) {r : ℝ} (hr : 0 < r) + (hball : ∀ w ∈ K, ball w r ⊆ U) {a : Fin n → ℂ} (ha : a ∈ holomorphicHull U K) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (ball a r) ∧ g =ᶠ[𝓝 a] f := by + have hnorm : ‖(r : ℂ)‖ = r := Complex.norm_of_nonneg hr.le + have h := taylor_continuation_on_holomorphicHull ho hK hKU + (q := fun _ => (r : ℂ)) analyticOnNhd_const hf (by simpa only [hnorm] using hball) ha + exact ⟨taylorSumAt f a, by simpa only [hnorm] using h.1, h.2.1⟩ + +/-- On a domain of holomorphy, a ball supporting continuation of every germ at its center must lie +in the domain. The overlap is chosen uniformly, independently of the function. -/ +theorem IsDomainOfHolomorphy.ball_subset_of_continuation {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) {a : Fin n → ℂ} (ha : a ∈ U) + {r : ℝ} (hr : 0 < r) + (he : ∀ f : (Fin n → ℂ) → ℂ, AnalyticOnNhd ℂ f U → + ∃ g, AnalyticOnNhd ℂ g (ball a r) ∧ g =ᶠ[𝓝 a] f) : ball a r ⊆ U := by + obtain ⟨ε, hε, hεU⟩ := Metric.isOpen_iff.mp ho a ha + let W := ball a (min ε r) + have haW : a ∈ W := mem_ball_self (lt_min hε hr) + have hWU : W ⊆ U := (ball_subset_ball (min_le_left _ _)).trans hεU + have hWV : W ⊆ ball a r := ball_subset_ball (min_le_right _ _) + apply hU (ball a r) W isOpen_ball (isConnected_ball hr) isOpen_ball ⟨a, haW⟩ hWU hWV + intro f hf + obtain ⟨g, hg, heq⟩ := he f hf + exact ⟨g, hg, (hg.mono hWV).eqOn_of_preconnected_of_eventuallyEq + (hf.mono hWU) isPreconnected_ball haW heq⟩ + +/-- A domain of holomorphy preserves every radius bound supplied by a holomorphic function on a +compact set, by Thullen's continuation lemma. -/ +theorem IsDomainOfHolomorphy.holomorphic_radius_bound {U K : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) (hK : IsCompact K) (hKU : K ⊆ U) + {q : (Fin n → ℂ) → ℂ} (hq : AnalyticOnNhd ℂ q U) + (hr : ∀ w ∈ K, ball w ‖q w‖ ⊆ U) : + ∀ a ∈ holomorphicHull U K, ball a ‖q a‖ ⊆ U := by + intro a ha + by_cases hqa : ‖q a‖ = 0 + · simp [hqa] + · apply hU.ball_subset_of_continuation ho ha.1 (lt_of_le_of_ne (norm_nonneg _) (Ne.symm hqa)) + intro f hf + have h := taylor_continuation_on_holomorphicHull ho hK hKU hq hf hr ha + exact ⟨taylorSumAt f a, h.1, h.2.1⟩ + +/-- Domains of holomorphy preserve uniform polydisc radii on compact hulls. -/ +theorem IsDomainOfHolomorphy.hasHolomorphicHullRadiusProperty {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : HasHolomorphicHullRadiusProperty U := by + intro K hK hKU r hr hball a ha + exact hU.ball_subset_of_continuation ho ha.1 hr fun _ hf => + exists_continuation_ball_of_mem_holomorphicHull ho hK hKU hr hball ha hf + +/-- The boundary distance of a compact holomorphic hull equals that of the original compact set in a +domain of holomorphy. -/ +theorem IsDomainOfHolomorphy.hasHolomorphicHullDistanceProperty {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : HasHolomorphicHullDistanceProperty U := + (hU.hasHolomorphicHullRadiusProperty ho).hasHolomorphicHullDistanceProperty + +/-- **Cartan–Thullen, forward implication.** A domain of holomorphy is holomorphically +convex, by Thullen's Taylor continuation lemma and the hull-radius criterion. This coordinate +case supplies the proof for general finite-dimensional spaces below. -/ +private theorem IsDomainOfHolomorphy.isHolomorphicallyConvex_fin {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : IsHolomorphicallyConvex U := + (hU.hasHolomorphicHullRadiusProperty ho).isHolomorphicallyConvex ho + +/-- **Cartan–Thullen, forward implication.** An open domain of holomorphy in any +finite-dimensional complex normed space is holomorphically convex. Linear transport of hull +compactness is used here; no invariance of numerical boundary distance is asserted. -/ +theorem IsDomainOfHolomorphy.isHolomorphicallyConvex + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : + IsHolomorphicallyConvex U := by + let L := (Module.finBasis ℂ E).equivFunL + have h := (hU.image_equiv L).isHolomorphicallyConvex_fin + (L.toHomeomorph.isOpenMap U ho) + simpa only [Set.image_image, Function.comp_def, L.symm_apply_apply, Set.image_id'] using + h.image_equiv L.symm + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Transport.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Transport.lean new file mode 100644 index 0000000000..edde0d5d97 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity/Transport.lean @@ -0,0 +1,115 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull + +/-! +# Products and biholomorphic transport of holomorphic convexity + +Products preserve holomorphic convexity. Biholomorphic maps transport relative hulls exactly and +preserve holomorphic convexity of their open source and target. These results are proved +directly from the hull definition and compactness; they do not depend on Cartan–Thullen. + +References: [Range][Range1986] II §3.3; [Scheidemann][Scheidemann2005] §7.1; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] §2.7. + +## Main results + +`IsHolomorphicallyConvex.prod` is stability under products. `IsBiholomorphic.image_holomorphicHull` +transports relative hulls. `IsBiholomorphic.isHolomorphicallyConvex_iff` is invariance of +holomorphic convexity. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Products of holomorphically convex ambient sets are holomorphically convex. -/ +theorem IsHolomorphicallyConvex.prod {U : Set E} {V : Set F} + (hU : IsHolomorphicallyConvex U) (hV : IsHolomorphicallyConvex V) : + IsHolomorphicallyConvex (U ×ˢ V) := by + intro K hK hKU + have hfst : MapsTo (Prod.fst : E × F → E) (U ×ˢ V) U := fun _ hz => hz.1 + have hsnd : MapsTo (Prod.snd : E × F → F) (U ×ˢ V) V := fun _ hz => hz.2 + apply isCompact_holomorphicHull_of_subset_compact + ((hU _ (hK.image continuous_fst) (by rintro _ ⟨z, hz, rfl⟩; exact (hKU hz).1)).prod + (hV _ (hK.image continuous_snd) (by rintro _ ⟨z, hz, rfl⟩; exact (hKU hz).2))) + · rintro z ⟨hzU, hzV⟩ + exact ⟨hzU.1, hzV.1⟩ + · intro z hz + exact ⟨mapsTo_holomorphicHull analyticOnNhd_fst hfst hz, + mapsTo_holomorphicHull analyticOnNhd_snd hsnd hz⟩ + +variable [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +/-- Biholomorphic maps transport relative holomorphic hulls exactly. -/ +theorem IsBiholomorphic.image_holomorphicHull {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) {K : Set E} (hK : K ⊆ e.source) : + e '' holomorphicHull e.source K = holomorphicHull e.target (e '' K) := by + let := FiniteDimensional.complete ℂ E + let := FiniteDimensional.complete ℂ F + have hf := he.1.analyticOnNhd_of_finiteDimensional e.open_source + have hg := he.2.analyticOnNhd_of_finiteDimensional e.open_target + have hback : e.symm '' (e '' K) = K := by + ext x + constructor + · rintro ⟨_, ⟨z, hz, rfl⟩, rfl⟩ + simpa only [e.left_inv (hK hz)] using hz + · intro hx + exact ⟨e x, ⟨x, hx, rfl⟩, e.left_inv (hK hx)⟩ + apply Subset.antisymm + · rintro _ ⟨z, hz, rfl⟩ + exact mapsTo_holomorphicHull hf (fun _ hx => e.map_source hx) hz + · intro z hz + have h := mapsTo_holomorphicHull hg (fun _ hx => e.map_target hx) hz + rw [hback] at h + exact ⟨e.symm z, h, e.right_inv hz.1⟩ + +/-- Holomorphic convexity passes from the target of a biholomorphism to its source. -/ +theorem IsBiholomorphic.isHolomorphicallyConvex_source {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) (hV : IsHolomorphicallyConvex e.target) : + IsHolomorphicallyConvex e.source := by + intro K hK hKU + let := FiniteDimensional.complete ℂ E + let := FiniteDimensional.complete ℂ F + have hf := he.1.analyticOnNhd_of_finiteDimensional e.open_source + have hg := he.2.analyticOnNhd_of_finiteDimensional e.open_target + have himage : e '' K ⊆ e.target := by + rintro _ ⟨z, hz, rfl⟩ + exact e.map_source (hKU hz) + have hc := hV _ (hK.image_of_continuousOn (hf.continuousOn.mono hKU)) himage + apply isCompact_holomorphicHull_of_subset_compact + (hc.image_of_continuousOn (hg.continuousOn.mono (holomorphicHull_subset _ _))) + · rintro _ ⟨z, hz, rfl⟩ + exact e.map_target hz.1 + · intro z hz + exact ⟨e z, mapsTo_holomorphicHull hf (fun _ hx => e.map_source hx) hz, e.left_inv hz.1⟩ + +/-- Holomorphic convexity is invariant under biholomorphic equivalence of open sets. -/ +theorem IsBiholomorphic.isHolomorphicallyConvex_iff {e : OpenPartialHomeomorph E F} + (he : IsBiholomorphic e) : + IsHolomorphicallyConvex e.source ↔ IsHolomorphicallyConvex e.target := + ⟨fun h => he.symm.isHolomorphicallyConvex_source h, + fun h => he.isHolomorphicallyConvex_source h⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicLp.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicLp.lean new file mode 100644 index 0000000000..b0e327f96e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicLp.lean @@ -0,0 +1,243 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Constructions.Pi +public import Mathlib.MeasureTheory.Function.ConvergenceInMeasure +public import Mathlib.MeasureTheory.Function.L2Space +public import Mathlib.MeasureTheory.Function.LpSeminorm.CompareExp +public import Mathlib.MeasureTheory.Measure.Lebesgue.Complex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue + +/-! +# Holomorphic Lp spaces + +The holomorphic Lp space on an open subset of `ι → ℂ` is the submodule of Lebesgue Lp classes +admitting a holomorphic representative. Such a representative is unique on the open set. Complex +Banach targets and empty coordinate types are allowed. + +[Jakóbczak–Jarnicki][JakobczakJarnicki2021], Lemma 1.4.20 and Corollary 1.4.21, motivate the +local Lp estimate and completeness for `1 ≤ p ≤ ∞`. The local estimate follows from the volume +mean-value formula and Hölder's inequality. It yields closedness and completeness. For Hilbert +targets, the space at `p = 2` inherits Mathlib's L2 inner product, with its convention of +linearity in the second argument. No boundedness or connectedness of the open set is required. + +## Main definitions + +* `holomorphicLpSubmodule`: The Lp classes which have a holomorphic representative on the open set. +* `HolomorphicLp`: Holomorphic Lp functions, represented as a subspace of Mathlib's Lebesgue Lp + space. + +## Main results + +* `exists_norm_le_mul_Lp_norm`: **Local Lp estimate ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] + 1.4.20).** On each compact subset of an open set, values of a holomorphic representative are + bounded by a fixed multiple of the norm of its Lp class. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public section + +open Filter Set MeasureTheory Metric +open scoped ENNReal Topology + +namespace SeveralComplexVariables + +variable {ι F : Type*} [Fintype ι] [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The Lp classes which have a holomorphic representative on the open set. -/ +@[expose] def holomorphicLpSubmodule (U : TopologicalSpace.Opens (ι → ℂ)) (p : ℝ≥0∞) : + Submodule ℂ (Lp F p (volume.restrict (U : Set (ι → ℂ)))) where + carrier := {u | ∃ f : (ι → ℂ) → F, DifferentiableOn ℂ f U ∧ + f =ᵐ[volume.restrict (U : Set (ι → ℂ))] u} + zero_mem' := ⟨0, differentiableOn_const 0, (Lp.coeFn_zero F p _).symm⟩ + add_mem' := by + rintro u v ⟨f, hf, he⟩ ⟨g, hg, he'⟩ + exact ⟨f + g, hf.add hg, (he.add he').trans (Lp.coeFn_add u v).symm⟩ + smul_mem' := by + rintro c u ⟨f, hf, he⟩ + exact ⟨c • f, hf.const_smul c, (he.const_smul c).trans (Lp.coeFn_smul c u).symm⟩ + +/-- Holomorphic Lp functions, represented as a subspace of Mathlib's Lebesgue Lp space. For `1 ≤ p` +the norm and complex normed-space structure are inherited from Lp. -/ +abbrev HolomorphicLp (U : TopologicalSpace.Opens (ι → ℂ)) (F : Type*) + [NormedAddCommGroup F] [NormedSpace ℂ F] (p : ℝ≥0∞) : Type _ := + ↥(holomorphicLpSubmodule (F := F) U p) + +/-- Every element of the holomorphic Lp subspace has a holomorphic representative. -/ +theorem HolomorphicLp.exists_representative {U : TopologicalSpace.Opens (ι → ℂ)} + {p : ℝ≥0∞} (u : HolomorphicLp U F p) : + ∃ f : (ι → ℂ) → F, DifferentiableOn ℂ f U ∧ + f =ᵐ[volume.restrict (U : Set (ι → ℂ))] (u.val : Lp F p _) := u.property + +/-- Holomorphic representatives of the same Lp class agree everywhere on the open set. -/ +theorem holomorphicLp_representative_unique {U : TopologicalSpace.Opens (ι → ℂ)} + {p : ℝ≥0∞} {u : Lp F p (volume.restrict (U : Set (ι → ℂ)))} + {f g : (ι → ℂ) → F} (hf : DifferentiableOn ℂ f U) (hg : DifferentiableOn ℂ g U) + (he : f =ᵐ[volume.restrict (U : Set (ι → ℂ))] u) + (he' : g =ᵐ[volume.restrict (U : Set (ι → ℂ))] u) : EqOn f g U := + Measure.eqOn_open_of_ae_eq (he.trans he'.symm) U.isOpen hf.continuousOn hg.continuousOn + +variable [CompleteSpace F] + +/-- The volume mean-value formula and Hölder's inequality bound the center value by the global Lp +norm. Only holomorphy on the closed polydisc is needed here. -/ +theorem volume_mul_norm_le_Lp_norm (U : TopologicalSpace.Opens (ι → ℂ)) + (p : ℝ≥0∞) [Fact (1 ≤ p)] {c : ι → ℂ} {r : ℝ} (hr : 0 < r) + (hBU : closedBall c r ⊆ U) + (u : Lp F p (volume.restrict (U : Set (ι → ℂ)))) {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f (closedBall c r)) + (he : f =ᵐ[volume.restrict (U : Set (ι → ℂ))] u) : + volume.real (closedBall c r) * ‖f c‖ ≤ + ‖u‖ * volume.real (closedBall c r) ^ (1 - 1 / p.toReal) := by + let μ := volume.restrict (closedBall c r) + have hmeas : AEStronglyMeasurable f μ := + (hf.continuousOn.integrableOn_compact (isCompact_closedBall _ _)).aestronglyMeasurable + have hpu : eLpNorm f p μ ≤ eLpNorm u p (volume.restrict (U : Set (ι → ℂ))) := by + rw [← eLpNorm_congr_ae he] + exact eLpNorm_mono_measure f (Measure.restrict_mono hBU le_rfl) + have hvol0 := (measure_closedBall_pos (volume : Measure (ι → ℂ)) c hr).ne' + have hvoltop : volume (closedBall c r) ≠ ∞ := measure_closedBall_lt_top.ne + have hh : eLpNorm f 1 μ ≤ eLpNorm u p (volume.restrict (U : Set (ι → ℂ))) * + volume (closedBall c r) ^ (1 - 1 / p.toReal) := by + have h := eLpNorm_le_eLpNorm_mul_rpow_measure_univ (Fact.out : 1 ≤ p) hmeas + simp only [ENNReal.toReal_one, div_one, μ, Measure.restrict_apply_univ] at h + exact h.trans (mul_le_mul' hpu le_rfl) + have hfinite : eLpNorm u p (volume.restrict (U : Set (ι → ℂ))) * + volume (closedBall c r) ^ (1 - 1 / p.toReal) ≠ ∞ := + ENNReal.mul_ne_top (Lp.eLpNorm_ne_top u) (ENNReal.rpow_ne_top_of_ne_zero hvol0 hvoltop) + have hreal := ENNReal.toReal_mono hfinite hh + rw [ENNReal.toReal_mul, ← ENNReal.toReal_rpow, ← Lp.norm_def] at hreal + calc + volume.real (closedBall c r) * ‖f c‖ = ‖∫ z in closedBall c r, f z‖ := by + rw [integral_closedBall_eq_volume_smul hf, norm_smul, Real.norm_eq_abs, + abs_of_nonneg (show 0 ≤ volume.real (closedBall c r) from ENNReal.toReal_nonneg)] + _ ≤ ∫ z in closedBall c r, ‖f z‖ := norm_integral_le_integral_norm _ + _ = (eLpNorm f 1 μ).toReal := by + rw [eLpNorm_one_eq_lintegral_enorm hmeas] + exact integral_norm_eq_lintegral_enorm hmeas + _ ≤ ‖u‖ * volume.real (closedBall c r) ^ (1 - 1 / p.toReal) := hreal + +/-- **Local Lp estimate ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.4.20).** On each compact +subset of an +open set, values of a holomorphic representative are bounded by a fixed multiple of +the norm of its Lp class. A uniform polydisc radius, the volume mean-value formula, +and Hölder's inequality give a constant independent of the representative. -/ +theorem exists_norm_le_mul_Lp_norm (U : TopologicalSpace.Opens (ι → ℂ)) + (p : ℝ≥0∞) [Fact (1 ≤ p)] + {K : Set (ι → ℂ)} (hKU : K ⊆ U) (hK : IsCompact K) : + ∃ C : ℝ, 0 < C ∧ ∀ (u : Lp F p (volume.restrict (U : Set (ι → ℂ)))) + (f : (ι → ℂ) → F), DifferentiableOn ℂ f U → + f =ᵐ[volume.restrict (U : Set (ι → ℂ))] u → + ∀ z ∈ K, ‖f z‖ ≤ C * ‖u‖ := by + obtain ⟨r, hr, hsub⟩ := hK.exists_cthickening_subset_open U.isOpen hKU + let v := volume.real (closedBall (0 : ι → ℂ) r) + have hv : 0 < v := ENNReal.toReal_pos + (measure_closedBall_pos (volume : Measure (ι → ℂ)) 0 hr).ne' + measure_closedBall_lt_top.ne + refine ⟨v ^ (1 - 1 / p.toReal) / v, div_pos (Real.rpow_pos_of_pos hv _) hv, ?_⟩ + intro u f hf he z hz + have hBU : closedBall z r ⊆ U := (closedBall_subset_cthickening hz r).trans hsub + have hbound := volume_mul_norm_le_Lp_norm U p hr hBU u + ((hf.analyticOnNhd_of_finiteDimensional U.isOpen).mono hBU) he + have hvol : volume.real (closedBall z r) = v := by + have hpre : (fun w : ι → ℂ => z + w) ⁻¹' closedBall z r = closedBall 0 r := by + ext w + simp [mem_closedBall, dist_eq_norm] + dsimp [v, Measure.real] + rw [← hpre, measure_preimage_add] + rw [hvol] at hbound + calc + ‖f z‖ ≤ (‖u‖ * v ^ (1 - 1 / p.toReal)) / v := + (le_div_iff₀ hv).mpr (by simpa only [mul_comm] using hbound) + _ = v ^ (1 - 1 / p.toReal) / v * ‖u‖ := by ring + +/-- An Lp-convergent sequence of holomorphic representatives converges locally uniformly on the open +set to a holomorphic representative of its Lp limit. This uses the local Lp estimate; in +particular, no global finite-measure hypothesis is needed. -/ +theorem exists_holomorphic_representative_of_tendsto_Lp + {U : TopologicalSpace.Opens (ι → ℂ)} {p : ℝ≥0∞} [Fact (1 ≤ p)] + {u : ℕ → Lp F p (volume.restrict (U : Set (ι → ℂ)))} + {v : Lp F p (volume.restrict (U : Set (ι → ℂ)))} + {f : ℕ → (ι → ℂ) → F} (hf : ∀ n, DifferentiableOn ℂ (f n) U) + (he : ∀ n, f n =ᵐ[volume.restrict (U : Set (ι → ℂ))] u n) + (hu : Tendsto u atTop (𝓝 v)) : + ∃ g : (ι → ℂ) → F, DifferentiableOn ℂ g U ∧ + g =ᵐ[volume.restrict (U : Set (ι → ℂ))] v ∧ + TendstoLocallyUniformlyOn f g atTop U := by + classical + have hc : ∀ K ⊆ (U : Set (ι → ℂ)), IsCompact K → UniformCauchySeqOn f atTop K := by + intro K hKU hK + obtain ⟨C, hC, hbound⟩ := exists_norm_le_mul_Lp_norm (F := F) U p hKU hK + rw [Metric.uniformCauchySeqOn_iff] + intro ε hε + obtain ⟨N, hN⟩ := Metric.cauchySeq_iff.mp hu.cauchySeq (ε / C) (div_pos hε hC) + refine ⟨N, fun m hm n hn z hz => ?_⟩ + have hb := hbound (u m - u n) (f m - f n) ((hf m).sub (hf n)) + (((he m).sub (he n)).trans (Lp.coeFn_sub _ _).symm) z hz + rw [dist_eq_norm] + have hdist := hN m hm n hn + rw [dist_eq_norm] at hdist + exact hb.trans_lt ((lt_div_iff₀' hC).mp hdist) + have hex : ∀ z : U, ∃ y : F, Tendsto (fun n => f n z) atTop (𝓝 y) := by + intro z + exact cauchySeq_tendsto_of_complete + ((hc {z.val} (singleton_subset_iff.mpr z.property) isCompact_singleton).cauchySeq + (mem_singleton z.val)) + choose g hg using hex + let G : (ι → ℂ) → F := fun z => if hz : z ∈ U then g ⟨z, hz⟩ else 0 + have hG : ∀ z ∈ U, Tendsto (fun n => f n z) atTop (𝓝 (G z)) := by + intro z hz + simpa only [G, dite_eq_left hz] using hg ⟨z, hz⟩ + have hloc : TendstoLocallyUniformlyOn f G atTop U := by + rw [tendstoLocallyUniformlyOn_iff_forall_isCompact U.isOpen] + intro K hKU hK + exact (hc K hKU hK).tendstoUniformlyOn_of_tendsto fun z hz => hG z (hKU hz) + refine ⟨G, (hloc.analyticOnNhd_pi + (.of_forall fun n => (hf n).analyticOnNhd_of_finiteDimensional U.isOpen) + U.isOpen).differentiableOn, ?_, hloc⟩ + obtain ⟨φ, hφ, hv⟩ := (tendstoInMeasure_of_tendsto_Lp hu).exists_seq_tendsto_ae + filter_upwards [hv, ae_all_iff.mpr he, ae_restrict_mem U.isOpen.measurableSet] with z hz hez hzU + have ht : Tendsto (fun n => u (φ n) z) atTop (𝓝 (G z)) := by + simpa only [Function.comp_def, ← hez] using (hG z hzU).comp hφ.tendsto_atTop + exact tendsto_nhds_unique ht hz + +/-- The holomorphic Lp submodule is closed for `1 ≤ p ≤ ∞`, by the local Lp estimate and Weierstrass +convergence. -/ +theorem isClosed_holomorphicLpSubmodule (U : TopologicalSpace.Opens (ι → ℂ)) + (p : ℝ≥0∞) [Fact (1 ≤ p)] : + IsClosed (holomorphicLpSubmodule (F := F) U p : Set (Lp F p + (volume.restrict (U : Set (ι → ℂ))))) := by + apply isSeqClosed_iff_isClosed.mp + intro u v hu hv + choose f hf he using hu + obtain ⟨g, hg, heq, _⟩ := exists_holomorphic_representative_of_tendsto_Lp hf he hv + exact ⟨g, hg, heq⟩ + +/-- **[Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.4.21.** Holomorphic Lp is a complex Banach space +for +`1 ≤ p ≤ ∞`. Completeness follows from closedness in Mathlib's complete Lp space. -/ +instance (U : TopologicalSpace.Opens (ι → ℂ)) (p : ℝ≥0∞) + [Fact (1 ≤ p)] : CompleteSpace (HolomorphicLp U F p) := + (isClosed_holomorphicLpSubmodule (F := F) U p).isComplete.completeSpace_coe + +/-- Holomorphic L2 inherits the integral inner product of Mathlib's L2 space. Together with +completeness this gives Corollary 1.4.21's Hilbert-space assertion, including Hilbert-valued +functions and Mathlib's linear-in-the-second-argument convention. -/ +theorem holomorphicL2_inner {H : Type*} [NormedAddCommGroup H] [InnerProductSpace ℂ H] + {U : TopologicalSpace.Opens (ι → ℂ)} (f g : HolomorphicLp U H 2) : + inner ℂ f g = ∫ z, inner ℂ (f.val z) (g.val z) + ∂volume.restrict (U : Set (ι → ℂ)) := + L2.inner_def f.val g.val + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IdentityPrinciple.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IdentityPrinciple.lean new file mode 100644 index 0000000000..f5cfd56923 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IdentityPrinciple.lean @@ -0,0 +1,76 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# The identity theorem for holomorphic functions in several variables + +Holomorphic maps on a preconnected open subset of a finite-dimensional complex normed space +agree everywhere if they agree near one point, equivalently on a nonempty open subset. The +target may be a complex Banach space. The proofs use the project's holomorphic–analytic +equivalence and Mathlib's analytic identity principle. + +`DifferentiableOn.eqOn_of_preconnected_of_eqOn` is +[Fritzsche–Grauert][FritzscheGrauert2002] (2002), I.4.10, p. 22, +with Banach-valued targets. Finite coordinate spaces `ι → ℂ` are covered as finite-dimensional +spaces, including empty coordinate types. The agreement set must be nonempty; agreement merely on a +set with a cluster point does not suffice in several variables. + +## Main results + +* `DifferentiableOn.eqOn_of_preconnected_of_eqOn`: **Identity theorem + ([Fritzsche–Grauert][FritzscheGrauert2002] I.4.10).** Two holomorphic maps on an open, + preconnected set agree everywhere if they agree on a nonempty open subset. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +-/ + +public section + +open Set Filter +open scoped Topology + +namespace DifferentiableOn + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The holomorphic identity principle from equality near one point of an open, preconnected set. +The target may be any complex Banach space. -/ +theorem eqOn_of_preconnected_of_eventuallyEq {U : Set E} (hU : IsOpen U) + (hconn : IsPreconnected U) {f g : E → F} + (hf : DifferentiableOn ℂ f U) (hg : DifferentiableOn ℂ g U) + {a : E} (ha : a ∈ U) (heq : f =ᶠ[𝓝 a] g) : EqOn f g U := + (hf.analyticOnNhd_of_finiteDimensional hU).eqOn_of_preconnected_of_eventuallyEq + (hg.analyticOnNhd_of_finiteDimensional hU) hconn ha heq + +/-- **Identity theorem ([Fritzsche–Grauert][FritzscheGrauert2002] I.4.10).** Two holomorphic maps on +an open, preconnected set agree everywhere if they agree on a nonempty open subset. -/ +theorem eqOn_of_preconnected_of_eqOn {U V : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) + {f g : E → F} (hf : DifferentiableOn ℂ f U) (hg : DifferentiableOn ℂ g U) + (hV : IsOpen V) (hne : V.Nonempty) (hVU : V ⊆ U) (heq : EqOn f g V) : + EqOn f g U := by + obtain ⟨a, ha⟩ := hne + exact hf.eqOn_of_preconnected_of_eventuallyEq hU hconn hg (hVU ha) + (Filter.mem_of_superset (hV.mem_nhds ha) (fun _ hx => heq hx)) + +/-- A holomorphic map vanishing on a nonempty open subset vanishes throughout the open, preconnected +domain. -/ +theorem eqOn_zero_of_preconnected_of_eqOn_zero {U V : Set E} (hU : IsOpen U) + (hconn : IsPreconnected U) + {f : E → F} (hf : DifferentiableOn ℂ f U) + (hV : IsOpen V) (hne : V.Nonempty) (hVU : V ⊆ U) (heq : EqOn f 0 V) : + EqOn f 0 U := + hf.eqOn_of_preconnected_of_eqOn hU hconn (differentiableOn_const 0) hV hne hVU heq + +end DifferentiableOn + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitGraph.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitGraph.lean new file mode 100644 index 0000000000..88ef9c82ca --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitGraph.lean @@ -0,0 +1,56 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph + +/-! +# Local zero sets as graphs + +The implicit mapping theorem supplies a homeomorphism from a regular local zero set to the +parameter neighborhood. This is an elementary statement about subsets of product spaces, without +a manifold or analytic-space structure. Reference: [Scheidemann][Scheidemann2005] (2005), +Corollary 3.1.5. + +## Main results + +`Homeomorph.implicitGraph` is the local graph homeomorphism of a regular zero set in a product. +`exists_implicit_zero_homeomorph` packages existence of that homeomorphism from the implicit +mapping theorem. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set + +namespace SeveralComplexVariables + +variable {P Q R : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] + [NormedAddCommGroup Q] [NormedSpace ℂ Q] [NormedAddCommGroup R] [NormedSpace ℂ R] + +/-- Near a regular zero, projection identifies the zero set homeomorphically with an open parameter +neighborhood. This retains the analytic graph and its explicit projection. -/ +theorem exists_implicit_zero_homeomorph [FiniteDimensional ℂ P] [FiniteDimensional ℂ Q] + [CompleteSpace R] {D : Set (P × Q)} (hD : IsOpen D) + {f : P × Q → R} (hf : DifferentiableOn ℂ f D) {a : P} {b : Q} + (hab : (a, b) ∈ D) (hz : f (a, b) = 0) + (hi : ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).IsInvertible) : + ∃ (U : Set P) (V : Set Q), IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + ∃ e : {p : P × Q // p ∈ U ×ˢ V ∧ f p = 0} ≃ₜ U, + ∀ p, (e p).val = p.val.1 := by + obtain ⟨U, V, g, hU, ha, hV, hb, hsub, hg, hm, _, hgraph⟩ := + exists_holomorphic_implicit_zero hD hf hab hz hi + exact ⟨U, V, hU, ha, hV, hb, hsub, Homeomorph.implicitGraph hg.continuousOn hm hgraph, + fun _ => rfl⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitMapping.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitMapping.lean new file mode 100644 index 0000000000..5f38fe1681 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ImplicitMapping.lean @@ -0,0 +1,152 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.ImplicitContDiff +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph + +/-! +# Holomorphic implicit mappings + +For `f : P × Q → R`, invertibility of the derivative in the `Q` variable gives a local +holomorphic solution `y = g x` of the level equation `f (x, y) = f (a, b)`. The conclusion uses +open product neighborhoods inside the original domain, includes uniqueness of every solution +there, and identifies the derivative of `g`. + +The analytic theorem works in complex Banach spaces. The holomorphic version uses the project's +finite-dimensional holomorphic–analytic equivalence. No connectedness assumptions or positive +dimension restrictions are imposed; zero-dimensional parameter spaces include isolated +solutions. We reuse Mathlib's implicit function theorem at regularity `ω`. + +Reference: [Range][Range1986] (1986), I §2.3, Theorem 2.4. + +## Main results + +* `exists_analytic_implicit_mapping`: **Analytic implicit mapping theorem.** Near a point where the + partial derivative in the second variable is invertible, the level set is precisely an analytic + graph. +* `exists_holomorphic_implicit_mapping`: **Holomorphic implicit mapping theorem.** The level set of + a holomorphic map with invertible partial derivative is locally a unique holomorphic graph. + +## References + +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology ContDiff + +namespace SeveralComplexVariables + +variable {P Q R : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] + [NormedAddCommGroup Q] [NormedSpace ℂ Q] [NormedAddCommGroup R] [NormedSpace ℂ R] + +section Analytic + +variable [CompleteSpace P] [CompleteSpace Q] [CompleteSpace R] + +/-- **Analytic implicit mapping theorem.** Near a point where the partial derivative +in the second variable is invertible, the level set is precisely an analytic graph. +Both neighborhoods lie in the supplied domain, and the derivative is `-(D₂f)⁻¹ ∘ D₁f`. -/ +theorem exists_analytic_implicit_mapping {D : Set (P × Q)} (hD : IsOpen D) + {f : P × Q → R} {a : P} {b : Q} (hab : (a, b) ∈ D) + (hf : AnalyticAt ℂ f (a, b)) + (hi : ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).IsInvertible) : + ∃ (U : Set P) (V : Set Q) (g : P → Q), + IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + AnalyticOnNhd ℂ g U ∧ MapsTo g U V ∧ g a = b ∧ + HasFDerivAt g + (-((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).inverse |>.comp + ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inl ℂ P Q))) a ∧ + ∀ x ∈ U, ∀ y ∈ V, f (x, y) = f (a, b) ↔ y = g x := by + have hc : ContDiffAt ℂ ω f (a, b) := hf.contDiffAt + let g := hc.implicitFunction (by simp) hi + have hga : g a = b := hc.implicitFunction_apply_self (by simp) hi + have hg : AnalyticAt ℂ g a := (hc.contDiffAt_implicitFunction (by simp) hi).analyticAt + have heq : ∀ᶠ p in 𝓝 (a, b), f p = f (a, b) ↔ g p.1 = p.2 := + hc.eventually_apply_eq_iff_implicitFunction (by simp) hi + obtain ⟨U₀, V, hU₀, ha₀, hV, hb, hsub⟩ := + mem_nhds_prod_iff'.mp (inter_mem (hD.mem_nhds hab) heq) + have hgV : g ⁻¹' V ∈ 𝓝 a := + hg.continuousAt.preimage_mem_nhds (hga.symm ▸ hV.mem_nhds hb) + obtain ⟨U, hUU, hU, ha⟩ := mem_nhds_iff.mp + (inter_mem (inter_mem (hU₀.mem_nhds ha₀) hg.eventually_analyticAt) hgV) + refine ⟨U, V, g, hU, ha, hV, hb, ?_, ?_, ?_, hga, ?_, ?_⟩ + · exact fun p hp => (hsub ⟨(hUU hp.1).1.1, hp.2⟩).1 + · exact fun x hx => (hUU hx).1.2 + · exact fun x hx => (hUU hx).2 + · exact (hc.hasStrictFDerivAt_implicitFunction (by simp) hi).hasFDerivAt + · intro x hx y hy + exact (hsub ⟨(hUU hx).1.1, hy⟩).2.trans eq_comm + +end Analytic + +section Holomorphic + +variable [FiniteDimensional ℂ P] [FiniteDimensional ℂ Q] [CompleteSpace R] + +/-- **Holomorphic implicit mapping theorem.** The level set of a holomorphic map +with invertible partial derivative is locally a unique holomorphic graph. +The target may be a complex Banach space; invertibility supplies the required dimension match. -/ +theorem exists_holomorphic_implicit_mapping {D : Set (P × Q)} (hD : IsOpen D) + {f : P × Q → R} (hf : DifferentiableOn ℂ f D) {a : P} {b : Q} + (hab : (a, b) ∈ D) + (hi : ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).IsInvertible) : + ∃ (U : Set P) (V : Set Q) (g : P → Q), + IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + DifferentiableOn ℂ g U ∧ MapsTo g U V ∧ g a = b ∧ + HasFDerivAt g + (-((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).inverse |>.comp + ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inl ℂ P Q))) a ∧ + ∀ x ∈ U, ∀ y ∈ V, f (x, y) = f (a, b) ↔ y = g x := by + let := FiniteDimensional.complete ℂ P + let := FiniteDimensional.complete ℂ Q + obtain ⟨U, V, g, hU, ha, hV, hb, hsub, hg, hm, hga, hd, heq⟩ := + exists_analytic_implicit_mapping hD hab (hf.analyticOnNhd_of_finiteDimensional hD _ hab) hi + exact ⟨U, V, g, hU, ha, hV, hb, hsub, hg.differentiableOn, hm, hga, hd, heq⟩ + +/-- [Range][Range1986]'s zero-set formulation: near a regular zero the zero set is a holomorphic +graph. -/ +theorem exists_holomorphic_implicit_zero {D : Set (P × Q)} (hD : IsOpen D) + {f : P × Q → R} (hf : DifferentiableOn ℂ f D) {a : P} {b : Q} + (hab : (a, b) ∈ D) (hzero : f (a, b) = 0) + (hi : ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).IsInvertible) : + ∃ (U : Set P) (V : Set Q) (g : P → Q), + IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + DifferentiableOn ℂ g U ∧ MapsTo g U V ∧ g a = b ∧ + ∀ x ∈ U, ∀ y ∈ V, f (x, y) = 0 ↔ y = g x := by + obtain ⟨U, V, g, hU, ha, hV, hb, hsub, hg, hm, hga, _, heq⟩ := + exists_holomorphic_implicit_mapping hD hf hab hi + exact ⟨U, V, g, hU, ha, hV, hb, hsub, hg, hm, hga, by simpa only [hzero] using heq⟩ + +end Holomorphic + +/-- The determinant-of-a-minor formulation of the implicit mapping theorem. The chosen coordinates +are the second factor; their Jacobian is the Jacobian of the corresponding slice. -/ +theorem exists_holomorphic_implicit_zero_of_det [FiniteDimensional ℂ P] + {ι : Type*} [Fintype ι] [DecidableEq ι] {D : Set (P × (ι → ℂ))} (hD : IsOpen D) + {f : P × (ι → ℂ) → (ι → ℂ)} (hf : DifferentiableOn ℂ f D) + {a : P} {b : ι → ℂ} (hab : (a, b) ∈ D) (hzero : f (a, b) = 0) + (hdet : (complexJacobian (fun y => f (a, y)) b).det ≠ 0) : + ∃ (U : Set P) (V : Set (ι → ℂ)) (g : P → (ι → ℂ)), + IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + DifferentiableOn ℂ g U ∧ MapsTo g U V ∧ g a = b ∧ + ∀ x ∈ U, ∀ y ∈ V, f (x, y) = 0 ↔ y = g x := by + have hd := ((hf (a, b) hab).differentiableAt (hD.mem_nhds hab)).hasFDerivAt + have hs := hd.comp b (hasFDerivAt_prodMk_right a b (𝕜 := ℂ)) + apply exists_holomorphic_implicit_zero hD hf hab hzero + have hi := (det_complexJacobian_ne_zero_iff hs.differentiableAt).mp hdet + rwa [hs.fderiv] at hi + + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping.lean new file mode 100644 index 0000000000..b2f6b27f55 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping.lean @@ -0,0 +1,144 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet + +/-! +# Injective holomorphic maps in equal dimensions + +An injective holomorphic map between equal-dimensional finite-dimensional complex spaces has +invertible derivative and is biholomorphic onto its open image. No connectedness or nonemptiness +is required. The critical-set argument proves nonsingularity; the inverse mapping theorem then +gives the global inverse onto the image. Supporting modules separate one-variable +nonsingularity, immersion points, the codimension-one reduction, and exclusion of the critical +set. + +Reference: [Fritzsche–Grauert][FritzscheGrauert2002] I, Theorem 8.5 and Corollary 8.6. + +## Main results + +`isInvertible_fderiv_of_injOn` is nonsingularity of an injective holomorphic map in equal +dimensions. `exists_biholomorphic_of_injOn` produces a biholomorphism onto the image. +`isOpen_image_of_holomorphic_injOn` is openness of the image. `det_complexJacobian_ne_zero_of_injOn` +is the Jacobian form in coordinates. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +/-- An injective holomorphic map in equal dimensions has invertible complex derivative. Equal +dimensions are essential: an injective parametrization of a cusp can have zero derivative. The +proof includes dimension zero and arbitrary finite-dimensional complex normed spaces. -/ +theorem isInvertible_fderiv_of_injOn (hdim : Module.finrank ℂ E = Module.finrank ℂ F) + {U : Set E} (hU : IsOpen U) {f : E → F} (hf : DifferentiableOn ℂ f U) + (hi : InjOn f U) {a : E} (ha : a ∈ U) : (fderiv ℂ f a).IsInvertible := by + let n := Module.finrank ℂ E + let A : E ≃L[ℂ] (Fin n → ℂ) := (Module.finBasis ℂ E).equivFunL + let B : F ≃L[ℂ] (Fin n → ℂ) := ContinuousLinearEquiv.ofFinrankEq (by simpa [n] using hdim.symm) + let g := B ∘ f ∘ A.symm + let V := A.symm ⁻¹' U + have hV : IsOpen V := hU.preimage A.symm.continuous + have hg : DifferentiableOn ℂ g V := + B.differentiable.comp_differentiableOn + (hf.comp A.symm.differentiable.differentiableOn (fun _ hz => hz)) + have hgi : InjOn g V := by + intro z hz w hw he + apply A.symm.injective + exact hi hz hw (B.injective he) + have haV : A a ∈ V := by simpa [V] + obtain ⟨T, hT⟩ := isInvertible_fderiv_of_injOn_coordinates hV hg hgi haV + have hda : fderiv ℂ g (A a) = + B.toContinuousLinearMap.comp ((fderiv ℂ f a).comp A.symm.toContinuousLinearMap) := by + have hfa : HasFDerivAt f (fderiv ℂ f a) (A.symm (A a)) := by + simpa only [A.symm_apply_apply] using + ((hf a ha).differentiableAt (hU.mem_nhds ha)).hasFDerivAt + exact (B.hasFDerivAt.comp (A a) (hfa.comp (A a) A.symm.hasFDerivAt)).fderiv + refine ⟨A.trans (T.trans B.symm), ?_⟩ + ext v + change B.symm (T (A v)) = (fderiv ℂ f a) v + apply B.injective + have he := DFunLike.congr_fun hT (A v) + simpa only [hda, ContinuousLinearMap.comp_apply, ContinuousLinearEquiv.coe_coe, + A.symm_apply_apply, B.apply_symm_apply] using he + +/-- An injective holomorphic map between equal-dimensional spaces gives a biholomorphic map with +source exactly `U` and target exactly its image. This follows from nonsingularity. -/ +theorem exists_biholomorphic_of_injOn (hdim : Module.finrank ℂ E = Module.finrank ℂ F) + {U : Set E} (hU : IsOpen U) {f : E → F} (hf : DifferentiableOn ℂ f U) + (hi : InjOn f U) : + ∃ e : OpenPartialHomeomorph E F, IsBiholomorphic e ∧ e.source = U ∧ + e.target = f '' U ∧ (e : E → F) = f := by + let g := Function.invFunOn f U + have hlocal : ∀ a ∈ U, ∃ e : OpenPartialHomeomorph E F, IsBiholomorphic e ∧ + a ∈ e.source ∧ e.source ⊆ U ∧ (e : E → F) = f := fun a ha => + exists_biholomorphic_of_isInvertible_fderiv hU hf ha + (isInvertible_fderiv_of_injOn hdim hU hf hi ha) + have ho : IsOpen (f '' U) := by + rw [isOpen_iff_mem_nhds] + rintro y ⟨a, ha, rfl⟩ + obtain ⟨e, _, hae, heU, heq⟩ := hlocal a ha + have htar : e.target ⊆ f '' U := by + intro z hz + exact ⟨e.symm z, heU (e.map_target hz), by rw [← heq]; exact e.right_inv hz⟩ + exact mem_of_superset (e.open_target.mem_nhds (by rw [← heq]; exact e.map_source hae)) htar + have hg : DifferentiableOn ℂ g (f '' U) := by + rintro y ⟨a, ha, rfl⟩ + obtain ⟨e, he, hae, heU, heq⟩ := hlocal a ha + have hfa : f a ∈ e.target := by rw [← heq]; exact e.map_source hae + have heqg : g =ᶠ[𝓝 (f a)] e.symm := by + filter_upwards [e.open_target.mem_nhds hfa] with z hz + have hzU : z ∈ f '' U := ⟨e.symm z, heU (e.map_target hz), + by rw [← heq]; exact e.right_inv hz⟩ + apply hi (Function.invFunOn_mem hzU) (heU (e.map_target hz)) + exact (Function.invFunOn_eq hzU).trans (by rw [← heq]; exact (e.right_inv hz).symm) + exact ((he.symm.differentiableAt hfa).congr_of_eventuallyEq heqg).differentiableWithinAt + let e : OpenPartialHomeomorph E F := + { toFun := f + invFun := g + source := U + target := f '' U + map_source' := fun x hx => mem_image_of_mem f hx + map_target' := fun y hy => Function.invFunOn_mem hy + left_inv' := hi.leftInvOn_invFunOn + right_inv' := fun y hy => Function.invFunOn_eq hy + open_source := hU + open_target := ho + continuousOn_toFun := hf.continuousOn + continuousOn_invFun := hg.continuousOn } + exact ⟨e, ⟨hf, hg⟩, rfl, rfl, rfl⟩ + +/-- The image of an injective holomorphic map in equal dimensions is open. -/ +theorem isOpen_image_of_holomorphic_injOn (hdim : Module.finrank ℂ E = Module.finrank ℂ F) + {U : Set E} (hU : IsOpen U) {f : E → F} (hf : DifferentiableOn ℂ f U) + (hi : InjOn f U) : IsOpen (f '' U) := by + obtain ⟨e, _, _, ht, _⟩ := exists_biholomorphic_of_injOn hdim hU hf hi + exact ht ▸ e.open_target + +/-- The coordinate Jacobian determinant of an injective holomorphic map never vanishes. -/ +theorem det_complexJacobian_ne_zero_of_injOn {ι : Type*} [Fintype ι] [DecidableEq ι] + {U : Set (ι → ℂ)} (hU : IsOpen U) {f : (ι → ℂ) → (ι → ℂ)} + (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) {a : ι → ℂ} (ha : a ∈ U) : + (complexJacobian f a).det ≠ 0 := + (det_complexJacobian_ne_zero_iff ((hf a ha).differentiableAt (hU.mem_nhds ha))).mpr + (isInvertible_fderiv_of_injOn rfl hU hf hi ha) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CorankOne.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CorankOne.lean new file mode 100644 index 0000000000..163e0c4af9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CorankOne.lean @@ -0,0 +1,194 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable + +/-! +# Nonsingularity in the presence of an invertible transverse minor + +The implicit function theorem reduces an injective map to an injective scalar function on a +one-dimensional level set. Its nonzero derivative completes an invertible minor to the full +derivative. These results are independent of the general injective-mapping theorem. + +## Main results + +`isInvertible_fderiv_of_injOn_of_invertible_partial` completes an invertible transverse minor. +`isInvertible_fderiv_of_injOn_of_hyperplane` is the corresponding statement after restricting to +a level hyperplane. `injective_of_injective_vertical_of_transverse_vector` is the +one-dimensional reduction. +-/ + +public noncomputable section + +open Set Filter Function +open scoped Topology + +namespace SeveralComplexVariables + +variable {P : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] + +/-- An injective vertical block and a nonzero transverse image imply injectivity. -/ +theorem injective_of_injective_vertical_of_transverse_vector + (L : (ℂ × P) →L[ℂ] (ℂ × P)) + (hi : Injective (fun p : P => (L (0, p)).2)) {b : P} + (hs : (L (1, b)).2 = 0) (ht : (L (1, b)).1 ≠ 0) : Injective L := by + apply (injective_iff_map_eq_zero L).mpr + intro v hv + have he : (0, v.2 - v.1 • b) = v - v.1 • (1, b) := by + ext <;> simp + have hz : (L (0, v.2 - v.1 • b)).2 = 0 := by + rw [he, map_sub, map_smul, hv] + simp [hs] + have hb : v.2 - v.1 • b = 0 := + hi (by simpa only [Prod.mk_zero_zero, map_zero, Prod.snd_zero] using hz) + have hv' : v = v.1 • (1, b) := by + ext + · simp + · exact sub_eq_zero.mp hb + have him : L v = v.1 • L (1, b) := by + conv_lhs => rw [hv'] + rw [map_smul] + have hc : v.1 * (L (1, b)).1 = 0 := by + simpa only [Prod.smul_fst, smul_eq_mul, Prod.fst_zero] using + congrArg Prod.fst (him.symm.trans hv) + have h0 : v.1 = 0 := (mul_eq_zero.mp hc).resolve_right ht + rw [hv', h0, zero_smul] + +variable [FiniteDimensional ℂ P] + +/-- An injective holomorphic map with an invertible codimension-one minor is nonsingular. -/ +theorem isInvertible_fderiv_of_injOn_of_invertible_partial + {D : Set (ℂ × P)} (hD : IsOpen D) {f : (ℂ × P) → (ℂ × P)} + (hf : DifferentiableOn ℂ f D) (hi : InjOn f D) {a : ℂ} {b : P} + (hab : (a, b) ∈ D) + (hpart : ((fderiv ℂ (fun z => (f z).2) (a, b)).comp + (ContinuousLinearMap.inr ℂ ℂ P)).IsInvertible) : + (fderiv ℂ f (a, b)).IsInvertible := by + let := FiniteDimensional.complete ℂ P + have hfs : DifferentiableOn ℂ (fun z => (f z).2) D := hf.snd + obtain ⟨U, V, g, hU, ha, hV, hb, hUV, hg, hm, hga, _, heq⟩ := + exists_holomorphic_implicit_mapping hD hfs hab hpart + let γ : ℂ → ℂ × P := fun w => (w, g w) + have hγ : DifferentiableOn ℂ γ U := differentiableOn_id.prodMk hg + have hγD : MapsTo γ U D := fun w hw => hUV ⟨hw, hm hw⟩ + have hfg : DifferentiableOn ℂ (f ∘ γ) U := hf.comp hγ hγD + have hscalar : InjOn (fun w => (f (γ w)).1) U := by + intro w hw z hz he + have hs : (f (γ w)).2 = (f (γ z)).2 := + ((heq w hw (g w) (hm hw)).mpr rfl).trans + ((heq z hz (g z) (hm hz)).mpr rfl).symm + exact congrArg Prod.fst (hi (hγD hw) (hγD hz) (Prod.ext he hs)) + have hne := deriv_ne_zero_of_injOn hU hfg.fst hscalar ha + have hγa : HasDerivAt γ (1, deriv g a) a := + (hasDerivAt_id a).prodMk ((hg a ha).differentiableAt (hU.mem_nhds ha)).hasDerivAt + have hfa := ((hf (a, b) hab).differentiableAt (hD.mem_nhds hab)).hasFDerivAt + have hc := hfa.comp_hasDerivAt_of_eq a hγa (by simp [γ, hga]) + have hcf := (ContinuousLinearMap.fst ℂ ℂ P).hasFDerivAt.comp_hasDerivAt a hc + have hcs := (ContinuousLinearMap.snd ℂ ℂ P).hasFDerivAt.comp_hasDerivAt a hc + change HasDerivAt (fun w => (f (γ w)).1) + (fderiv ℂ f (a, b) (1, deriv g a)).1 a at hcf + change HasDerivAt (fun w => (f (γ w)).2) + (fderiv ℂ f (a, b) (1, deriv g a)).2 a at hcs + have hs : (fderiv ℂ f (a, b) (1, deriv g a)).2 = 0 := by + rw [← hcs.deriv] + apply (Filter.EventuallyEq.deriv_eq ?_).trans (deriv_const a (f (a, b)).2) + filter_upwards [hU.mem_nhds ha] with w hw + exact (heq w hw (g w) (hm hw)).mpr rfl + have ht : (fderiv ℂ f (a, b) (1, deriv g a)).1 ≠ 0 := by + rwa [← hcf.deriv] + have hA : Injective (fun p : P => (fderiv ℂ f (a, b) (0, p)).2) := by + obtain ⟨A, hA⟩ := hpart + have he : (fun p : P => (fderiv ℂ f (a, b) (0, p)).2) = A := by + funext p + change _ = (A : P →L[ℂ] P) p + rw [hA] + rw [hfa.snd.fderiv] + rfl + rw [he] + exact A.injective + have hinj := injective_of_injective_vertical_of_transverse_vector + (fderiv ℂ f (a, b)) hA hs ht + exact ⟨(LinearEquiv.ofBijective (fderiv ℂ f (a, b)).toLinearMap + ⟨hinj, (LinearMap.injective_iff_surjective).mp hinj⟩).toContinuousLinearEquiv, rfl⟩ + +/-- An embedding of a hyperplane extends to linear coordinates with one extra scalar variable. -/ +theorem exists_linearEquiv_prod_extension + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + (i : P →L[ℂ] E) (hi : Injective i) + (hdim : Module.finrank ℂ P + 1 = Module.finrank ℂ E) : + ∃ A : (ℂ × P) ≃L[ℂ] E, ∀ p, A (0, p) = i p := by + let R := LinearMap.range i.toLinearMap + let e : P ≃ₗ[ℂ] R := LinearEquiv.ofInjective i.toLinearMap hi + obtain ⟨Q, hQ⟩ := R.exists_isCompl + have hdimQ : Module.finrank ℂ Q = 1 := by + have hh := Submodule.finrank_add_eq_of_isCompl hQ + have he := e.finrank_eq + omega + let c : ℂ ≃ₗ[ℂ] Q := LinearEquiv.ofFinrankEq ℂ Q (by simpa using hdimQ.symm) + let A := ((c.prodCongr e).trans (Q.prodEquivOfIsCompl R hQ.symm)).toContinuousLinearEquiv + refine ⟨A, fun p => ?_⟩ + change (c 0 : E) + (e p : E) = i p + simp only [map_zero, Submodule.coe_zero, zero_add] + rfl + +/-- If the derivative of an injective holomorphic map is injective on a hyperplane, then its full +derivative is invertible. -/ +theorem isInvertible_fderiv_of_injOn_of_hyperplane + {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [FiniteDimensional ℂ F] + (hdim : Module.finrank ℂ E = Module.finrank ℂ F) + {U : Set E} (hU : IsOpen U) {f : E → F} (hf : DifferentiableOn ℂ f U) + (hi : InjOn f U) {a : E} (ha : a ∈ U) (S : P →L[ℂ] E) + (hS : Injective S) (hP : Module.finrank ℂ P + 1 = Module.finrank ℂ E) + (hdfS : Injective ((fderiv ℂ f a).comp S)) : (fderiv ℂ f a).IsInvertible := by + obtain ⟨A, hA⟩ := exists_linearEquiv_prod_extension S hS hP + obtain ⟨B, hB⟩ := exists_linearEquiv_prod_extension ((fderiv ℂ f a).comp S) hdfS + (hP.trans hdim) + let g := B.symm ∘ f ∘ A + let D := A ⁻¹' U + have hD : IsOpen D := hU.preimage A.continuous + have hg : DifferentiableOn ℂ g D := + B.symm.differentiable.comp_differentiableOn + (hf.comp A.differentiable.differentiableOn (fun _ hz => hz)) + have hgi : InjOn g D := by + intro z hz w hw he + apply A.injective + apply hi hz hw + exact B.symm.injective he + have haD : A.symm a ∈ D := by simpa [D] + have hda : fderiv ℂ g (A.symm a) = + B.symm.toContinuousLinearMap.comp ((fderiv ℂ f a).comp A.toContinuousLinearMap) := by + have hfa : HasFDerivAt f (fderiv ℂ f a) (A (A.symm a)) := by + simpa only [A.apply_symm_apply] using + ((hf a ha).differentiableAt (hU.mem_nhds ha)).hasFDerivAt + exact (B.symm.hasFDerivAt.comp (A.symm a) (hfa.comp (A.symm a) A.hasFDerivAt)).fderiv + have hpartial : (fderiv ℂ (fun z => (g z).2) (A.symm a)).comp + (ContinuousLinearMap.inr ℂ ℂ P) = ContinuousLinearMap.id ℂ P := by + rw [((hg _ haD).differentiableAt (hD.mem_nhds haD)).hasFDerivAt.snd.fderiv, hda] + ext p + change (B.symm ((fderiv ℂ f a) (A (0, p)))).2 = p + rw [hA, ← ContinuousLinearMap.comp_apply, ← hB, B.symm_apply_apply] + have hinv : (fderiv ℂ g (A.symm a)).IsInvertible := + isInvertible_fderiv_of_injOn_of_invertible_partial hD hg hgi haD + (by + change ((fderiv ℂ (fun z => (g z).2) (A.symm a)).comp + (ContinuousLinearMap.inr ℂ ℂ P)).IsInvertible + rw [hpartial] + exact ⟨ContinuousLinearEquiv.refl ℂ P, rfl⟩) + obtain ⟨T, hT⟩ := hinv + refine ⟨A.symm.trans (T.trans B), ?_⟩ + ext v + change B (T (A.symm v)) = (fderiv ℂ f a) v + apply B.symm.injective + have he := DFunLike.congr_fun hT (A.symm v) + simpa only [hda, ContinuousLinearMap.comp_apply, ContinuousLinearEquiv.coe_coe, + A.apply_symm_apply, B.symm_apply_apply] using he + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean new file mode 100644 index 0000000000..5ea75dbf23 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean @@ -0,0 +1,126 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion + +/-! +# Excluding critical points of injective holomorphic maps + +The critical set cannot have a regular hypersurface point: restriction to that hypersurface has +an immersion point, where an invertible transverse minor forces nonsingularity. The Jacobian +determinant is not identically zero, and any nonempty zero set of it has a regular hypersurface +point. Thus the critical set is empty. + +## Main results + +`not_isRegularAnalyticSetAt_criticalSet` excludes a regular hypersurface point of the critical +set. `analyticOnNhd_det_complexJacobian` is holomorphy of the Jacobian determinant. +`isInvertible_fderiv_of_injOn_coordinates` is nonsingularity in coordinates, by emptiness of +that critical set. +-/ + +public noncomputable section + +open Set Filter Function Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +/-- A critical set of an injective holomorphic map cannot contain a regular hypersurface. -/ +theorem not_isRegularAnalyticSetAt_criticalSet + (hdim : Module.finrank ℂ E = Module.finrank ℂ F) + {U : Set E} (hU : IsOpen U) {f : E → F} (hf : DifferentiableOn ℂ f U) + (hi : InjOn f U) {A : Set E} (hAU : A ⊆ U) + (hcrit : ∀ x ∈ A, ¬ (fderiv ℂ f x).IsInvertible) {a : E} : + ¬ IsRegularAnalyticSetAt A a 1 := by + rintro ⟨haA, e, L, he, hae, hLs, heA⟩ + let K := L.ker + let V : Set K := K.subtypeL ⁻¹' e.target + have hV : IsOpen V := e.open_target.preimage K.subtypeL.continuous + have hLa : e a ∈ K := (heA a hae).mp haA + have hVne : V.Nonempty := ⟨⟨e a, hLa⟩, e.map_source hae⟩ + let G : K → F := fun z => f (e.symm z) + have hxA (z : K) (hz : z ∈ V) : e.symm z ∈ A := by + apply (heA _ (e.map_target hz)).mpr + rw [e.right_inv hz] + exact z.property + have hG : DifferentiableOn ℂ G V := by + intro z hz + exact (((hf _ (hAU (hxA z hz))).differentiableAt (hU.mem_nhds (hAU (hxA z hz)))).comp + z ((he.symm.differentiableAt hz).comp z K.subtypeL.differentiableAt)).differentiableWithinAt + have hGi : InjOn G V := by + intro z hz w hw hzw + apply Subtype.val_injective + exact e.symm.injOn hz hw (hi (hAU (hxA z hz)) (hAU (hxA w hw)) hzw) + obtain ⟨z, hz, hzi⟩ := exists_injective_fderiv_of_injOn hV hVne hG hGi + let S := (fderiv ℂ e.symm (z : E)).comp K.subtypeL + have hS : Injective S := + (he.symm.isInvertible_fderiv hz).injective.comp Subtype.val_injective + have hP : Module.finrank ℂ K + 1 = Module.finrank ℂ E := by + have hh := L.toLinearMap.finrank_range_add_finrank_ker + rw [LinearMap.range_eq_top.mpr hLs, finrank_top] at hh + simpa [K, add_comm] using hh + have hd : fderiv ℂ G z = (fderiv ℂ f (e.symm z)).comp S := by + exact (((hf _ (hAU (hxA z hz))).differentiableAt + (hU.mem_nhds (hAU (hxA z hz)))).hasFDerivAt.comp z + ((he.symm.differentiableAt hz).hasFDerivAt.comp z K.subtypeL.hasFDerivAt)).fderiv + exact hcrit _ (hxA z hz) (isInvertible_fderiv_of_injOn_of_hyperplane hdim hU hf hi + (hAU (hxA z hz)) S hS hP (by rwa [← hd])) + +/-- The determinant of the complex Jacobian is analytic on a holomorphic map's open domain. -/ +theorem analyticOnNhd_det_complexJacobian {ι : Type*} [Fintype ι] [DecidableEq ι] + {U : Set (ι → ℂ)} (hU : IsOpen U) {f : (ι → ℂ) → (ι → ℂ)} + (hf : AnalyticOnNhd ℂ f U) : AnalyticOnNhd ℂ (fun z => (complexJacobian f z).det) U := by + classical + intro a ha + simp only [Matrix.det_apply', complexJacobian] + apply Finset.analyticAt_fun_sum + intro σ _ + apply analyticAt_const.mul + apply Finset.analyticAt_fun_prod + intro i _ + exact ((analyticOnNhd_pi_iff.mp hf (σ i)).partialDeriv hU i) a ha + +/-- An injective holomorphic map between equal complex coordinate spaces has no critical points. -/ +theorem isInvertible_fderiv_of_injOn_coordinates {ι : Type*} [Fintype ι] + {U : Set (ι → ℂ)} (hU : IsOpen U) {f : (ι → ℂ) → (ι → ℂ)} + (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) {a : ι → ℂ} (ha : a ∈ U) : + (fderiv ℂ f a).IsInvertible := by + classical + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + let V := Metric.ball a r + have haV : a ∈ V := Metric.mem_ball_self hr + have hV : IsOpen V := Metric.isOpen_ball + have hfV := hf.mono hball + let J := fun z => (complexJacobian f z).det + have hJ : AnalyticOnNhd ℂ J V := + analyticOnNhd_det_complexJacobian hV (hfV.analyticOnNhd_of_finiteDimensional hV) + obtain ⟨b, hb, hbi⟩ := exists_injective_fderiv_of_injOn hV ⟨a, haV⟩ hfV (hi.mono hball) + have hJb : J b ≠ 0 := (det_complexJacobian_ne_zero_iff + ((hfV b hb).differentiableAt (hV.mem_nhds hb))).mpr + ⟨(LinearEquiv.ofBijective (fderiv ℂ f b).toLinearMap + ⟨hbi, LinearMap.surjective_of_injective hbi⟩).toContinuousLinearEquiv, rfl⟩ + apply (det_complexJacobian_ne_zero_iff + ((hf a ha).differentiableAt (hU.mem_nhds ha))).mp + intro hJa + obtain ⟨c, hc⟩ := exists_regularPoint_zeroSet hV isPreconnected_ball hJ + ⟨b, hb, hJb⟩ ⟨a, haV, hJa⟩ + apply not_isRegularAnalyticSetAt_criticalSet rfl hU hf hi + (fun z hz => hball hz.1) (a := c) _ hc + intro z hz hinv + exact ((det_complexJacobian_ne_zero_iff + ((hf z (hball hz.1)).differentiableAt (hU.mem_nhds (hball hz.1)))).mpr hinv) hz.2 + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/Immersion.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/Immersion.lean new file mode 100644 index 0000000000..f6a284bad3 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/Immersion.lean @@ -0,0 +1,193 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.LinearAlgebra.Dual.Lemmas +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable + +/-! +# Immersion points of injective holomorphic maps + +Scalar projections with nonzero differential admit local coordinates. Restricting to a level +hyperplane lowers the source dimension and preserves injectivity. This gives immersion points +without assuming that source and target dimensions agree. + +## Main results + +`exists_fderiv_ne_zero_of_injOn` finds a point of nonzero derivative on a nonempty open set in +positive dimension. `exists_scalar_projection_fderiv_ne_zero` produces a scalar coordinate with +nonzero derivative. `exists_injective_fderiv_of_injOn` is the immersion-point theorem after +restricting to a level hyperplane. +-/ + +public noncomputable section + +open Set Filter Metric Function +open scoped Topology + +namespace SeveralComplexVariables + +universe u + +variable {E : Type u} {F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] + +omit [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] in +/-- An injective holomorphic map on a nonempty open set in positive dimension has nonzero +differential somewhere. -/ +theorem exists_fderiv_ne_zero_of_injOn [Nontrivial E] + {U : Set E} (hU : IsOpen U) (hne : U.Nonempty) {f : E → F} + (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) : + ∃ a ∈ U, fderiv ℂ f a ≠ 0 := by + by_contra! hz + obtain ⟨a, ha⟩ := hne + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + have hs : ({a} : Set E) ∈ 𝓝 a := by + filter_upwards [ball_mem_nhds a hr] with z hzball + apply hi (hball hzball) ha + exact isOpen_ball.is_const_of_fderiv_eq_zero isPreconnected_ball + (hf.mono hball) (fun w hw => hz w (hball hw)) hzball (mem_ball_self hr) + have := mem_interior_iff_mem_nhds.mpr hs + simp at this + +omit [FiniteDimensional ℂ E] in +/-- Some scalar projection of an injective holomorphic map has nonzero differential at a point of +any nonempty open domain of positive dimension. -/ +theorem exists_scalar_projection_fderiv_ne_zero [Nontrivial E] + {U : Set E} (hU : IsOpen U) (hne : U.Nonempty) {f : E → F} + (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) : + ∃ a ∈ U, ∃ ℓ : F →L[ℂ] ℂ, fderiv ℂ (ℓ ∘ f) a ≠ 0 := by + obtain ⟨a, ha, hdfa⟩ := exists_fderiv_ne_zero_of_injOn hU hne hf hi + obtain ⟨v, hv⟩ := DFunLike.ne_iff.mp hdfa + obtain ⟨l, hl⟩ := Module.Projective.exists_dual_ne_zero ℂ hv + let ℓ : F →L[ℂ] ℂ := l.toContinuousLinearMap + refine ⟨a, ha, ℓ, ?_⟩ + have hd : fderiv ℂ (ℓ ∘ f) a = ℓ.comp (fderiv ℂ f a) := + (ℓ.hasFDerivAt.comp a ((hf a ha).differentiableAt (hU.mem_nhds ha)).hasFDerivAt).fderiv + intro hz + apply hl + change ℓ (fderiv ℂ f a v) = 0 + rw [← ContinuousLinearMap.comp_apply, ← hd, hz, zero_apply] + +/-- A scalar holomorphic submersion becomes its own differential in suitable local coordinates. -/ +theorem exists_biholomorphic_scalar_normalization {U : Set E} (hU : IsOpen U) + {f : E → ℂ} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hn : fderiv ℂ f a ≠ 0) : + ∃ e : OpenPartialHomeomorph E E, IsBiholomorphic e ∧ a ∈ e.source ∧ e.source ⊆ U ∧ + ∀ z ∈ e.source, (fderiv ℂ f a) (e z) = f z := by + let L := fderiv ℂ f a + have hL : L.toLinearMap ≠ 0 := fun h => hn (by ext z; exact DFunLike.congr_fun h z) + obtain ⟨R, hR⟩ := L.toLinearMap.exists_rightInverse_of_surjective + (LinearMap.range_eq_top.mpr (LinearMap.surjective hL)) + let B : ℂ →L[ℂ] E := R.toContinuousLinearMap + have hLB (w : ℂ) : L (B w) = w := DFunLike.congr_fun hR w + let g : E → E := fun z => z + B (f z - L z) + have hg : DifferentiableOn ℂ g U := + differentiableOn_id.add (B.differentiable.comp_differentiableOn + (hf.sub L.differentiable.differentiableOn)) + have hd : HasFDerivAt g (ContinuousLinearMap.id ℂ E) a := by + simpa only [g, L, Pi.add_def, Pi.sub_def, Function.comp_def, id_eq, + sub_self, ContinuousLinearMap.comp_zero, add_zero] using + (hasFDerivAt_id a).add (B.hasFDerivAt.comp a + (((hf a ha).differentiableAt (hU.mem_nhds ha)).hasFDerivAt.sub L.hasFDerivAt)) + obtain ⟨e, he, hae, heU, heq⟩ := exists_biholomorphic_of_isInvertible_fderiv hU hg ha + (by rw [hd.fderiv]; exact ⟨ContinuousLinearEquiv.refl ℂ E, rfl⟩) + refine ⟨e, he, hae, heU, fun z _ => ?_⟩ + rw [heq] + change L (z + B (f z - L z)) = f z + rw [map_add, hLB] + abel + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- Dimension induction for the existence of immersion points. -/ +private theorem exists_injective_fderiv_aux (n : ℕ) : + ∀ {E : Type u} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E], + Module.finrank ℂ E = n → ∀ {U : Set E}, IsOpen U → U.Nonempty → + ∀ {f : E → F}, DifferentiableOn ℂ f U → InjOn f U → + ∃ a ∈ U, Injective (fderiv ℂ f a) := by + induction n using Nat.strong_induction_on with + | h n ih => + intro E _ _ _ hn U hU hne f hf hi + by_cases hzero : Module.finrank ℂ E = 0 + · have : Subsingleton E := Module.finrank_zero_iff.mp hzero + obtain ⟨a, ha⟩ := hne + exact ⟨a, ha, fun _ _ _ => Subsingleton.elim _ _⟩ + have : Nontrivial E := not_subsingleton_iff_nontrivial.mp + (fun hs => hzero (@Module.finrank_zero_of_subsingleton ℂ E _ _ _ _ hs)) + obtain ⟨a, ha, ℓ, hL⟩ := exists_scalar_projection_fderiv_ne_zero hU hne hf hi + let φ := ℓ ∘ f + have hφ : DifferentiableOn ℂ φ U := ℓ.differentiable.comp_differentiableOn hf + let L := fderiv ℂ φ a + obtain ⟨e, he, hae, heU, heφ⟩ := exists_biholomorphic_scalar_normalization hU hφ ha hL + let G := f ∘ e.symm + have hG : DifferentiableOn ℂ G e.target := + hf.comp he.2 (fun y hy => heU (e.map_target hy)) + have hGL : EqOn (ℓ ∘ G) L e.target := by + intro y hy + exact (heφ (e.symm y) (e.map_target hy)).symm.trans (by rw [e.right_inv hy]) + let K := L.ker + let κ : K → E := fun z => e a + z + have hκ : ∀ z, HasFDerivAt κ K.subtypeL z := by + intro z + simpa only [zero_add, κ, Pi.add_def, Submodule.subtypeL_apply] using + (hasFDerivAt_const (e a) z).add K.subtypeL.hasFDerivAt + let V := κ ⁻¹' e.target + have hV : IsOpen V := e.open_target.preimage + (continuous_const.add continuous_subtype_val) + have hVne : V.Nonempty := ⟨0, by simpa [V, κ] using e.map_source hae⟩ + have hGK : DifferentiableOn ℂ (G ∘ κ) V := + hG.comp (fun z _ => (hκ z).differentiableAt.differentiableWithinAt) (fun _ hz => hz) + have hGKi : InjOn (G ∘ κ) V := by + intro z hz w hw hzw + apply Subtype.val_injective + apply add_left_cancel (a := e a) + apply e.symm.injOn hz hw + exact hi (heU (e.map_target hz)) (heU (e.map_target hw)) hzw + have hL' : L.toLinearMap ≠ 0 := fun h => hL (by ext z; exact DFunLike.congr_fun h z) + have hdim : Module.finrank ℂ K < n := by + have hh := Module.Dual.finrank_ker_add_one_of_ne_zero hL' + change Module.finrank ℂ K + 1 = Module.finrank ℂ E at hh + omega + obtain ⟨z, hz, hzi⟩ := ih (Module.finrank ℂ K) hdim rfl hV hVne hGK hGKi + have hGd := (hG (κ z) hz).differentiableAt (e.open_target.mem_nhds hz) + have hLG : ℓ.comp (fderiv ℂ G (κ z)) = L := by + rw [← (ℓ.hasFDerivAt.comp (κ z) hGd.hasFDerivAt).fderiv] + have hh : (ℓ ∘ G) =ᶠ[𝓝 (κ z)] L := + Filter.mem_of_superset (e.open_target.mem_nhds hz) hGL + exact hh.fderiv_eq.trans L.fderiv + have hKG : fderiv ℂ (G ∘ κ) z = (fderiv ℂ G (κ z)).comp K.subtypeL := + (hGd.hasFDerivAt.comp z (hκ z)).fderiv + have hinjG : Injective (fderiv ℂ G (κ z)) := by + apply (injective_iff_map_eq_zero _).mpr + intro v hv + have hvK : v ∈ K := by + change L v = 0 + rw [← hLG, ContinuousLinearMap.comp_apply, hv, map_zero] + have hvz : (⟨v, hvK⟩ : K) = 0 := hzi (by simp [hKG, hv]) + exact congrArg Subtype.val hvz + refine ⟨e.symm (κ z), heU (e.map_target hz), ?_⟩ + have hd : fderiv ℂ G (κ z) = + (fderiv ℂ f (e.symm (κ z))).comp (fderiv ℂ e.symm (κ z)) := + fderiv_comp _ ((hf _ (heU (e.map_target hz))).differentiableAt + (hU.mem_nhds (heU (e.map_target hz)))) (he.symm.differentiableAt hz) + have hsurj := (he.symm.isInvertible_fderiv hz).bijective.surjective + intro v w hvw + obtain ⟨v', rfl⟩ := hsurj v + obtain ⟨w', rfl⟩ := hsurj w + exact congrArg (fderiv ℂ e.symm (κ z)) (hinjG (by simpa only [hd, + ContinuousLinearMap.comp_apply] using hvw)) + +/-- Every nonempty open restriction of an injective holomorphic map has an immersion point. The +source and target dimensions need not agree. -/ +theorem exists_injective_fderiv_of_injOn {U : Set E} (hU : IsOpen U) (hne : U.Nonempty) + {f : E → F} (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) : + ∃ a ∈ U, Injective (fderiv ℂ f a) := + exists_injective_fderiv_aux (Module.finrank ℂ E) rfl hU hne hf hi + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/OneVariable.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/OneVariable.lean new file mode 100644 index 0000000000..1f63d8aa22 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/OneVariable.lean @@ -0,0 +1,100 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.InverseFunctionTheorem.Deriv +public import Mathlib.Analysis.Calculus.MeanValue +public import Mathlib.Analysis.Complex.OpenMapping +public import Mathlib.Analysis.Complex.RemovableSingularity +public import Mathlib.Analysis.Normed.Module.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic + +/-! +# Nonsingularity of injective holomorphic functions of one variable + +The open mapping theorem makes the inverse continuous. Isolated zeros of the derivative make it +holomorphic off the image of the base point, so the removable singularity theorem makes it +holomorphic there too. The chain rule then excludes a zero derivative. + +## Main results + +`deriv_ne_zero_of_injOn` is nonsingularity of an injective holomorphic function of one complex +variable. `not_eventually_constant_of_injOn_complex` and `not_eventually_deriv_eq_zero_of_injOn` +exclude a locally constant germ and a locally vanishing derivative. +-/ + +public noncomputable section + +open Set Filter Metric Function +open scoped Topology + +namespace SeveralComplexVariables + +/-- A function injective on a neighborhood in the complex plane is not locally constant. -/ +theorem not_eventually_constant_of_injOn_complex {f : ℂ → ℂ} {U : Set ℂ} {a : ℂ} + (hU : U ∈ 𝓝 a) (hi : InjOn f U) : ¬ ∀ᶠ z in 𝓝 a, f z = f a := by + intro hc + have hs : ({a} : Set ℂ) ∈ 𝓝 a := by + filter_upwards [hU, hc] with z hz he + exact hi hz (mem_of_mem_nhds hU) he + have := mem_interior_iff_mem_nhds.mpr hs + simp at this + +/-- The derivative of a locally injective analytic function is not locally identically zero. -/ +theorem not_eventually_deriv_eq_zero_of_injOn {f : ℂ → ℂ} {U : Set ℂ} {a : ℂ} + (hU : U ∈ 𝓝 a) (hi : InjOn f U) (hf : AnalyticAt ℂ f a) : + ¬ deriv f =ᶠ[𝓝 a] 0 := by + intro hz + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp + (inter_mem hU (hf.eventually_analyticAt.and hz)) + apply not_eventually_constant_of_injOn_complex hU hi + filter_upwards [ball_mem_nhds a hr] with z hz + exact isOpen_ball.is_const_of_deriv_eq_zero isPreconnected_ball + (fun w hw => ((hball hw).2.1).differentiableAt.differentiableWithinAt) + (fun w hw => (hball hw).2.2) hz (mem_ball_self hr) + +/-- An injective holomorphic function of one complex variable has nonzero derivative. -/ +theorem deriv_ne_zero_of_injOn {U : Set ℂ} (hU : IsOpen U) {f : ℂ → ℂ} + (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) {a : ℂ} (ha : a ∈ U) : + deriv f a ≠ 0 := by + have hfa := hf.analyticOnNhd hU a ha + have hopen : 𝓝 (f a) ≤ map f (𝓝 a) := + hfa.eventually_constant_or_nhds_le_map_nhds.resolve_left + (not_eventually_constant_of_injOn_complex (hU.mem_nhds ha) hi) + let g := invFunOn f U + have hleft : (g ∘ f) =ᶠ[𝓝 a] id := + Filter.mem_of_superset (hU.mem_nhds ha) (fun _ hz => hi.leftInvOn_invFunOn hz) + have hga : g (f a) = a := hi.leftInvOn_invFunOn ha + have hgcont : ContinuousAt g (f a) := by + rw [ContinuousAt, hga] + have ht : Tendsto (g ∘ f) (𝓝 a) (𝓝 a) := tendsto_id.congr' hleft.symm + change map (g ∘ f) (𝓝 a) ≤ 𝓝 a at ht + exact (Filter.map_mono hopen).trans (by rwa [map_map]) + have hisol : ∀ᶠ z in 𝓝[≠] a, deriv f z ≠ 0 := + hfa.deriv.eventually_eq_zero_or_eventually_ne_zero.resolve_left + (not_eventually_deriv_eq_zero_of_injOn (hU.mem_nhds ha) hi hfa) + have hV : {z | z ∈ U ∧ (z ≠ a → deriv f z ≠ 0)} ∈ 𝓝 a := + inter_mem (hU.mem_nhds ha) (eventually_nhdsWithin_iff.mp hisol) + have hW : f '' {z | z ∈ U ∧ (z ≠ a → deriv f z ≠ 0)} ∈ 𝓝 (f a) := + hopen (image_mem_map hV) + have hgd : ∀ᶠ w in 𝓝[≠] (f a), DifferentiableAt ℂ g w := by + filter_upwards [nhdsWithin_le_nhds hW, self_mem_nhdsWithin] with w hw hwne + obtain ⟨z, ⟨hz, hdz⟩, rfl⟩ := hw + have hzane : z ≠ a := fun h => hwne (by simp [h]) + have hstrict := (hf.analyticOnNhd hU z hz).contDiffAt.hasStrictDerivAt (n := 1) one_ne_zero + exact (hstrict.to_local_left_inverse (hdz hzane) + (Filter.mem_of_superset (hU.mem_nhds hz) + (fun _ ht => hi.leftInvOn_invFunOn ht))).hasDerivAt.differentiableAt + have hgan := Complex.analyticAt_of_differentiable_on_punctured_nhds_of_continuousAt hgd hgcont + have hder : deriv g (f a) * deriv f a = 1 := by + have hc := hgan.differentiableAt.hasDerivAt.comp a hfa.differentiableAt.hasDerivAt + exact hc.deriv.symm.trans ((Filter.EventuallyEq.deriv_eq hleft).trans (deriv_id a)) + intro hz + simp [hz] at hder + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean new file mode 100644 index 0000000000..763086ed9f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean @@ -0,0 +1,9 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral/Circle.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral/Circle.lean new file mode 100644 index 0000000000..a280584388 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral/Circle.lean @@ -0,0 +1,47 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.CircleAverage +public import Mathlib.MeasureTheory.Integral.CircleIntegral + +/-! +# Circle integrability of maxima and reflection invariance of circle averages + +The maximum of two real-valued functions integrable on a circle is integrable there, and circle +averages are invariant under the antipodal reflection of the circle. + +## Main results + +* `CircleIntegrable.max`: Maxima of circle-integrable functions are circle integrable. +* `Real.circleAverage_reflect`: The circle average is invariant under the antipodal reflection of + the circle. +-/ + +public section + +open Complex MeasureTheory Real + +/-- Maxima of circle-integrable functions are circle integrable. -/ +theorem CircleIntegrable.max {u v : ℂ → ℝ} {c : ℂ} {R : ℝ} (hu : CircleIntegrable u c R) + (hv : CircleIntegrable v c R) : CircleIntegrable (fun z => max (u z) (v z)) c R := by + rw [circleIntegrable_def] at hu hv ⊢ + exact ⟨hu.1.sup hv.1, hu.2.sup hv.2⟩ + +/-- The circle average is invariant under the antipodal reflection of the circle. -/ +theorem Real.circleAverage_reflect (u : ℂ → ℝ) (c : ℂ) (r : ℝ) : + circleAverage (fun t => u (2 * c - t)) c r = circleAverage u c r := by + rw [circleAverage_eq_integral_add (f := u) π, circleAverage_def] + congr 1 + refine intervalIntegral.integral_congr fun θ _ => ?_ + simp only [circleMap] + congr 1 + rw [Complex.ofReal_add, add_mul, Complex.exp_add, Complex.exp_pi_mul_I] + ring + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IsolatedSingularity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IsolatedSingularity.lean new file mode 100644 index 0000000000..7a98646936 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/IsolatedSingularity.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell + +/-! +# Removal of isolated singularities + +An arbitrary finite-dimensional complex normed source is reduced by a continuous linear +coordinate equivalence to the proved punctured-polydisc theorem. The extension is then glued to +the original function. No boundedness hypothesis is imposed near the puncture. Reference: +[Scheidemann][Scheidemann2005] (2005), Corollary 2.3.2. + +## Main results + +`exists_analyticOnNhd_extension_diff_singleton` removes an isolated singularity of a Banach-valued +holomorphic map on an open set in complex dimension at least two, without a local boundedness +hypothesis. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Metric Filter +open scoped Topology + +namespace SeveralComplexVariables + +/-- An isolated singularity is removable on any open set in complex dimension at least two. The +target is any complex Banach space, and the domain need not be connected. -/ +theorem exists_analyticOnNhd_extension_diff_singleton + {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + (hdim : 2 ≤ Module.finrank ℂ E) {U : Set E} (ho : IsOpen U) + {a : E} (ha : a ∈ U) {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ {a})) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ {a}) := by + classical + let d := Module.finrank ℂ E - 1 + have hd : 0 < d := by dsimp [d]; omega + let : Nonempty (Fin d) := ⟨⟨0, hd⟩⟩ + have hdim' : Module.finrank ℂ E = Module.finrank ℂ ((Fin d → ℂ) × ℂ) := by + simp only [Module.finrank_prod, Module.finrank_pi, Module.finrank_self, Fintype.card_fin] + dsimp [d] + omega + let L : E ≃L[ℂ] ((Fin d → ℂ) × ℂ) := ContinuousLinearEquiv.ofFinrankEq hdim' + have hc : Continuous (fun p => a + L.symm p) := continuous_const.add L.symm.continuous + have hn : {p | a + L.symm p ∈ U} ∈ 𝓝 (0 : (Fin d → ℂ) × ℂ) := + hc.continuousAt.preimage_mem_nhds (by simpa using ho.mem_nhds ha) + obtain ⟨r, hr, hrU⟩ := Metric.mem_nhds_iff.mp hn + have hfun : AnalyticOnNhd ℂ (fun p => f (a + L.symm p)) + ((ball 0 r ×ˢ ball 0 r) \ {0}) := by + intro p hp + have hpU : a + L.symm p ∈ U := + hrU (by simpa only [Prod.zero_eq_mk, ball_prod_same] using hp.1) + have hpne : a + L.symm p ≠ a := by + intro he + apply hp.2 + have he' : L.symm p = 0 := by simpa only [add_eq_left] using he + simpa using congrArg L he' + exact (hf _ ⟨hpU, hpne⟩).comp (f := fun q => a + L.symm q) + (analyticAt_const.add (L.symm.toContinuousLinearMap.analyticAt p)) + obtain ⟨g, hg, heq⟩ := exists_extension_punctured_polydisc hr hr hfun + let G := Function.update f a (g 0) + refine ⟨G, ?_, ?_⟩ + · intro x hx + by_cases hxa : x = a + · subst x + have hga : AnalyticAt ℂ (fun x => g (L (x - a))) a := + (hg 0 ⟨mem_ball_self hr, mem_ball_self hr⟩).comp_of_eq + ((L.toContinuousLinearMap.analyticAt (a - a)).comp (f := fun x : E => x - a) + (analyticAt_id.sub analyticAt_const)) (by simp) + apply hga.congr + have hn' : {x | L (x - a) ∈ ball 0 r} ∈ 𝓝 a := + (L.continuous.comp (continuous_id.sub continuous_const)).continuousAt.preimage_mem_nhds + (by simpa using ball_mem_nhds (0 : (Fin d → ℂ) × ℂ) hr) + filter_upwards [hn'] with x hx + by_cases hxa : x = a + · subst x; simp [G] + · have hp : L (x - a) ∈ (ball 0 r ×ˢ ball 0 r) \ {0} := by + refine ⟨by simpa only [Prod.zero_eq_mk, ball_prod_same] using hx, ?_⟩ + intro hzero + apply hxa + apply sub_eq_zero.mp + have h := congrArg L.symm hzero + simpa using h + simpa [G, hxa] using heq hp + · apply (hf x ⟨hx, hxa⟩).congr + filter_upwards [isOpen_compl_singleton.mem_nhds hxa] with y hy + exact (Function.update_of_ne hy _ _).symm + · intro x hx + exact Function.update_of_ne hx.2 _ _ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentApproximation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentApproximation.lean new file mode 100644 index 0000000000..b455b9f130 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentApproximation.lean @@ -0,0 +1,226 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Function.LpSpace.ContinuousFunctions +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries + +/-! +# Laurent approximation and coefficient projections + +Finite Laurent sums approximate holomorphic functions uniformly on compact subsets. The +coefficient functionals are continuous independently of Laurent expansion. The projections, +their mutual orthogonality, and convergence in the compact-open holomorphic space are derived +from the Laurent expansion theorem. Only the elementary analytic consequences of +[Scheidemann][Scheidemann2005] (2005), Section 2.2, are used; no representation theory of +compact groups is introduced. + +## Main results + +`exists_finite_laurent_approximation` approximates a holomorphic function uniformly on a compact +set by a finite Laurent sum. `exists_laurentCoeffCLM` and `exists_laurentTermCLM` are the +continuous coefficient and term projections on the compact-open holomorphic space. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter MeasureTheory Complex +open scoped Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Integration on a fixed coordinate torus is a continuous linear coefficient functional on the +compact-open space of holomorphic maps. This construction does not require Laurent expansion or +connectedness. -/ +theorem exists_laurentCoeffCLM (U : TopologicalSpace.Opens (Fin n → ℂ)) + (hR : IsReinhardt (U : Set (Fin n → ℂ))) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + (m : Fin n → ℤ) : + ∃ A : HolomorphicMap U F →L[ℂ] F, ∀ f, + A f = multivariableLaurentCoeff (openExtension U f.val) r m := by + classical + let := U.isOpen.locallyCompactSpace + let K := Icc (0 : Fin n → ℝ) (fun _ => 2 * Real.pi) + have hK : IsCompact K := isCompact_Icc + let : CompactSpace K := isCompact_iff_compactSpace.mp hK + let : MeasureSpace K := Measure.Subtype.measureSpace + let : IsFiniteMeasure (volume : Measure K) := ⟨by + rw [Measure.Subtype.volume_univ hK.measurableSet.nullMeasurableSet] + exact hK.measure_lt_top⟩ + have htor (θ : Fin n → ℝ) : torusMap 0 r θ ∈ U := by + apply hR hrU + intro i + simpa only [Pi.zero_apply, sub_zero, Complex.norm_of_nonneg (hr i).le] using + norm_torusMap_sub (c := 0) (fun i => (hr i).le) θ i + let γ : C(K, U) := ⟨fun θ => ⟨torusMap 0 r θ, htor θ⟩, + ((continuous_torusMap 0 r).comp continuous_subtype_val).subtype_mk _⟩ + have hnz (θ : K) (i : Fin n) : torusMap 0 r θ i ≠ 0 := + torusMap_apply_ne_of_norm_sub_lt (c := 0) (w := 0) hr (by simpa using hr i) + let b : C(K, ℂ) := ⟨fun θ => + (∏ i, (r i : ℂ) * exp ((θ.val i : ℂ) * I) * I) * + ∏ i, torusMap 0 r θ i ^ (-m i - 1), by + apply Continuous.mul + · apply continuous_finsetProd + intro i _ + exact ((continuous_const.mul + (Complex.continuous_exp.comp ((Complex.continuous_ofReal.comp + ((continuous_apply i).comp continuous_subtype_val)).mul continuous_const))).mul + continuous_const) + · apply continuous_finsetProd + intro i _ + exact ((continuous_apply i).comp ((continuous_torusMap 0 r).comp + continuous_subtype_val)).zpow₀ (-m i - 1) (fun θ => Or.inl (hnz θ i))⟩ + let T : HolomorphicMap U F →L[ℂ] C(K, F) := + { toFun := fun f => ⟨fun θ => b θ • f.val (γ θ), + b.continuous.smul (f.val.continuous.comp γ.continuous)⟩ + map_add' := by intros; ext; simp + map_smul' := by + intro c f + ext θ + exact smul_comm (b θ) c (f.val (γ θ)) + cont := by + apply ContinuousMap.continuous_of_continuous_uncurry + exact (b.continuous.comp continuous_snd).smul + (continuous_eval.comp + ((continuous_subtype_val.comp continuous_fst).prodMk + (γ.continuous.comp continuous_snd))) } + let J : C(K, F) →L[ℂ] F := + (L1.integralCLM' ℂ).comp (ContinuousMap.toLp 1 volume ℂ) + let A : HolomorphicMap U F →L[ℂ] F := + ((2 * Real.pi * I : ℂ) ^ n)⁻¹ • J.comp T + refine ⟨A, fun f => ?_⟩ + have hJ : J (T f) = ∫ θ : K, T f θ := by + change L1.integralCLM' ℂ (ContinuousMap.toLp 1 volume ℂ (T f)) = _ + rw [← L1.integral_eq' ℂ, L1.integral_eq_integral] + exact integral_congr_ae (ContinuousMap.coeFn_toLp (𝕜 := ℂ) volume (T f)) + change ((2 * Real.pi * I : ℂ) ^ n)⁻¹ • J (T f) = _ + rw [hJ, multivariableLaurentCoeff, torusIntegral, ← integral_subtype hK.measurableSet] + congr 1 + apply integral_congr_ae + filter_upwards with θ + change b θ • f.val (γ θ) = _ + rw [openExtension_apply U _ (htor θ)] + exact mul_smul _ _ _ + +/-- Each Laurent term defines a continuous operator with values in holomorphic maps. Vanishing of +forbidden coefficients uses the Laurent expansion theorem. -/ +theorem exists_laurentTermCLM (U : TopologicalSpace.Opens (Fin n → ℂ)) + (hc : IsConnected (U : Set (Fin n → ℂ))) (hR : IsReinhardt (U : Set (Fin n → ℂ))) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + (m : Fin n → ℤ) : + ∃ P : HolomorphicMap U F →L[ℂ] HolomorphicMap U F, ∀ f z, + (P f).val z = multivariableLaurentTerm + (multivariableLaurentCoeff (openExtension U f.val) r) m z := by + classical + obtain ⟨A, hA⟩ := exists_laurentCoeffCLM (F := F) U hR hr hrU m + by_cases hm : ∀ i, m i < 0 → ∀ z ∈ U, z i ≠ 0 + · let a : (Fin n → ℂ) → ℂ := fun z => ∏ i, z i ^ m i + have ha : AnalyticOnNhd ℂ a U := by + intro z hz + apply Finset.analyticAt_fun_prod + intro i _ + by_cases hi : 0 ≤ m i + · exact ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt z).zpow_nonneg hi + · exact ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt z).zpow + (hm i (lt_of_not_ge hi) z hz) + let B : F →L[ℂ] HolomorphicMap U F := + { toFun := fun v => + ⟨⟨fun z => a z • v, ha.continuousOn.domRestrict.smul continuous_const⟩, by + apply AnalyticOnNhd.congr U.isOpen (ha.smul (analyticOnNhd_const (v := v))) + intro z hz + rw [openExtension_apply U _ hz] + rfl⟩ + map_add' := by intros; ext; exact smul_add _ _ _ + map_smul' := by intros; ext; exact smul_comm _ _ _ + cont := by + apply Continuous.subtype_mk + apply ContinuousMap.continuous_of_continuous_uncurry + exact (ha.continuousOn.domRestrict.comp continuous_snd).smul continuous_fst } + refine ⟨B.comp A, fun f z => ?_⟩ + change a z • A f = _ + rw [hA] + rfl + · push Not at hm + obtain ⟨i, hi, z, hz, hzi⟩ := hm + refine ⟨0, fun f w => ?_⟩ + have hzero := (multivariableLaurent_expansion U.isOpen hc.isPreconnected hR f.property hr + hrU).2.2.1 + m i ⟨z, hz, hzi⟩ hi + simp [multivariableLaurentTerm, hzero] + +/-- Finite canonical Laurent sums approximate uniformly on any given compact subset. Depends on the +Laurent expansion theorem, with no finite-dimensional target restriction. -/ +theorem exists_finite_laurent_approximation {U K : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + (hK : IsCompact K) (hKU : K ⊆ U) {ε : ℝ} (hε : 0 < ε) : + ∃ s : Finset (Fin n → ℤ), ∀ z ∈ K, + ‖f z - ∑ m ∈ s, multivariableLaurentTerm (multivariableLaurentCoeff f r) m z‖ < ε := by + have h := hasSumUniformlyOn_iff_tendstoUniformlyOn.mp + (hasSumUniformlyOn_multivariableLaurent ho hc.isPreconnected hR hf hr hrU hK hKU) + obtain ⟨s, hs⟩ := (Metric.tendstoUniformlyOn_iff.mp h ε hε).exists + exact ⟨s, fun z hz => by simpa [dist_eq_norm] using hs z hz⟩ + +/-- Continuous Laurent projections, their coefficient formulas, and their mutual orthogonality +follow from continuity of torus integration, holomorphy of permitted monomials, and Laurent +uniqueness. Terms with forbidden negative exponents are zero. The finite partial sums converge +in the existing compact-open topology. This deduction depends on the Laurent expansion theorem. -/ +theorem exists_laurentProjections (U : TopologicalSpace.Opens (Fin n → ℂ)) + (hc : IsConnected (U : Set (Fin n → ℂ))) (hR : IsReinhardt (U : Set (Fin n → ℂ))) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) : + ∃ P : (Fin n → ℤ) → HolomorphicMap U F →L[ℂ] HolomorphicMap U F, + (∀ m f z, (P m f).val z = + multivariableLaurentTerm (multivariableLaurentCoeff (openExtension U f.val) r) m z) ∧ + (∀ m k f, P m (P k f) = if m = k then P m f else 0) ∧ + (∀ f, Tendsto (fun s : Finset (Fin n → ℤ) => ∑ m ∈ s, P m f) atTop (𝓝 f)) := by + classical + choose P hP using fun m => exists_laurentTermCLM (F := F) U hc hR hr hrU m + refine ⟨P, hP, ?_, ?_⟩ + · intro m k f + let c : (Fin n → ℤ) → F := fun j => if j = k then + multivariableLaurentCoeff (openExtension U f.val) r k else 0 + have hsingle : HasSum (fun j => if j = k then P k f else 0) (P k f) := + hasSum_ite_eq k (P k f) + have hs : HasSumLocallyUniformlyOn (multivariableLaurentTerm c) + (openExtension U (P k f).val) U := by + apply (holomorphicMap_tendsto_iff.mp hsingle).congr + intro s z hz + rw [openExtension_apply U _ hz] + simp only [Submodule.coe_sum, ContinuousMap.sum_apply] + apply Finset.sum_congr rfl + intro j _ + by_cases hj : j = k + · subst j + simp only [ite_true, hP, multivariableLaurentTerm, c] + · simp [hj, c, multivariableLaurentTerm] + have hcoeff := (multivariableLaurent_expansion U.isOpen hc.isPreconnected hR + (P k f).property hr hrU).2.2.2.2 c hs + ext z + rw [hP, ← hcoeff] + by_cases hmk : m = k + · subst m + simp only [c, ite_true, multivariableLaurentTerm] + exact (hP k f z).symm + · simp [c, hmk, multivariableLaurentTerm] + · intro f + rw [holomorphicMap_tendsto_iff] + apply (multivariableLaurent_expansion U.isOpen hc.isPreconnected hR f.property hr hrU).1.congr + intro s z hz + rw [openExtension_apply U _ hz] + simp only [Submodule.coe_sum, ContinuousMap.sum_apply] + exact Finset.sum_congr rfl (fun m _ => (hP m f ⟨z, hz⟩).symm) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries.lean new file mode 100644 index 0000000000..67ed9d24a3 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries.lean @@ -0,0 +1,97 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness + +/-! +# Multivariable analytic Laurent series + +Coefficients are arbitrary families indexed by integer multi-indices, not algebraic +`LaurentSeries`, whose support is bounded below. Sums use finite subsets of the index type. The +main expansion theorem includes coordinate hyperplanes: coefficients with negative exponent in a +coordinate vanish when the domain meets that hyperplane. This makes the statement compatible +with Lean's totalized integer powers at zero. + +The proof combines successive circle expansions, independence of coefficient tori, and summable +local geometric bounds. References: [Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), +Theorem 2.7.1 and Lemma 2.8.1. + +## Main results + +`multivariableLaurent_expansion` is the expansion theorem on a connected open Reinhardt domain. +`hasSumUniformlyOn_multivariableLaurent` is uniform convergence on compact subsets of the +domain. `multivariableLaurentCoeff_eq_zero_of_not_nonneg` vanishes coefficients with a negative +exponent in a coordinate that meets a hyperplane. Supporting lemmas live in the `LaurentSeries` +submodules. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Complex Set MeasureTheory +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- **Multivariable Laurent expansion on a connected Reinhardt domain.** The expansion is +absolutely and locally uniformly convergent, its coefficients are independent of the torus, +and they are unique. Negative exponents disappear in any coordinate whose hyperplane is met. -/ +theorem multivariableLaurent_expansion {U : Set (Fin n → ℂ)} (ho : IsOpen U) + (hc : IsPreconnected U) (hR : IsReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) + (hrU : (fun i => (r i : ℂ)) ∈ U) : + HasSumLocallyUniformlyOn (multivariableLaurentTerm (multivariableLaurentCoeff f r)) f U ∧ + (∀ z ∈ U, Summable (fun m => ‖multivariableLaurentTerm (multivariableLaurentCoeff f r) m z‖)) ∧ + (∀ (m : Fin n → ℤ) (i : Fin n), (∃ z ∈ U, z i = 0) → m i < 0 → + multivariableLaurentCoeff f r m = 0) ∧ + (∀ s : Fin n → ℝ, (∀ i, 0 < s i) → (fun i => (s i : ℂ)) ∈ U → + multivariableLaurentCoeff f s = multivariableLaurentCoeff f r) ∧ + (∀ c : (Fin n → ℤ) → F, + HasSumLocallyUniformlyOn (multivariableLaurentTerm c) f U → + c = multivariableLaurentCoeff f r) := by + refine ⟨hasSumLocallyUniformlyOn_multivariableLaurent_of_pointwise ho hc hR hf hr hrU + (fun z hz => hasSum_multivariableLaurent ho hc hR hf hr hrU hz), + fun z hz => summable_norm_multivariableLaurent ho hc hR hf hr hrU hz, + multivariableLaurentCoeff_neg_eq_zero ho hc hR hf hr hrU, + fun s hs hsU => multivariableLaurentCoeff_eq_of_radii ho hc hR hf hr hs hrU hsU, + fun c hs => eq_multivariableLaurentCoeff_of_hasSumLocallyUniformlyOn hf.continuousOn hr ?_ hs⟩ + intro z hz + apply hR hrU + intro i + simpa [abs_of_pos (hr i)] using hz i + +/-- Laurent expansion converges uniformly on compact subsets of the original domain. -/ +theorem hasSumUniformlyOn_multivariableLaurent {U K : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) + (hrU : (fun i => (r i : ℂ)) ∈ U) (hK : IsCompact K) (hKU : K ⊆ U) : + HasSumUniformlyOn (multivariableLaurentTerm (multivariableLaurentCoeff f r)) f K := + hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + ((tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK).mp + (((multivariableLaurent_expansion ho hc hR hf hr hrU).1).mono hKU)) + +/-- If a Reinhardt domain meets every coordinate hyperplane, only nonnegative exponents occur in its +Laurent expansion. This is Lemma 2.8.1 applied in each coordinate. -/ +theorem multivariableLaurentCoeff_eq_zero_of_not_nonneg {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + (hmeet : ∀ i, ∃ z ∈ U, z i = 0) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) + (hrU : (fun i => (r i : ℂ)) ∈ U) {m : Fin n → ℤ} (hm : ¬ ∀ i, 0 ≤ m i) : + multivariableLaurentCoeff f r m = 0 := by + push Not at hm + obtain ⟨i, hi⟩ := hm + exact multivariableLaurentCoeff_neg_eq_zero ho hc hR hf hr hrU m i (hmeet i) hi + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Annulus.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Annulus.lean new file mode 100644 index 0000000000..0a5be50c73 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Annulus.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.CauchyIntegral +public import Mathlib.Analysis.Normed.Group.Bounded +public import Mathlib.Topology.Algebra.InfiniteSum.NatInt + +/-! +# Cauchy's formula on an annulus + +Subtracting the value at the evaluation point removes the singularity of the Cauchy kernel. +Cauchy–Goursat on an annulus then gives the difference of the outer and inner Cauchy integrals. + +## Main results + +`circleIntegral_sub_inv_smul_sub_of_analyticOnNhd_annulus` is the annulus formula. +`circleIntegral_sub_inv_eq_zero_of_lt_norm` vanishes the inner integral when the evaluation +point lies outside the inner circle. `hasSum_circleIntegral_geometric` expands the outer kernel +as a geometric series. +-/ + +public noncomputable section + +open Complex Set Metric Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Integrating a divided difference separates the function and constant terms. -/ +private theorem circleIntegral_dslope {f : ℂ → F} {r : ℝ} (hr : 0 ≤ r) + (hf : ContinuousOn f (sphere (0 : ℂ) r)) {z : ℂ} + (hz : ∀ w ∈ sphere (0 : ℂ) r, w ≠ z) : + (∮ w in C(0, r), dslope f z w) = + (∮ w in C(0, r), (w - z)⁻¹ • f w) - + (∮ w in C(0, r), (w - z)⁻¹) • f z := by + have hk : ContinuousOn (fun w : ℂ => (w - z)⁻¹) (sphere 0 r) := + (continuousOn_id.sub continuousOn_const).inv₀ fun w hw => sub_ne_zero.mpr (hz w hw) + have h₁ : CircleIntegrable (fun w => (w - z)⁻¹ • f w) 0 r := + (hk.smul hf).circleIntegrable hr + have h₂ : CircleIntegrable (fun w => (w - z)⁻¹ • f z) 0 r := + (hk.smul continuousOn_const).circleIntegrable hr + rw [← circleIntegral.integral_smul_const, ← circleIntegral.integral_sub h₁ h₂] + apply circleIntegral.integral_congr hr + intro w hw + rw [dslope_of_ne _ (hz w hw), slope_def_module, smul_sub] + +/-- The Cauchy kernel has zero integral on a circle that does not enclose its pole. -/ +theorem circleIntegral_sub_inv_eq_zero_of_lt_norm {r : ℝ} (hr : 0 ≤ r) {z : ℂ} + (hz : r < ‖z‖) : (∮ w in C(0, r), (w - z)⁻¹) = 0 := by + have hd : DifferentiableOn ℂ (fun w : ℂ => (w - z)⁻¹) (closedBall 0 r) := by + intro w hw + apply ((differentiableAt_id.sub_const z).inv ?_).differentiableWithinAt + apply sub_ne_zero.mpr + intro he + change w = z at he + subst w + exact (not_le.mpr hz) (mem_closedBall_zero_iff.mp hw) + exact (hd.mono closure_ball_subset_closedBall).diffContOnCl.circleIntegral_eq_zero hr + +/-- Cauchy's formula between two concentric circles, for Banach-valued functions. -/ +theorem circleIntegral_sub_inv_smul_sub_of_analyticOnNhd_annulus + {f : ℂ → F} {r R : ℝ} (hr : 0 < r) {z : ℂ} + (hzr : r < ‖z‖) (hzR : ‖z‖ < R) + (hf : AnalyticOnNhd ℂ f (closedBall 0 R \ ball 0 r)) : + (∮ w in C(0, R), (w - z)⁻¹ • f w) - + (∮ w in C(0, r), (w - z)⁻¹ • f w) = (2 * Real.pi * I : ℂ) • f z := by + have hz : z ∈ closedBall (0 : ℂ) R \ ball 0 r := by + simp only [Set.mem_sdiff, mem_closedBall_zero_iff, mem_ball_zero_iff, not_lt] + exact ⟨hzR.le, hzr.le⟩ + have hn : closedBall (0 : ℂ) R \ ball 0 r ∈ 𝓝 z := + inter_mem (closedBall_mem_nhds_of_mem (mem_ball_zero_iff.mpr hzR)) + (mem_of_superset + (isClosed_closedBall.isOpen_compl.mem_nhds + (show z ∈ (closedBall (0 : ℂ) r)ᶜ by simpa using hzr)) + (compl_subset_compl.mpr ball_subset_closedBall)) + have hcont := (continuousOn_dslope hn).mpr ⟨hf.continuousOn, (hf z hz).differentiableAt⟩ + have he := circleIntegral_eq_of_differentiable_on_annulus_off_countable hr + (hzr.trans hzR).le (countable_singleton z) hcont (by + intro w hw + apply (differentiableAt_dslope_of_ne (by simpa using hw.2)).mpr + exact (hf w ⟨ball_subset_closedBall hw.1.1, + fun hb => hw.1.2 (ball_subset_closedBall hb)⟩).differentiableAt) + have hs (t : ℝ) (ht : t = r ∨ t = R) : sphere (0 : ℂ) t ⊆ closedBall 0 R \ ball 0 r := by + rintro w hw + have hw' := mem_sphere_zero_iff_norm.mp hw + simp only [Set.mem_sdiff, mem_closedBall_zero_iff, mem_ball_zero_iff, not_lt, hw'] + rcases ht with rfl | rfl <;> constructor <;> linarith + rw [circleIntegral_dslope (hr.trans (hzr.trans hzR)).le + (hf.continuousOn.mono (hs R (Or.inr rfl))) (by + intro w hw he; subst w; exact (ne_of_lt hzR) (mem_sphere_zero_iff_norm.mp hw)), + circleIntegral_dslope hr.le (hf.continuousOn.mono (hs r (Or.inl rfl))) (by + intro w hw he; subst w; exact (ne_of_gt hzr) (mem_sphere_zero_iff_norm.mp hw)), + circleIntegral.integral_sub_inv_of_mem_ball (mem_ball_zero_iff.mpr hzR), + circleIntegral_sub_inv_eq_zero_of_lt_norm hr.le hzr, zero_smul, sub_zero] at he + exact sub_eq_iff_eq_add.mpr (sub_eq_iff_eq_add.mp he |>.trans (add_comm _ _)) + +omit [CompleteSpace F] in +/-- A uniformly contracting scalar kernel can be summed under a circle integral. -/ +theorem hasSum_circleIntegral_geometric {f : ℂ → F} {g : ℂ → ℂ} {r q : ℝ} + (hr : 0 ≤ r) (hf : ContinuousOn f (sphere (0 : ℂ) r)) + (hg : ContinuousOn g (sphere (0 : ℂ) r)) (hq₀ : 0 ≤ q) (hq : q < 1) + (hbound : ∀ w ∈ sphere (0 : ℂ) r, ‖g w‖ ≤ q) : + HasSum (fun n : ℕ => ∮ w in C(0, r), g w ^ n • f w) + (∮ w in C(0, r), (1 - g w)⁻¹ • f w) := by + obtain ⟨M, hM⟩ := (isCompact_sphere (0 : ℂ) r).exists_bound_of_continuousOn hf + have hfc : Continuous (fun θ => f (circleMap 0 r θ)) := + hf.comp_continuous (continuous_circleMap _ _) (circleMap_mem_sphere _ hr) + have hgc : Continuous (fun θ => g (circleMap 0 r θ)) := + hg.comp_continuous (continuous_circleMap _ _) (circleMap_mem_sphere _ hr) + refine intervalIntegral.hasSum_integral_of_dominated_convergence + (fun n _ => r * (q ^ n * M)) (fun n => ?_) (fun n => ?_) ?_ ?_ ?_ + · apply Continuous.aestronglyMeasurable + simp only [deriv_circleMap] + exact ((continuous_circleMap 0 r).mul_const I).smul ((hgc.pow n).smul hfc) + · refine .of_forall fun θ _ => ?_ + simp only [norm_smul, norm_pow] + have hd : ‖deriv (circleMap 0 r) θ‖ = r := by simp [deriv_circleMap, abs_of_nonneg hr] + rw [hd] + gcongr + · exact hbound _ (circleMap_mem_sphere _ hr θ) + · exact hM _ (circleMap_mem_sphere _ hr θ) + · exact .of_forall fun _ _ => + ((summable_geometric_of_lt_one hq₀ hq).mul_right M).mul_left r + · exact intervalIntegrable_const + · refine .of_forall fun θ _ => ?_ + exact ((hasSum_geometric_of_norm_lt_one + ((hbound _ (circleMap_mem_sphere _ hr θ)).trans_lt hq)).smul_const _).const_smul _ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Basic.lean new file mode 100644 index 0000000000..2d1ce3bd0c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Basic.lean @@ -0,0 +1,216 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.Pi +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc + +/-! +# Torus coefficients for Laurent series + +Integer-indexed coefficients are defined by integration on a coordinate torus. Their bounds and +their action on monomials do not require a Laurent expansion theorem. Negative powers are +written `z i ^ (-m i - 1)` in the integrand; this is compatible with Lean's totalized integer +powers at zero once the torus avoids the coordinate hyperplanes. + +## Main results + +`multivariableLaurentCoeff` is the coefficient of multi-index `m` on the torus of radii `r`. +`multivariableLaurentTerm` is the corresponding monomial term. +`norm_multivariableLaurentCoeff_le` is the Cauchy bound. `multivariableLaurentCoeff_monomial` +evaluates the coefficient on a monomial. `multivariableLaurentCoeff_fin_one` recovers the +one-variable `circleLaurentCoeff`. +-/ + +public noncomputable section + +open Complex Set MeasureTheory Metric +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The Laurent coefficient obtained by integrating over a positive-radius coordinate torus. -/ +@[expose] def multivariableLaurentCoeff (f : (Fin n → ℂ) → F) (r : Fin n → ℝ) + (m : Fin n → ℤ) : F := + ((2 * π * I : ℂ) ^ n)⁻¹ • + torusIntegral (fun z => (∏ i, z i ^ (-m i - 1)) • f z) 0 r + +omit [CompleteSpace F] in +/-- The multivariable circle coefficient in dimension one is the ordinary Laurent coefficient. -/ +theorem multivariableLaurentCoeff_fin_one (f : ℂ → F) (r : ℝ) (k : ℤ) : + multivariableLaurentCoeff (fun z : Fin 1 → ℂ => f (z 0)) (fun _ => r) (fun _ => k) = + circleLaurentCoeff f r k := by + simp [multivariableLaurentCoeff, torusIntegral_dim1, circleLaurentCoeff] + +/-- An integer-indexed Laurent term. Negative powers at zero are totalized; the expansion theorem +separately forces their coefficients to vanish whenever necessary. -/ +@[expose] def multivariableLaurentTerm (c : (Fin n → ℤ) → F) (m : Fin n → ℤ) (z : Fin n → ℂ) : F := + (∏ i, z i ^ m i) • c m + +omit [CompleteSpace F] in +/-- Cauchy's bound for an integer-indexed torus coefficient. -/ +theorem norm_multivariableLaurentCoeff_le {f : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (hr : ∀ i, 0 < r i) {M : ℝ} (hM : ∀ θ, ‖f (torusMap 0 r θ)‖ ≤ M) + (m : Fin n → ℤ) : ‖multivariableLaurentCoeff f r m‖ ≤ M * ∏ i, r i ^ (-m i) := by + have hker (θ : Fin n → ℝ) : ‖∏ i, torusMap 0 r θ i ^ (-m i - 1)‖ = + ∏ i, r i ^ (-m i - 1) := by + simp [norm_prod, norm_zpow, torusMap, abs_of_pos (hr _)] + rw [multivariableLaurentCoeff, norm_smul] + refine (mul_le_mul_of_nonneg_left (norm_torusIntegral_le_of_norm_le_const + (C := M * ∏ i, r i ^ (-m i - 1)) ?_) (norm_nonneg _)).trans_eq ?_ + · intro θ + rw [norm_smul, hker] + exact (mul_le_mul_of_nonneg_left (hM θ) + (Finset.prod_nonneg fun i _ => zpow_nonneg (hr i).le _)).trans_eq (mul_comm _ _) + · simp only [norm_inv, norm_pow, norm_mul, norm_ofNat, norm_real, norm_I, mul_one, + Real.norm_eq_abs, abs_of_pos Real.pi_pos, abs_of_pos (hr _)] + have hp : (∏ i, r i) * (∏ i, r i ^ (-m i - 1)) = ∏ i, r i ^ (-m i) := by + rw [← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i _ + calc + r i * r i ^ (-m i - 1) = r i ^ (1 : ℤ) * r i ^ (-m i - 1) := by rw [zpow_one] + _ = r i ^ (-m i) := by rw [← zpow_add₀ (hr i).ne']; congr 1; omega + calc + ((2 * π) ^ n)⁻¹ * (((2 * π) ^ n * ∏ i, r i) * (M * ∏ i, r i ^ (-m i - 1))) = + M * ((∏ i, r i) * ∏ i, r i ^ (-m i - 1)) := by field_simp + _ = _ := by rw [hp] + +/-- A product of scalar functions separates into a product of circle integrals. -/ +theorem torusIntegral_prod (g : Fin n → ℂ → ℂ) (r : Fin n → ℝ) : + torusIntegral (fun z => ∏ i, g i (z i)) 0 r = + ∏ i, ∮ w in C(0, r i), g i w := by + have hbox : Icc (0 : Fin n → ℝ) (fun _ => 2 * π) = + Set.pi univ (fun _ : Fin n => Icc (0 : ℝ) (2 * π)) := by ext θ; simp [Set.mem_Icc, Pi.le_def] + simp only [torusIntegral, smul_eq_mul, ← Finset.prod_mul_distrib] + simp only [torusMap, Pi.zero_apply, zero_add] + rw [hbox, volume_pi, Measure.restrict_pi_pi, integral_fintype_prod_eq_prod + (fun i (θ : ℝ) => (r i : ℂ) * exp (θ * I) * I * g i ((r i : ℂ) * exp (θ * I)))] + apply Finset.prod_congr rfl + intro i _ + rw [circleIntegral_def_Icc] + congr 1 + funext θ + simp [circleMap, deriv_circleMap] + +/-- Integer monomials have zero torus integral unless every exponent is `-1`. -/ +theorem torusIntegral_zpow_prod (r : Fin n → ℝ) (hr : ∀ i, 0 < r i) (m : Fin n → ℤ) : + torusIntegral (fun z => ∏ i, z i ^ m i) 0 r = + ∏ i, if m i = -1 then (2 * π * I : ℂ) else 0 := by + rw [torusIntegral_prod (fun i w => w ^ m i)] + apply Finset.prod_congr rfl + intro i _ + by_cases hi : m i = -1 + · simp only [hi, ite_true, zpow_neg_one] + simpa using circleIntegral.integral_sub_inv_of_mem_ball (mem_ball_self (x := (0 : ℂ)) (hr i)) + · simp only [hi, ite_false] + simpa using circleIntegral.integral_sub_zpow_of_ne hi 0 0 (r i) + +omit [CompleteSpace F] in +/-- Torus integrals depend only on values on the parametrized torus. -/ +theorem torusIntegral_congr {f g : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (h : ∀ θ, f (torusMap 0 r θ) = g (torusMap 0 r θ)) : + torusIntegral f 0 r = torusIntegral g 0 r := by + unfold torusIntegral + apply integral_congr_ae + exact Filter.Eventually.of_forall fun θ => congrArg (_ • ·) (h θ) + +/-- A constant vector can be taken outside a scalar torus integral. -/ +theorem torusIntegral_smul_const (f : (Fin n → ℂ) → ℂ) (r : Fin n → ℝ) (v : F) : + torusIntegral (fun z => f z • v) 0 r = torusIntegral f 0 r • v := by + simp only [torusIntegral, ← smul_assoc, integral_smul_const] + +/-- A Laurent monomial has exactly its prescribed coefficient on every positive torus. -/ +theorem multivariableLaurentCoeff_monomial (r : Fin n → ℝ) (hr : ∀ i, 0 < r i) + (k m : Fin n → ℤ) (v : F) : + multivariableLaurentCoeff (fun z => (∏ i, z i ^ k i) • v) r m = + if m = k then v else 0 := by + classical + have he : torusIntegral (fun z => (∏ i, z i ^ (-m i - 1)) • ((∏ i, z i ^ k i) • v)) 0 r = + torusIntegral (fun z => (∏ i, z i ^ (k i - m i - 1)) • v) 0 r := by + apply torusIntegral_congr + intro θ + rw [smul_smul, ← Finset.prod_mul_distrib] + congr 1 + apply Finset.prod_congr rfl + intro i _ + have hi : torusMap 0 r θ i ≠ 0 := by simp [torusMap, (hr i).ne'] + rw [← zpow_add₀ hi] + congr 1 + omega + rw [multivariableLaurentCoeff, he, torusIntegral_smul_const, torusIntegral_zpow_prod r hr] + by_cases hmk : m = k + · subst m + simp only [sub_self, zero_sub, ite_true, Fin.prod_const] + exact inv_smul_smul₀ (pow_ne_zero _ two_pi_I_ne_zero) v + · rw [ite_eq_right hmk] + have hi : ∃ i, m i ≠ k i := Function.ne_iff.mp hmk + obtain ⟨i, hi⟩ := hi + have hp : (∏ i, if k i - m i - 1 = -1 then (2 * π * I : ℂ) else 0) = 0 := by + apply Finset.prod_eq_zero (Finset.mem_univ i) + rw [ite_eq_right (by omega)] + rw [hp, zero_smul, smul_zero] + +omit [CompleteSpace F] in +/-- Multiplying by an integer monomial preserves continuity along a positive torus. -/ +theorem continuous_laurentMonomial_smul_torus {f : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (hr : ∀ i, 0 < r i) (hf : Continuous (fun θ => f (torusMap 0 r θ))) (m : Fin n → ℤ) : + Continuous (fun θ => (∏ i, torusMap 0 r θ i ^ m i) • f (torusMap 0 r θ)) := by + apply Continuous.smul _ hf + apply continuous_finsetProd + intro i _ + exact ((continuous_apply i).comp (continuous_torusMap 0 r)).zpow₀ _ + (fun θ => Or.inl (by simp [torusMap, (hr i).ne'])) + +omit [CompleteSpace F] in +/-- A continuous function on a positive torus has integrable Laurent kernels. -/ +theorem torusIntegrable_laurentKernel {f : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (hr : ∀ i, 0 < r i) (hf : Continuous (fun θ => f (torusMap 0 r θ))) (m : Fin n → ℤ) : + TorusIntegrable (fun z => (∏ i, z i ^ (-m i - 1)) • f z) 0 r := + ((continuous_laurentMonomial_smul_torus hr hf (fun i => -m i - + 1)).continuousOn).integrableOn_compact + isCompact_Icc + +omit [CompleteSpace F] in +/-- Laurent coefficients commute with finite sums of functions continuous on the torus. -/ +theorem multivariableLaurentCoeff_sum {α : Type*} (s : Finset α) + {f : α → (Fin n → ℂ) → F} {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) + (hf : ∀ a ∈ s, Continuous (fun θ => f a (torusMap 0 r θ))) (m : Fin n → ℤ) : + multivariableLaurentCoeff (fun z => ∑ a ∈ s, f a z) r m = + ∑ a ∈ s, multivariableLaurentCoeff (f a) r m := by + simp only [multivariableLaurentCoeff, torusIntegral, Finset.smul_sum] + rw [integral_finsetSum] + · exact Finset.smul_sum + · intro a ha + exact (torusIntegrable_laurentKernel hr (hf a ha) m).function_integrable + +omit [CompleteSpace F] in +/-- Laurent coefficients commute with subtraction for functions continuous on the torus. -/ +theorem multivariableLaurentCoeff_sub {f g : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (hr : ∀ i, 0 < r i) (hf : Continuous (fun θ => f (torusMap 0 r θ))) + (hg : Continuous (fun θ => g (torusMap 0 r θ))) (m : Fin n → ℤ) : + multivariableLaurentCoeff (fun z => f z - g z) r m = + multivariableLaurentCoeff f r m - multivariableLaurentCoeff g r m := by + simp only [multivariableLaurentCoeff, smul_sub] + rw [torusIntegral_sub (torusIntegrable_laurentKernel hr hf m) + (torusIntegrable_laurentKernel hr hg m), smul_sub] + +omit [CompleteSpace F] in +/-- Laurent coefficients depend only on values on their coefficient torus. -/ +theorem multivariableLaurentCoeff_congr {f g : (Fin n → ℂ) → F} {r : Fin n → ℝ} + (h : ∀ θ, f (torusMap 0 r θ) = g (torusMap 0 r θ)) : + multivariableLaurentCoeff f r = multivariableLaurentCoeff g r := by + funext m + unfold multivariableLaurentCoeff + congr 1 + exact torusIntegral_congr fun θ => congrArg (_ • ·) (h θ) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Coefficients.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Coefficients.lean new file mode 100644 index 0000000000..f17b09b56e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Coefficients.lean @@ -0,0 +1,114 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.LocallyConstant.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected + +/-! +# Global Laurent coefficients on Reinhardt domains + +The space of admissible positive radii is connected. Local independence on circular product +neighborhoods therefore gives global independence of the coefficient torus. + +## Main results + +`IsReinhardt.isConnected_positive_radii` is connectedness of the positive radius vectors in a +connected open Reinhardt domain. `multivariableLaurentCoeff_eq_of_radii` is independence of the +torus. `multivariableLaurentCoeff_neg_eq_zero` vanishes coefficients with a negative exponent in +a coordinate that meets a hyperplane. +-/ + +public noncomputable section + +open Complex Set Metric Filter +open scoped Topology NNReal + +namespace SeveralComplexVariables + +/-- Positive radius vectors of a connected open Reinhardt domain form a connected set. -/ +theorem IsReinhardt.isConnected_positive_radii {n : ℕ} {U : Set (Fin n → ℂ)} + (hR : IsReinhardt U) (ho : IsOpen U) (hc : IsPreconnected U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) : + IsConnected {s : Fin n → ℝ | (∀ i, 0 < s i) ∧ (fun i => (s i : ℂ)) ∈ U} := by + have hp : AnalyticOnNhd ℂ (fun z : Fin n → ℂ => ∏ i, z i) U := by + intro z _ + apply Finset.analyticAt_fun_prod + intro i _ + exact (ContinuousLinearMap.proj (R := ℂ) i).analyticAt z + have hconn := isConnected_nonzero_of_analyticOnNhd ho hc hp + ⟨fun i => (r i : ℂ), hrU, Finset.prod_ne_zero_iff.mpr (fun i _ => by exact_mod_cast (hr i).ne')⟩ + have he : (fun z : Fin n → ℂ => fun i => ‖z i‖) '' (U \ (fun z => ∏ i, z i) ⁻¹' {0}) = + {s : Fin n → ℝ | (∀ i, 0 < s i) ∧ (fun i => (s i : ℂ)) ∈ U} := by + ext s + constructor + · rintro ⟨z, ⟨hz, hn⟩, rfl⟩ + have hn' : ∏ i, z i ≠ 0 := hn + exact ⟨fun i => norm_pos_iff.mpr ((Finset.prod_ne_zero_iff.mp hn') i (Finset.mem_univ _)), + hR hz (fun i => by simp)⟩ + · rintro ⟨hs, hsU⟩ + refine ⟨fun i => (s i : ℂ), ⟨hsU, ?_⟩, ?_⟩ + · exact Finset.prod_ne_zero_iff.mpr (fun i _ => by exact_mod_cast (hs i).ne') + · funext i; simp [abs_of_pos (hs i)] + rw [← he] + exact hconn.image _ (by fun_prop) + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Laurent coefficients on a connected Reinhardt domain are independent of the torus. The proof +uses local Cauchy–Goursat and connectedness, not Laurent expansion. -/ +theorem multivariableLaurentCoeff_eq_of_radii {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r s : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hs : ∀ i, 0 < s i) + (hrU : (fun i => (r i : ℂ)) ∈ U) (hsU : (fun i => (s i : ℂ)) ∈ U) : + multivariableLaurentCoeff f s = multivariableLaurentCoeff f r := by + let D : Set (Fin n → ℝ) := {t | (∀ i, 0 < t i) ∧ (fun i => (t i : ℂ)) ∈ U} + have hD : IsConnected D := hR.isConnected_positive_radii ho hc hr hrU + let : PreconnectedSpace D := isPreconnected_iff_preconnectedSpace.mp hD.isPreconnected + let g : D → ((Fin n → ℤ) → F) := fun t => multivariableLaurentCoeff f t.val + have hg : IsLocallyConstant g := by + apply (IsLocallyConstant.iff_eventually_eq g).mpr + intro t + obtain ⟨V, hVo, hVc, hVr, htV, hVU⟩ := + hR.exists_circular_product_neighborhood ho t.property.2 + have hv : IsOpen (Set.pi univ V) := isOpen_set_pi finite_univ (fun i _ => hVo i) + have ht : ∀ᶠ u : D in 𝓝 t, (fun i => (u.val i : ℂ)) ∈ Set.pi univ V := + (hv.preimage (continuous_pi fun i => Complex.continuous_ofReal.comp + ((continuous_apply i).comp continuous_subtype_val))).mem_nhds htV + filter_upwards [ht] with u hu + exact multivariableLaurentCoeff_eq_on_product hVo hVc hVr (hf.mono hVU) + t.property.1 u.property.1 (fun i => htV i (mem_univ _)) (fun i => hu i (mem_univ _)) + exact hg.apply_eq_of_preconnectedSpace ⟨s, hs, hsU⟩ ⟨r, hr, hrU⟩ + +/-- Meeting a coordinate hyperplane forces every negative coefficient in that coordinate to vanish. +This follows from the circle Cauchy theorem on a local product neighborhood. -/ +theorem multivariableLaurentCoeff_neg_eq_zero {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + (m : Fin n → ℤ) (i : Fin n) (hzero : ∃ z ∈ U, z i = 0) (hm : m i < 0) : + multivariableLaurentCoeff f r m = 0 := by + obtain ⟨z, hz, hzi⟩ := hzero + obtain ⟨V, hVo, hVc, hVr, hzV, hVU⟩ := hR.exists_circular_product_neighborhood ho hz + have hprod : IsReinhardt (Set.pi univ V) := by + intro x hx y hy j _ + exact hVr j _ (hx j (mem_univ _)) _ (hy j) + obtain ⟨s, hsV, hs⟩ := hprod.exists_strict_modulus_majorant + (isOpen_set_pi finite_univ (fun i _ => hVo i)) hzV + have hspos (j : Fin n) : 0 < (s j : ℝ) := by + exact_mod_cast (show (0 : ℝ≥0) ≤ ‖z j‖₊ from zero_le).trans_lt (hs j) + have he := multivariableLaurentCoeff_eq_of_radii ho hc hR hf hr hspos hrU (hVU hsV) + rw [← he] + exact multivariableLaurentCoeff_neg_on_product hVo hVc hVr (hf.mono hVU) hspos + (fun j => hsV j (mem_univ _)) m i (by simpa only [hzi] using hzV i (mem_univ _)) hm + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Convergence.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Convergence.lean new file mode 100644 index 0000000000..8c9052bfdf --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Convergence.lean @@ -0,0 +1,229 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Ring.InfiniteSum +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Normal convergence of Laurent coefficient families + +Inner and outer coefficient tori bound the two halves of each coordinate series by geometric +sequences. Their finite products give summable local majorants. + +## Main results + +`exists_local_laurent_majorant` produces a geometric bound from inner and outer tori. +`summable_norm_multivariableLaurent` is absolute summability of the terms. +`hasSumLocallyUniformlyOn_multivariableLaurent_of_pointwise` upgrades a pointwise summable +expansion to locally uniform convergence. +-/ + +public noncomputable section + +open Complex Set Metric Filter +open scoped Real Topology + +namespace SeveralComplexVariables + +/-- A finite product of nonnegative summable families is summable over all tuples. -/ +private theorem summable_fin_prod_of_nonneg {n : ℕ} (b : Fin n → ℤ → ℝ) + (hb : ∀ i, Summable (b i)) (hb₀ : ∀ i k, 0 ≤ b i k) : + Summable (fun m : Fin n → ℤ => ∏ i, b i (m i)) := by + induction n with + | zero => exact Summable.of_finite + | succ n ih => + have h := (hb 0).mul_of_nonneg (ih (fun i => b i.succ) (fun i => hb i.succ) + (fun i => hb₀ i.succ)) (hb₀ 0) (fun m => Finset.prod_nonneg (fun i _ => hb₀ i.succ (m i))) + apply (Fin.consEquiv (fun _ : Fin (n + 1) => ℤ)).summable_iff.mp + simpa [Fin.consEquiv, Fin.prod_univ_succ, Function.comp_def] using h + +/-- Positive and negative geometric tails give a summable integer-indexed family. -/ +private theorem summable_two_sided_geometric {p q : ℝ} + (hp₀ : 0 ≤ p) (hp : p < 1) (hq₀ : 0 ≤ q) (hq : q < 1) : + Summable (Int.rec (fun n => p ^ n) (fun n => q ^ (n + 1))) := by + apply (summable_geometric_of_lt_one hp₀ hp).int_rec + simpa only [pow_succ] using (summable_geometric_of_lt_one hq₀ hq).mul_right q + +/-- A scalar Laurent factor is controlled by its inner or outer geometric ratio. -/ +private theorem zpow_mul_corner_le {a b t T u : ℝ} + (ha : 0 < a) (hb : 0 < b) (ht : 0 < t) (hu : 0 ≤ u) + (huT : u ≤ T) (k : ℤ) (htu : k < 0 → t ≤ u) : + u ^ k * (if k < 0 then a else b) ^ (-k) ≤ + Int.rec (fun n => (T / b) ^ n) (fun n => (a / t) ^ (n + 1)) k := by + cases k with + | ofNat n => + simp only [zpow_neg] + calc + u ^ n * (b ^ n)⁻¹ ≤ T ^ n * (b ^ n)⁻¹ := by gcongr + _ = (T / b) ^ n := by simp [div_eq_mul_inv, mul_pow] + | negSucc n => + have htu' := htu (by omega) + simp only [Int.negSucc_lt_zero, ite_true, Int.neg_negSucc, zpow_natCast, zpow_negSucc] + calc + (u ^ (n + 1))⁻¹ * a ^ (n + 1) ≤ (t ^ (n + 1))⁻¹ * a ^ (n + 1) := by gcongr + _ = (a / t) ^ (n + 1) := by simp only [div_eq_mul_inv]; ring + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Corner coefficient bounds give a product geometric bound for every Laurent term. -/ +private theorem norm_laurentTerm_le_geometric {c : (Fin n → ℤ) → F} + {a b t T : Fin n → ℝ} (ha : ∀ i, 0 < a i) (hb : ∀ i, 0 < b i) + (ht : ∀ i, 0 < t i) (hT : ∀ i, 0 ≤ T i) {M : ℝ} (hM : 0 ≤ M) + {z w : Fin n → ℂ} (hwT : ∀ i, ‖w i‖ ≤ T i) + (htw : ∀ i, z i ≠ 0 → t i ≤ ‖w i‖) (m : Fin n → ℤ) + (hzero : ∀ i, z i = 0 → m i < 0 → c m = 0) + (hc : ‖c m‖ ≤ M * ∏ i, (if m i < 0 then a i else b i) ^ (-m i)) : + ‖multivariableLaurentTerm c m w‖ ≤ + M * ∏ i, Int.rec (fun n => (T i / b i) ^ n) (fun n => (a i / t i) ^ (n + 1)) (m i) := by + have hgeom (i : Fin n) : + (0 : ℝ) ≤ Int.rec (fun n => (T i / b i) ^ n) (fun n => (a i / t i) ^ (n + 1)) (m i) := by + cases m i with + | ofNat k => exact pow_nonneg (div_nonneg (hT i) (hb i).le) _ + | negSucc k => exact pow_nonneg (div_nonneg (ha i).le (ht i).le) _ + by_cases hbad : ∃ i, z i = 0 ∧ m i < 0 + · obtain ⟨i, hi, hm⟩ := hbad + rw [multivariableLaurentTerm, hzero i hi hm, smul_zero, norm_zero] + exact mul_nonneg hM (Finset.prod_nonneg fun i _ => hgeom i) + · rw [multivariableLaurentTerm, norm_smul, norm_prod] + simp only [norm_zpow] + calc + (∏ i, ‖w i‖ ^ m i) * ‖c m‖ ≤ + (∏ i, ‖w i‖ ^ m i) * (M * ∏ i, (if m i < 0 then a i else b i) ^ (-m i)) := + mul_le_mul_of_nonneg_left hc (Finset.prod_nonneg fun i _ => zpow_nonneg (norm_nonneg _) _) + _ = M * ∏ i, ‖w i‖ ^ m i * (if m i < 0 then a i else b i) ^ (-m i) := by + rw [Finset.prod_mul_distrib]; ring + _ ≤ _ := by + apply mul_le_mul_of_nonneg_left _ hM + apply Finset.prod_le_prod₀ + · intro i _ + apply mul_nonneg (zpow_nonneg (norm_nonneg _) _) + apply zpow_nonneg + split_ifs + · exact (ha i).le + · exact (hb i).le + · intro i _ + exact zpow_mul_corner_le (ha i) (hb i) (ht i) (norm_nonneg _) (hwT i) (m i) + (fun hm => htw i (fun hi => hbad ⟨i, hi, hm⟩)) + +omit [NormedSpace ℂ F] in +/-- The finitely many corner tori of a circular product share a bound for a continuous function. -/ +private theorem exists_bound_torus_corners {V : Fin n → Set ℂ} + (hrot : ∀ i, ∀ v ∈ V i, ∀ w : ℂ, ‖w‖ = ‖v‖ → w ∈ V i) + {a b : Fin n → ℝ} (ha : ∀ i, 0 < a i) (hb : ∀ i, 0 < b i) + (haV : ∀ i, (a i : ℂ) ∈ V i) (hbV : ∀ i, (b i : ℂ) ∈ V i) + {f : (Fin n → ℂ) → F} (hf : ContinuousOn f (Set.pi univ V)) : + ∃ M : ℝ, 0 ≤ M ∧ ∀ p : Fin n → Bool, ∀ θ, + ‖f (torusMap 0 (fun i => if p i then a i else b i) θ)‖ ≤ M := by + let r (p : Fin n → Bool) (i : Fin n) := if p i then a i else b i + have hr (p : Fin n → Bool) (i : Fin n) : 0 < r p i := by + dsimp [r]; split_ifs <;> [exact ha i; exact hb i] + have hrV (p : Fin n → Bool) (i : Fin n) : (r p i : ℂ) ∈ V i := by + dsimp [r]; split_ifs <;> [exact haV i; exact hbV i] + let K (p : Fin n → Bool) := {w : Fin n → ℂ | ∀ i, w i ∈ sphere 0 (r p i)} + have hKV (p : Fin n → Bool) : K p ⊆ Set.pi univ V := by + intro w hw i _ + apply hrot i _ (hrV p i) _ + simpa [abs_of_pos (hr p i)] using hw i + have hbound (p : Fin n → Bool) : ∃ M : ℝ, ∀ w ∈ K p, ‖f w‖ ≤ M := + (isCompact_pi_infinite fun i => isCompact_sphere (0 : ℂ) (r p i)).exists_bound_of_continuousOn + (hf.mono (hKV p)) + choose M hM using hbound + refine ⟨∑ p, max (M p) 0, Finset.sum_nonneg (fun p _ => le_max_right _ _), ?_⟩ + intro p θ + apply (hM p _ (fun i => by + change torusMap 0 (r p) θ i ∈ sphere 0 (r p i) + simp [torusMap, abs_of_pos (hr p i)])).trans + exact (le_max_left _ _).trans (Finset.single_le_sum + (fun q _ => le_max_right (M q) 0) (Finset.mem_univ p)) + +variable [CompleteSpace F] + +/-- Every point has a neighborhood on which the Laurent terms admit a summable majorant. -/ +theorem exists_local_laurent_majorant {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + {z : Fin n → ℂ} (hz : z ∈ U) : + ∃ N : Set (Fin n → ℂ), N ∈ 𝓝 z ∧ N ⊆ U ∧ + ∃ B : (Fin n → ℤ) → ℝ, Summable B ∧ ∀ m, ∀ w ∈ N, + ‖multivariableLaurentTerm (multivariableLaurentCoeff f r) m w‖ ≤ B m := by + obtain ⟨V, hVo, hVc, hVr, hzV, hVU⟩ := hR.exists_circular_product_neighborhood ho hz + choose a b t T ha hat hT hTb haV hbV hzT htz using + fun i => exists_circular_radii_bounds (hVo i) (hVr i) (hzV i (mem_univ _)) + have hb (i) : 0 < b i := (hT i).trans (hTb i) + have ht (i) : 0 < t i := (ha i).trans (hat i) + obtain ⟨M, hM, hcorner⟩ := exists_bound_torus_corners hVr ha hb haV hbV (hf.continuousOn.mono hVU) + let W : Fin n → Set ℂ := fun i => {w | ‖w‖ < T i ∧ (z i ≠ 0 → t i < ‖w‖)} + have hWo (i) : IsOpen (W i) := by + by_cases hzi : z i = 0 + · simpa [W, hzi] using isOpen_lt (f := fun w : ℂ => ‖w‖) continuous_norm + (g := fun _ => T i) continuous_const + · simp only [W, hzi, ne_eq, not_false_eq_true, true_implies] + exact (isOpen_lt (f := fun w : ℂ => ‖w‖) continuous_norm + (g := fun _ => T i) continuous_const).inter + (isOpen_lt (f := fun _ : ℂ => t i) continuous_const continuous_norm) + let B (m : Fin n → ℤ) := + M * ∏ i, Int.rec (fun k => (T i / b i) ^ k) (fun k => (a i / t i) ^ (k + 1)) (m i) + have hB : Summable B := by + apply Summable.mul_left M + apply summable_fin_prod_of_nonneg + · intro i + exact summable_two_sided_geometric (div_nonneg (hT i).le (hb i).le) + ((div_lt_one (hb i)).mpr (hTb i)) (div_nonneg (ha i).le (ht i).le) + ((div_lt_one (ht i)).mpr (hat i)) + · intro i k + cases k with + | ofNat k => exact pow_nonneg (div_nonneg (hT i).le (hb i).le) _ + | negSucc k => exact pow_nonneg (div_nonneg (ha i).le (ht i).le) _ + refine ⟨Set.pi univ W ∩ U, + ((isOpen_set_pi finite_univ (fun i _ => hWo i)).inter ho).mem_nhds + ⟨fun i _ => ⟨hzT i, htz i⟩, hz⟩, inter_subset_right, B, hB, ?_⟩ + intro m w hw + apply norm_laurentTerm_le_geometric ha hb ht (fun i => (hT i).le) hM + (fun i => (hw.1 i (mem_univ _)).1.le) + (fun i hi => ((hw.1 i (mem_univ _)).2 hi).le) m + · intro i hzi hmi + exact multivariableLaurentCoeff_neg_eq_zero ho hc hR hf hr hrU m i ⟨z, hz, hzi⟩ hmi + · let q (i : Fin n) := if m i < 0 then a i else b i + have hq (i) : 0 < q i := by dsimp [q]; split_ifs <;> [exact ha i; exact hb i] + have hqV : (fun i => (q i : ℂ)) ∈ Set.pi univ V := by + intro i _; dsimp [q]; split_ifs <;> [exact haV i; exact hbV i] + rw [← multivariableLaurentCoeff_eq_of_radii ho hc hR hf hr hq hrU (hVU hqV)] + apply norm_multivariableLaurentCoeff_le hq + intro θ + simpa [q] using hcorner (fun i => decide (m i < 0)) θ + +/-- The Laurent expansion family is absolutely summable at every point of the domain. -/ +theorem summable_norm_multivariableLaurent {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + {z : Fin n → ℂ} (hz : z ∈ U) : + Summable (fun m => ‖multivariableLaurentTerm (multivariableLaurentCoeff f r) m z‖) := by + obtain ⟨N, hN, _, B, hB, hb⟩ := exists_local_laurent_majorant ho hc hR hf hr hrU hz + exact hB.of_nonneg_of_le (fun _ => norm_nonneg _) (fun m => hb m z (mem_of_mem_nhds hN)) + +/-- Pointwise Laurent expansion with torus coefficients automatically converges locally +uniformly. -/ +theorem hasSumLocallyUniformlyOn_multivariableLaurent_of_pointwise {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + (hsum : ∀ z ∈ U, HasSum (fun m => multivariableLaurentTerm (multivariableLaurentCoeff f r) m + z) (f z)) : + HasSumLocallyUniformlyOn (multivariableLaurentTerm (multivariableLaurentCoeff f r)) f U := by + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro z hz + obtain ⟨N, hN, hNU, B, hB, hb⟩ := exists_local_laurent_majorant ho hc hR hf hr hrU hz + refine ⟨N, mem_nhdsWithin_of_mem_nhds hN, ?_⟩ + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + exact (tendstoUniformlyOn_tsum hB hb).congr_right (fun w hw => (hsum w (hNU hw)).tsum_eq) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Iterated.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Iterated.lean new file mode 100644 index 0000000000..849e637c12 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Iterated.lean @@ -0,0 +1,99 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic + +/-! +# Iterated Laurent coefficients + +Fubini's theorem writes a torus integral with the first circle integrated first. Consequently +Laurent coefficients can be computed one coordinate at a time. + +## Main results + +`torusIntegral_succ_inner` is Fubini for the first circle of a coordinate torus. +`multivariableLaurentCoeff_succ` identifies the multivariable coefficient with an iterated +one-variable coefficient in the remaining coordinates. +-/ + +public noncomputable section + +open Complex Set MeasureTheory Function +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +omit [CompleteSpace F] in +/-- A torus integral can be evaluated by first integrating the first coordinate circle. -/ +theorem torusIntegral_succ_inner {f : (Fin (n + 1) → ℂ) → F} + {c : Fin (n + 1) → ℂ} {r : Fin (n + 1) → ℝ} (hf : TorusIntegrable f c r) : + torusIntegral f c r = torusIntegral + (fun y => ∮ x in C(c 0, r 0), f (Fin.cons x y)) (c ∘ Fin.succ) (r ∘ Fin.succ) := by + let e : ℝ × (Fin n → ℝ) ≃ᵐ (Fin (n + 1) → ℝ) := + (MeasurableEquiv.piFinSuccAbove (fun _ => ℝ) 0).symm + have hem : MeasurePreserving e := + (volume_preserving_piFinSuccAbove (fun _ : Fin (n + 1) => ℝ) 0).symm _ + have heπ : e ⁻¹' Icc 0 (fun _ => 2 * π) = + Icc 0 (2 * π) ×ˢ Icc (0 : Fin n → ℝ) (fun _ => 2 * π) := + ((Fin.insertNthOrderIso (fun _ => ℝ) 0).preimage_Icc _ _).trans (Icc_prod_eq _ _) + rw [torusIntegral, ← hem.map_eq, setIntegral_map_equiv, heπ, Measure.volume_eq_prod, + ← setIntegral_prod_swap, setIntegral_prod] + · rw [torusIntegral] + refine setIntegral_congr_fun measurableSet_Icc fun Θ _ => ?_ + simp only [circleIntegral_def_Icc, ← integral_smul] + refine setIntegral_congr_fun measurableSet_Icc fun θ _ => ?_ + simp only [e, MeasurableEquiv.piFinSuccAbove_symm_apply, Fin.insertNth_zero, + Fin.insertNthEquiv, Equiv.coe_fn_mk, Fin.prod_univ_succ, Fin.cons_zero, Fin.cons_succ, + Function.comp_apply, deriv_circleMap, smul_smul] + congr 1 + · simp [circleMap, mul_assoc, mul_comm] + · congr 1 + funext i + refine Fin.cases ?_ (fun j => ?_) i <;> simp [torusMap, circleMap] + · have h := hf.function_integrable + rw [← hem.integrableOn_comp_preimage e.measurableEmbedding, heπ] at h + exact h.swap + +omit [CompleteSpace F] in +/-- A multivariable Laurent coefficient is obtained by taking a circle coefficient first. -/ +theorem multivariableLaurentCoeff_succ {f : (Fin (n + 1) → ℂ) → F} + {r : Fin (n + 1) → ℝ} (hr : ∀ i, 0 < r i) + (hf : Continuous (fun θ => f (torusMap 0 r θ))) (m : Fin (n + 1) → ℤ) : + multivariableLaurentCoeff f r m = + multivariableLaurentCoeff + (fun y => circleLaurentCoeff (fun x => f (Fin.cons x y)) (r 0) (m 0)) + (r ∘ Fin.succ) (m ∘ Fin.succ) := by + let g (y : Fin n → ℂ) := ∮ x in C(0, r 0), x ^ (-m 0 - 1) • f (Fin.cons x y) + let b (y : Fin n → ℂ) := ∏ i, y i ^ (-m i.succ - 1) + have hcircle (y : Fin n → ℂ) : + (∮ x in C(0, r 0), (∏ i, (Fin.cons x y : Fin (n + 1) → ℂ) i ^ (-m i - 1)) • f (Fin.cons x + y)) = + b y • g y := by + rw [← circleIntegral.integral_smul] + apply circleIntegral.integral_congr (hr 0).le + intro x _ + dsimp only [b, g] + rw [Fin.prod_univ_succ] + simp only [Fin.cons_zero, Fin.cons_succ, mul_smul] + exact smul_comm _ _ _ + rw [multivariableLaurentCoeff, torusIntegral_succ_inner (torusIntegrable_laurentKernel hr hf m)] + simp only [Pi.zero_apply] + simp_rw [hcircle] + change ((2 * π * I : ℂ) ^ (n + 1))⁻¹ • torusIntegral (fun y => b y • g y) 0 (r ∘ Fin.succ) = _ + have he : (fun y => b y • ((2 * π * I : ℂ)⁻¹ • g y)) = + (fun y => (2 * π * I : ℂ)⁻¹ • (b y • g y)) := by + funext y + exact smul_comm _ _ _ + change _ = ((2 * π * I : ℂ) ^ n)⁻¹ • torusIntegral + (fun y => b y • ((2 * π * I : ℂ)⁻¹ • g y)) 0 (r ∘ Fin.succ) + rw [he, torusIntegral_smul, smul_smul, pow_succ, mul_inv] + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Neighborhoods.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Neighborhoods.lean new file mode 100644 index 0000000000..83dfa80103 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Neighborhoods.lean @@ -0,0 +1,120 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Module.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc + +/-! +# Circular product neighborhoods in Reinhardt sets + +An open Reinhardt set contains a product of connected circular domains around each point, +including points on coordinate hyperplanes. + +## Main results + +`IsReinhardt.exists_circular_product_neighborhood` produces such a product neighborhood of any +point. `isConnected_complex_annulus` and `isConnected_norm_preimage_ball` record connectedness +of the circular factors, including degenerate annuli that meet a coordinate hyperplane. +-/ + +public noncomputable section + +open Complex Set Metric +open scoped Topology + +namespace SeveralComplexVariables + +/-- An open annulus with nonnegative inner radius is connected. -/ +theorem isConnected_complex_annulus {a b : ℝ} (ha : 0 ≤ a) (hab : a < b) : + IsConnected {z : ℂ | a < ‖z‖ ∧ ‖z‖ < b} := by + have hc := (isConnected_Ioo hab).prod (isConnected_univ : IsConnected (univ : Set ℝ)) + have hcont : Continuous (fun p : ℝ × ℝ => (p.1 : ℂ) * exp (p.2 * I)) := by fun_prop + have he : (fun p : ℝ × ℝ => (p.1 : ℂ) * exp (p.2 * I)) '' (Ioo a b ×ˢ univ) = + {z : ℂ | a < ‖z‖ ∧ ‖z‖ < b} := by + ext z + constructor + · rintro ⟨⟨r, θ⟩, ⟨hr, _⟩, rfl⟩ + simpa [abs_of_pos (ha.trans_lt hr.1)] using hr + · intro hz + exact ⟨(‖z‖, z.arg), ⟨hz, mem_univ _⟩, norm_mul_exp_arg_mul_I z⟩ + rw [← he] + exact hc.image _ hcont.continuousOn + +/-- A positive-width neighborhood of a nonnegative radius is a connected circular domain. -/ +theorem isConnected_norm_preimage_ball {a δ : ℝ} (ha : 0 ≤ a) (hδ : 0 < δ) : + IsConnected ((norm : ℂ → ℝ) ⁻¹' ball a δ) := by + by_cases h : a < δ + · have he : (norm : ℂ → ℝ) ⁻¹' ball a δ = ball 0 (a + δ) := by + ext z + simp only [mem_preimage, mem_ball, Real.dist_eq, dist_zero_right, abs_sub_lt_iff] + constructor + · intro hz; linarith + · intro hz; constructor <;> linarith [norm_nonneg z] + rw [he] + exact isConnected_ball (by linarith) + · have he : (norm : ℂ → ℝ) ⁻¹' ball a δ = + {z : ℂ | a - δ < ‖z‖ ∧ ‖z‖ < a + δ} := by + ext z + simp only [mem_preimage, mem_ball, Real.dist_eq, mem_ofPred_eq, abs_sub_lt_iff] + constructor <;> intro hz <;> constructor <;> linarith [hz.1, hz.2] + rw [he] + exact isConnected_complex_annulus (by linarith) (by linarith) + +/-- Every point of an open Reinhardt set has a circular product neighborhood with connected factors. +The factors containing zero are discs. -/ +theorem IsReinhardt.exists_circular_product_neighborhood {n : ℕ} {U : Set (Fin n → ℂ)} + (hR : IsReinhardt U) (ho : IsOpen U) {z : Fin n → ℂ} (hz : z ∈ U) : + ∃ V : Fin n → Set ℂ, + (∀ i, IsOpen (V i)) ∧ (∀ i, IsConnected (V i)) ∧ + (∀ i, ∀ v ∈ V i, ∀ w : ℂ, ‖w‖ = ‖v‖ → w ∈ V i) ∧ + z ∈ Set.pi univ V ∧ Set.pi univ V ⊆ U := by + have hz' : (fun i => (‖z i‖ : ℂ)) ∈ U := hR hz (fun i => by simp) + obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp ho _ hz' + let V : Fin n → Set ℂ := fun i => (norm : ℂ → ℝ) ⁻¹' ball ‖z i‖ δ + refine ⟨V, fun i => isOpen_ball.preimage continuous_norm, + fun i => isConnected_norm_preimage_ball (norm_nonneg _) hδ, ?_, ?_, ?_⟩ + · intro i v hv w hw + change ‖w‖ ∈ ball ‖z i‖ δ + rwa [hw] + · intro i _ + exact mem_ball_self hδ + · intro w hw + apply hR (z := fun i => (‖w i‖ : ℂ)) (hball ?_) (fun i => by simp) + rw [mem_ball, dist_pi_lt_iff hδ] + intro i + rw [dist_eq_norm, ← Complex.ofReal_sub, Complex.norm_real, Real.norm_eq_abs] + simpa only [V, mem_preimage, mem_ball, Real.dist_eq] using hw i (mem_univ _) + +/-- Choose inner and outer coefficient circles and stricter evaluation bounds. At zero only the +upper evaluation bound is required. -/ +theorem exists_circular_radii_bounds {V : Set ℂ} (ho : IsOpen V) + (hrot : ∀ z ∈ V, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V) {z : ℂ} (hz : z ∈ V) : + ∃ a b t T : ℝ, 0 < a ∧ a < t ∧ 0 < T ∧ T < b ∧ + (a : ℂ) ∈ V ∧ (b : ℂ) ∈ V ∧ ‖z‖ < T ∧ (z ≠ 0 → t < ‖z‖) := by + by_cases hz0 : z = 0 + · subst z + obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp ho _ hz + have hb : ((δ / 2 : ℝ) : ℂ) ∈ V := hball (by + simpa [abs_of_pos hδ] using half_lt_self hδ) + refine ⟨δ / 2, δ / 2, δ, δ / 4, by positivity, by linarith, + by positivity, by linarith, hb, hb, ?_, ?_⟩ + · simp only [norm_zero]; positivity + · simp + · have hn : 0 < ‖z‖ := norm_pos_iff.mpr hz0 + have hzV : (‖z‖ : ℂ) ∈ V := hrot z hz _ (by simp) + obtain ⟨l, u, hlu, hsub⟩ := mem_nhds_iff_exists_Ioo_subset.mp + ((ho.preimage continuous_ofReal).mem_nhds hzV) + obtain ⟨a, ha, haz⟩ := exists_between (max_lt hn hlu.1) + obtain ⟨b, hzb, hb⟩ := exists_between hlu.2 + refine ⟨a, b, (a + ‖z‖) / 2, (‖z‖ + b) / 2, + (le_max_left _ _).trans_lt ha, by linarith, by linarith, by linarith, + hsub ⟨(le_max_right _ _).trans_lt ha, haz.trans hlu.2⟩, + hsub ⟨hlu.1.trans hzb, hb⟩, by linarith, fun _ => by linarith⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/OneVariable.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/OneVariable.lean new file mode 100644 index 0000000000..4da9ab2b9b --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/OneVariable.lean @@ -0,0 +1,306 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy + +/-! +# Circle coefficients for analytic Laurent series + +Laurent coefficients on a circle satisfy Cauchy bounds and depend holomorphically on holomorphic +parameters. Cauchy's formula on an annulus proves the Laurent expansion, independence of radius, +and vanishing of negative coefficients on a disc. These results are independent of the +multivariable Laurent expansion. + +## Main results + +`circleLaurentCoeff` is the coefficient of `z ^ k` on the circle of radius `r`. +`circleLaurentCoeff_eq_of_connected` is independence of radius on a connected set of admissible +radii. `circleLaurentCoeff_neg_eq_zero` is vanishing of negative coefficients on a disc. +`circleLaurent_expansion` is the two-sided series on an annulus. +-/ + +public noncomputable section + +open Complex Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The coefficient of exponent `k` obtained by integrating on the circle of radius `r`. -/ +@[expose] def circleLaurentCoeff (f : ℂ → F) (r : ℝ) (k : ℤ) : F := + (2 * Real.pi * I : ℂ)⁻¹ • ∮ w in C(0, r), w ^ (-k - 1) • f w + +omit [CompleteSpace F] in +/-- Cauchy's bound for an arbitrary integer Laurent coefficient. No analyticity assumption is needed +for this integral estimate. -/ +theorem norm_circleLaurentCoeff_le {f : ℂ → F} {r M : ℝ} (hr : 0 < r) + (hM : ∀ w ∈ sphere (0 : ℂ) r, ‖f w‖ ≤ M) (k : ℤ) : + ‖circleLaurentCoeff f r k‖ ≤ M * r ^ (-k) := by + have h := circleIntegral.norm_two_pi_i_inv_smul_integral_le_of_norm_le_const hr.le + (C := r ^ (-k - 1) * M) (f := fun w => w ^ (-k - 1) • f w) (by + intro w hw + have hn : ‖w‖ = r := mem_sphere_zero_iff_norm.mp hw + rw [norm_smul, norm_zpow, hn] + exact mul_le_mul_of_nonneg_left (hM w hw) (zpow_nonneg hr.le _)) + apply h.trans_eq + have he : r * r ^ (-k - 1) = r ^ (-k) := by + calc + r * r ^ (-k - 1) = r ^ (1 : ℤ) * r ^ (-k - 1) := by rw [zpow_one] + _ = r ^ (-k) := by rw [← zpow_add₀ hr.ne']; congr 1; omega + rw [mul_comm (r ^ (-k - 1)) M, ← mul_assoc, mul_comm r M, mul_assoc, + he] + +/-- A fixed-circle Laurent coefficient is analytic in any finite-dimensional complex parameter on +which the integrand depends holomorphically. -/ +theorem analyticOnNhd_circleLaurentCoeff {E : Type*} [NormedAddCommGroup E] + [NormedSpace ℂ E] [FiniteDimensional ℂ E] {V : Set E} (hV : IsOpen V) + {U : Set (E × ℂ)} {f : E × ℂ → F} (hf : AnalyticOnNhd ℂ f U) + {r : ℝ} (hr : 0 < r) (hsub : ∀ z ∈ V, ∀ w ∈ sphere (0 : ℂ) r, (z, w) ∈ U) + (k : ℤ) : AnalyticOnNhd ℂ (fun z => circleLaurentCoeff (fun w => f (z, w)) r k) V := by + let W := U ∩ {p : E × ℂ | p.2 ≠ 0} + have hH : AnalyticOnNhd ℂ (fun p : E × ℂ => p.2 ^ (-k - 1) • f p) W := by + intro p hp + exact (analyticAt_snd.zpow (n := -k - 1) hp.2).smul (hf p hp.1) + apply (analyticOnNhd_circleIntegral_kernel hV hH hr.le ?_).const_smul + intro z hz w hw + refine ⟨hsub z hz w hw, ?_⟩ + exact norm_pos_iff.mp (by rw [mem_sphere_zero_iff_norm.mp hw]; exact hr) + +omit [CompleteSpace F] in +/-- The nonnegative Laurent terms admit a geometric bound inside the coefficient circle. -/ +theorem norm_circleLaurentTerm_nat_le {f : ℂ → F} {R M t : ℝ} (hR : 0 < R) + (hbound : ∀ w ∈ sphere (0 : ℂ) R, ‖f w‖ ≤ M) + {z : ℂ} (hz : ‖z‖ ≤ t) (n : ℕ) : + ‖z ^ (n : ℤ) • circleLaurentCoeff f R n‖ ≤ M * (t / R) ^ n := by + have hc := norm_circleLaurentCoeff_le hR hbound (n : ℤ) + have ht : 0 ≤ t := (norm_nonneg z).trans hz + rw [zpow_neg, zpow_natCast] at hc + rw [norm_smul, norm_zpow, zpow_natCast] + calc + ‖z‖ ^ n * ‖circleLaurentCoeff f R n‖ ≤ t ^ n * (M * (R ^ n)⁻¹) := by + gcongr + _ = M * (t / R) ^ n := by simp only [div_eq_mul_inv]; ring + +omit [CompleteSpace F] in +/-- The negative Laurent terms admit a geometric bound outside the coefficient circle. -/ +theorem norm_circleLaurentTerm_negSucc_le {f : ℂ → F} {r M t : ℝ} (hr : 0 < r) + (ht : 0 < t) (hbound : ∀ w ∈ sphere (0 : ℂ) r, ‖f w‖ ≤ M) + {z : ℂ} (hz : t ≤ ‖z‖) (n : ℕ) : + ‖z ^ (Int.negSucc n) • circleLaurentCoeff f r (Int.negSucc n)‖ ≤ + M * (r / t) ^ (n + 1) := by + have hc := norm_circleLaurentCoeff_le hr hbound (Int.negSucc n) + simp only [Int.neg_negSucc, zpow_natCast] at hc + rw [norm_smul, norm_zpow, zpow_negSucc] + calc + (‖z‖ ^ (n + 1))⁻¹ * ‖circleLaurentCoeff f r (Int.negSucc n)‖ ≤ + (t ^ (n + 1))⁻¹ * (M * r ^ (n + 1)) := by + gcongr + _ = M * (r / t) ^ (n + 1) := by simp only [div_eq_mul_inv]; ring + +/-- A connected rotation-invariant set contains all intermediate radii. -/ +private theorem mem_of_norm_between {V : Set ℂ} (hc : IsConnected V) + (hrot : ∀ z ∈ V, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V) + {a b w : ℂ} (ha : a ∈ V) (hb : b ∈ V) + (haw : ‖a‖ ≤ ‖w‖) (hwb : ‖w‖ ≤ ‖b‖) : w ∈ V := by + obtain ⟨v, hv, he⟩ := (hc.isPreconnected.image norm continuous_norm.continuousOn).Icc_subset + (mem_image_of_mem _ ha) (mem_image_of_mem _ hb) ⟨haw, hwb⟩ + exact hrot v hv w he.symm + +omit [CompleteSpace F] in +/-- Laurent coefficients are unchanged between two circles in an analytic annulus. -/ +theorem circleLaurentCoeff_eq_of_analyticOnNhd_annulus {f : ℂ → F} {r R : ℝ} + (hr : 0 < r) (hrR : r ≤ R) + (hf : AnalyticOnNhd ℂ f (closedBall 0 R \ ball 0 r)) : + circleLaurentCoeff f R = circleLaurentCoeff f r := by + funext k + have ha : AnalyticOnNhd ℂ (fun w => w ^ (-k - 1) • f w) + (closedBall 0 R \ ball 0 r) := by + intro w hw + have hw0 : w ≠ 0 := by + intro he + subst w + exact hw.2 (mem_ball_self hr) + exact (analyticAt_id.zpow hw0).smul (hf w hw) + unfold circleLaurentCoeff + congr 1 + exact circleIntegral_eq_of_differentiable_on_annulus_off_countable hr hrR countable_empty + ha.continuousOn (fun w hw => (ha w ⟨ball_subset_closedBall hw.1.1, + fun hb => hw.1.2 (ball_subset_closedBall hb)⟩).differentiableAt) + +omit [CompleteSpace F] in +/-- On a connected rotation-invariant set, the Laurent coefficients do not depend on radius. -/ +theorem circleLaurentCoeff_eq_of_connected {V : Set ℂ} (hc : IsConnected V) + (hrot : ∀ z ∈ V, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V) + {f : ℂ → F} (hf : AnalyticOnNhd ℂ f V) {r s : ℝ} + (hr : 0 < r) (hs : 0 < s) (hrV : (r : ℂ) ∈ V) (hsV : (s : ℂ) ∈ V) : + circleLaurentCoeff f s = circleLaurentCoeff f r := by + have hordered {a b : ℝ} (ha : 0 < a) (hab : a ≤ b) + (haV : (a : ℂ) ∈ V) (hbV : (b : ℂ) ∈ V) : + circleLaurentCoeff f b = circleLaurentCoeff f a := by + apply circleLaurentCoeff_eq_of_analyticOnNhd_annulus ha hab (hf.mono ?_) + intro w hw + apply mem_of_norm_between hc hrot haV hbV + · simpa [abs_of_pos ha] using (not_lt.mp (mem_ball_zero_iff.not.mp hw.2)) + · simpa [abs_of_pos (ha.trans_le hab)] using mem_closedBall_zero_iff.mp hw.1 + rcases le_total r s with h | h + · exact hordered hr h hrV hsV + · exact (hordered hs h hsV hrV).symm + +omit [CompleteSpace F] in +/-- Negative Laurent coefficients vanish if the coefficient circle bounds an analytic disc. -/ +theorem circleLaurentCoeff_neg_eq_zero {f : ℂ → F} {r : ℝ} (hr : 0 ≤ r) + (hf : AnalyticOnNhd ℂ f (closedBall 0 r)) {k : ℤ} (hk : k < 0) : + circleLaurentCoeff f r k = 0 := by + have he : -k - 1 = ((-k - 1).toNat : ℤ) := (Int.toNat_of_nonneg (by omega)).symm + have ha : AnalyticOnNhd ℂ (fun w => w ^ (-k - 1) • f w) (closedBall 0 r) := by + have ha' : AnalyticOnNhd ℂ (fun w => w ^ (-k - 1).toNat • f w) (closedBall 0 r) := + fun w hw => (analyticAt_id.pow _).smul (hf w hw) + convert ha' using 1 + funext w + rw [he, zpow_natCast, Int.toNat_natCast] + rw [circleLaurentCoeff, + (ha.differentiableOn.mono closure_ball_subset_closedBall).diffContOnCl.circleIntegral_eq_zero + hr, + smul_zero] + +omit [CompleteSpace F] in +/-- The nonnegative Laurent terms sum to the outer Cauchy integral. -/ +theorem hasSum_circleLaurentCoeff_nat {f : ℂ → F} {R : ℝ} + (hf : CircleIntegrable f 0 R) {z : ℂ} (hz : ‖z‖ < R) : + HasSum (fun n : ℕ => z ^ (n : ℤ) • circleLaurentCoeff f R n) + ((2 * Real.pi * I : ℂ)⁻¹ • ∮ w in C(0, R), (w - z)⁻¹ • f w) := by + have hR : 0 < R := (norm_nonneg z).trans_lt hz + have hs := (hasSum_two_pi_I_cauchyPowerSeries_integral hf hz).const_smul + (2 * Real.pi * I : ℂ)⁻¹ + simp only [zero_add, sub_zero] at hs + apply hs.congr_fun + intro n + rw [circleLaurentCoeff, smul_comm (z ^ (n : ℤ)), ← circleIntegral.integral_smul] + congr 1 + apply circleIntegral.integral_congr hR.le + intro w _ + dsimp only + rw [show -(n : ℤ) - 1 = -((n + 1 : ℕ) : ℤ) by omega, zpow_neg, + zpow_natCast, zpow_natCast, smul_smul, smul_smul] + congr 1 + simp [div_eq_mul_inv, mul_pow, pow_succ, mul_left_comm, mul_comm] + +omit [CompleteSpace F] in +/-- The negative Laurent terms sum to the inner Cauchy integral with reversed kernel. -/ +theorem hasSum_circleLaurentCoeff_negSucc {f : ℂ → F} {r : ℝ} (hr : 0 ≤ r) + (hf : ContinuousOn f (sphere (0 : ℂ) r)) {z : ℂ} (hz : r < ‖z‖) : + HasSum (fun n : ℕ => z ^ (Int.negSucc n) • circleLaurentCoeff f r (Int.negSucc n)) + ((2 * Real.pi * I : ℂ)⁻¹ • ∮ w in C(0, r), (z - w)⁻¹ • f w) := by + have hz0 : z ≠ 0 := norm_pos_iff.mp (hr.trans_lt hz) + have hs := (hasSum_circleIntegral_geometric hr (hf.const_smul z⁻¹) + (g := fun w => w / z) (continuousOn_id.div_const z) + (div_nonneg hr (norm_nonneg z)) ((div_lt_one (hr.trans_lt hz)).mpr hz) (by + intro w hw + simp [mem_sphere_zero_iff_norm.mp hw])).const_smul (2 * Real.pi * I : ℂ)⁻¹ + have he : (∮ w in C(0, r), (1 - w / z)⁻¹ • z⁻¹ • f w) = + ∮ w in C(0, r), (z - w)⁻¹ • f w := by + apply circleIntegral.integral_congr hr + intro w _ + dsimp only + rw [smul_smul] + congr 1 + rw [← mul_inv, sub_mul, one_mul, div_mul_cancel₀ _ hz0] + simp only [Pi.smul_apply] at hs + rw [he] at hs + apply hs.congr_fun + intro n + rw [circleLaurentCoeff, smul_comm (z ^ (Int.negSucc n)), + ← circleIntegral.integral_smul] + congr 1 + apply circleIntegral.integral_congr hr + intro w _ + dsimp only + rw [show -(Int.negSucc n) - 1 = (n : ℤ) by omega, zpow_natCast, + zpow_negSucc, smul_smul, smul_smul] + congr 1 + simp [div_eq_mul_inv, mul_pow, pow_succ, mul_left_comm, mul_comm] + +/-- Laurent expansion at a point strictly between two analytic coefficient circles. -/ +theorem hasSum_circleLaurentCoeff_annulus {f : ℂ → F} {r R : ℝ} + (hr : 0 < r) {z : ℂ} (hzr : r < ‖z‖) (hzR : ‖z‖ < R) + (hf : AnalyticOnNhd ℂ f (closedBall 0 R \ ball 0 r)) : + HasSum (fun k : ℤ => z ^ k • circleLaurentCoeff f r k) (f z) := by + have hs (t : ℝ) (ht : t = r ∨ t = R) : sphere (0 : ℂ) t ⊆ closedBall 0 R \ ball 0 r := by + intro w hw + have hw' := mem_sphere_zero_iff_norm.mp hw + simp only [Set.mem_sdiff, mem_closedBall_zero_iff, mem_ball_zero_iff, not_lt, hw'] + rcases ht with rfl | rfl <;> constructor <;> linarith + have hp := hasSum_circleLaurentCoeff_nat + ((hf.continuousOn.mono (hs R (Or.inr rfl))).circleIntegrable (hr.trans (hzr.trans hzR)).le) hzR + rw [circleLaurentCoeff_eq_of_analyticOnNhd_annulus hr (hzr.trans hzR).le hf] at hp + have hn := hasSum_circleLaurentCoeff_negSucc hr.le (hf.continuousOn.mono (hs r (Or.inl rfl))) hzr + have hi : (∮ w in C(0, r), (z - w)⁻¹ • f w) = + -(∮ w in C(0, r), (w - z)⁻¹ • f w) := by + calc + _ = ∮ w in C(0, r), -((w - z)⁻¹ • f w) := by + congr 1 + funext w + rw [← neg_sub w z, inv_neg, neg_smul] + _ = _ := by simp only [circleIntegral, smul_neg, intervalIntegral.integral_neg] + have hsum := hp.int_rec hn + rw [hi, ← smul_add, ← sub_eq_add_neg, + circleIntegral_sub_inv_smul_sub_of_analyticOnNhd_annulus hr hzr hzR hf, + inv_smul_smul₀ two_pi_I_ne_zero] at hsum + exact hsum.congr_fun fun k => by cases k <;> rfl + +/-- One-variable Laurent expansion on a connected rotation-invariant open set, including +independence of radius and vanishing of negative coefficients at zero. -/ +theorem circleLaurent_expansion {V : Set ℂ} (hV : IsOpen V) (hc : IsConnected V) + (hrot : ∀ z ∈ V, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V) + {f : ℂ → F} (hf : AnalyticOnNhd ℂ f V) {r : ℝ} (hr : 0 < r) (hrV : (r : ℂ) ∈ V) : + (∀ z ∈ V, HasSum (fun k : ℤ => z ^ k • circleLaurentCoeff f r k) (f z)) ∧ + (∀ s : ℝ, 0 < s → (s : ℂ) ∈ V → circleLaurentCoeff f s = circleLaurentCoeff f r) ∧ + (0 ∈ V → ∀ k : ℤ, k < 0 → circleLaurentCoeff f r k = 0) := by + have hind (s : ℝ) (hs : 0 < s) (hsV : (s : ℂ) ∈ V) : + circleLaurentCoeff f s = circleLaurentCoeff f r := + circleLaurentCoeff_eq_of_connected hc hrot hf hr hs hrV hsV + have hdisc (h0 : 0 ∈ V) : AnalyticOnNhd ℂ f (closedBall 0 r) := by + apply hf.mono + intro w hw + apply mem_of_norm_between hc hrot h0 hrV + · simp + · simpa [abs_of_pos hr] using mem_closedBall_zero_iff.mp hw + refine ⟨?_, hind, fun h0 k hk => circleLaurentCoeff_neg_eq_zero hr.le (hdisc h0) hk⟩ + intro z hz + by_cases hz0 : z = 0 + · subst z + have he : circleLaurentCoeff f r 0 = f 0 := by + have hdc := ((hdisc hz).differentiableOn.mono closure_ball_subset_closedBall).diffContOnCl + simpa [circleLaurentCoeff] using + hdc.two_pi_i_inv_smul_circleIntegral_sub_inv_smul (mem_ball_self hr) + simpa [he] using (hasSum_single (0 : ℤ) + (f := fun k : ℤ => (0 : ℂ) ^ k • circleLaurentCoeff f r k) (by + intro k hk + simp [zero_zpow k hk])) + · have hn : 0 < ‖z‖ := norm_pos_iff.mpr hz0 + have hzV : (‖z‖ : ℂ) ∈ V := hrot z hz _ (by simp) + obtain ⟨a, b, hab, hsub⟩ := mem_nhds_iff_exists_Ioo_subset.mp + ((hV.preimage continuous_ofReal).mem_nhds hzV) + obtain ⟨s, hs₁, hs₂⟩ := exists_between (max_lt hn hab.1) + obtain ⟨R, hR₁, hR₂⟩ := exists_between hab.2 + have hs : 0 < s := (le_max_left _ _).trans_lt hs₁ + have hsV : (s : ℂ) ∈ V := hsub ⟨(le_max_right _ _).trans_lt hs₁, hs₂.trans hab.2⟩ + have hRV : (R : ℂ) ∈ V := hsub ⟨hab.1.trans hR₁, hR₂⟩ + have ha : AnalyticOnNhd ℂ f (closedBall 0 R \ ball 0 s) := by + apply hf.mono + intro w hw + apply mem_of_norm_between hc hrot hsV hRV + · simpa [abs_of_pos hs] using (not_lt.mp (mem_ball_zero_iff.not.mp hw.2)) + · simpa [abs_of_pos (hn.trans hR₁)] using mem_closedBall_zero_iff.mp hw.1 + simpa only [hind s hs hsV] using hasSum_circleLaurentCoeff_annulus hs hs₂ hR₁ ha + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductCoefficients.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductCoefficients.lean new file mode 100644 index 0000000000..9fc9c651b0 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductCoefficients.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated + +/-! +# Laurent coefficients on products of circular domains + +Circle coefficients are analytic in the remaining coordinates. Iteration therefore proves +independence of the coordinate radii on products of connected circular domains. + +## Main results + +`analyticOnNhd_circleLaurentCoeff_cons` is holomorphy of a circle coefficient in the remaining +coordinates. `multivariableLaurentCoeff_eq_on_product` is independence of radii on a product of +connected circular domains. `multivariableLaurentCoeff_neg_on_product` vanishes negative +exponents in a factor that is a disc. +-/ + +public noncomputable section + +open Complex Set Metric Function +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Combining an analytic first coordinate and analytic remaining coordinates is analytic. -/ +private theorem analyticAt_fin_cons {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {a : E} {f : E → ℂ} {g : E → (Fin n → ℂ)} + (hf : AnalyticAt ℂ f a) (hg : AnalyticAt ℂ g a) : + AnalyticAt ℂ (fun x => (Fin.cons (f x) (g x) : Fin (n + 1) → ℂ)) a := by + apply AnalyticAt.pi + intro i + refine Fin.cases ?_ (fun j => ?_) i + · exact hf + · exact ((ContinuousLinearMap.proj (R := ℂ) j).analyticAt (g a)).comp hg + +/-- Rotation invariance of each factor puts the entire coefficient torus in the product. -/ +theorem torusMap_mem_product {V : Fin n → Set ℂ} + (hrot : ∀ i, ∀ z ∈ V i, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V i) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrV : ∀ i, (r i : ℂ) ∈ V i) + (θ : Fin n → ℝ) : torusMap 0 r θ ∈ Set.pi univ V := by + intro i _ + apply hrot i _ (hrV i) + simp [torusMap, abs_of_pos (hr i)] + +/-- Taking the first circle coefficient preserves analyticity in the remaining coordinates. -/ +theorem analyticOnNhd_circleLaurentCoeff_cons {V : Fin (n + 1) → Set ℂ} + (ho : ∀ i, IsOpen (V i)) + (hrot : ∀ i, ∀ z ∈ V i, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V i) + {f : (Fin (n + 1) → ℂ) → F} (hf : AnalyticOnNhd ℂ f (Set.pi univ V)) + {r : ℝ} (hr : 0 < r) (hrV : (r : ℂ) ∈ V 0) (k : ℤ) : + AnalyticOnNhd ℂ (fun y => circleLaurentCoeff (fun x => f (Fin.cons x y)) r k) + (Set.pi univ (V ∘ Fin.succ)) := by + let W := {p : (Fin n → ℂ) × ℂ | Fin.cons p.2 p.1 ∈ Set.pi univ V} + have hH : AnalyticOnNhd ℂ (fun p : (Fin n → ℂ) × ℂ => f (Fin.cons p.2 p.1)) W := + fun p hp => (hf _ hp).comp_of_eq (analyticAt_fin_cons (f := Prod.snd) (g := Prod.fst) (a := p) + analyticAt_snd analyticAt_fst) rfl + apply analyticOnNhd_circleLaurentCoeff + (isOpen_set_pi finite_univ (fun i _ => ho i.succ)) hH hr + intro y hy w hw + change Fin.cons w y ∈ Set.pi univ V + intro i _ + refine Fin.cases ?_ (fun j => ?_) i + · exact hrot 0 _ hrV w (by simpa [abs_of_pos hr] using mem_sphere_zero_iff_norm.mp hw) + · exact hy j (mem_univ _) + +/-- In a product of connected circular domains, Laurent coefficients are independent of radii. -/ +theorem multivariableLaurentCoeff_eq_on_product {V : Fin n → Set ℂ} + (ho : ∀ i, IsOpen (V i)) (hc : ∀ i, IsConnected (V i)) + (hrot : ∀ i, ∀ z ∈ V i, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V i) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f (Set.pi univ V)) + {r s : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hs : ∀ i, 0 < s i) + (hrV : ∀ i, (r i : ℂ) ∈ V i) (hsV : ∀ i, (s i : ℂ) ∈ V i) : + multivariableLaurentCoeff f s = multivariableLaurentCoeff f r := by + induction n with + | zero => rw [Subsingleton.elim s r] + | succ n ih => + have hcont (t : Fin (n + 1) → ℝ) (ht : ∀ i, 0 < t i) (htV : ∀ i, (t i : ℂ) ∈ V i) : + Continuous (fun θ => f (torusMap 0 t θ)) := + hf.continuousOn.comp_continuous (continuous_torusMap 0 t) + (torusMap_mem_product hrot ht htV) + funext m + rw [multivariableLaurentCoeff_succ hs (hcont s hs hsV), + multivariableLaurentCoeff_succ hr (hcont r hr hrV)] + let a (t : ℝ) (y : Fin n → ℂ) := circleLaurentCoeff (fun x => f (Fin.cons x y)) t (m 0) + have ha : AnalyticOnNhd ℂ (a (r 0)) (Set.pi univ (V ∘ Fin.succ)) := + analyticOnNhd_circleLaurentCoeff_cons ho hrot hf (hr 0) (hrV 0) (m 0) + have heq : EqOn (a (s 0)) (a (r 0)) (Set.pi univ (V ∘ Fin.succ)) := by + intro y hy + have hfy : AnalyticOnNhd ℂ (fun x => f (Fin.cons x y)) (V 0) := by + intro x hx + apply (hf _ ?_).comp_of_eq + (analyticAt_fin_cons (f := id) (g := fun _ : ℂ => y) analyticAt_id analyticAt_const) rfl + intro i _ + exact Fin.cases hx (fun j => hy j (mem_univ _)) i + exact congrFun (circleLaurentCoeff_eq_of_connected (hc 0) (hrot 0) hfy + (hr 0) (hs 0) (hrV 0) (hsV 0)) (m 0) + have he := multivariableLaurentCoeff_congr (r := s ∘ Fin.succ) (fun θ => + heq (torusMap_mem_product (fun i => hrot i.succ) (fun i => hs i.succ) + (fun i => hsV i.succ) θ)) + change multivariableLaurentCoeff (a (s 0)) (s ∘ Fin.succ) (m ∘ Fin.succ) = _ + rw [he] + exact congrFun (ih (fun i => ho i.succ) (fun i => hc i.succ) (fun i => hrot i.succ) ha + (r := r ∘ Fin.succ) (s := s ∘ Fin.succ) + (fun i => hr i.succ) (fun i => hs i.succ) (fun i => hrV i.succ) (fun i => hsV i.succ)) + (m ∘ Fin.succ) + +/-- Negative coefficients vanish in a product when the corresponding factor contains zero. -/ +theorem multivariableLaurentCoeff_neg_on_product {V : Fin n → Set ℂ} + (ho : ∀ i, IsOpen (V i)) (hc : ∀ i, IsConnected (V i)) + (hrot : ∀ i, ∀ z ∈ V i, ∀ w : ℂ, ‖w‖ = ‖z‖ → w ∈ V i) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f (Set.pi univ V)) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrV : ∀ i, (r i : ℂ) ∈ V i) + (m : Fin n → ℤ) (i : Fin n) (hi : 0 ∈ V i) (hm : m i < 0) : + multivariableLaurentCoeff f r m = 0 := by + induction n with + | zero => exact Fin.elim0 i + | succ n ih => + have hcont : Continuous (fun θ => f (torusMap 0 r θ)) := + hf.continuousOn.comp_continuous (continuous_torusMap 0 r) + (torusMap_mem_product hrot hr hrV) + rw [multivariableLaurentCoeff_succ hr hcont] + cases i using Fin.cases with + | zero => + have he : multivariableLaurentCoeff + (fun y => circleLaurentCoeff (fun x => f (Fin.cons x y)) (r 0) (m 0)) + (r ∘ Fin.succ) = multivariableLaurentCoeff (fun _ => (0 : F)) (r ∘ Fin.succ) := by + apply multivariableLaurentCoeff_congr + intro θ + let y := torusMap 0 (r ∘ Fin.succ) θ + have hy := torusMap_mem_product (fun i => hrot i.succ) (fun i => hr i.succ) + (fun i => hrV i.succ) θ + have hfy : AnalyticOnNhd ℂ (fun x => f (Fin.cons x y)) (V 0) := by + intro x hx + apply (hf _ ?_).comp_of_eq + (analyticAt_fin_cons (f := id) (g := fun _ : ℂ => y) analyticAt_id analyticAt_const) rfl + intro i _ + exact Fin.cases hx (fun j => hy j (mem_univ _)) i + exact (circleLaurent_expansion (ho 0) (hc 0) (hrot 0) hfy (hr 0) (hrV 0)).2.2 hi (m 0) hm + rw [he] + simp [multivariableLaurentCoeff, torusIntegral] + | succ j => + exact ih (fun i => ho i.succ) (fun i => hc i.succ) (fun i => hrot i.succ) + (analyticOnNhd_circleLaurentCoeff_cons ho hrot hf (hr 0) (hrV 0) (m 0)) + (r := r ∘ Fin.succ) (fun i => hr i.succ) (fun i => hrV i.succ) + (m ∘ Fin.succ) j hi hm + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductExpansion.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductExpansion.lean new file mode 100644 index 0000000000..2725139486 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/ProductExpansion.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence + +/-! +# Laurent expansion by successive circle expansions + +On circular products, induction on the number of coordinates combines the circle Laurent theorem +with Fubini for absolutely summable families. Circular product neighborhoods then give pointwise +expansion on every Reinhardt domain. + +## Main results + +`hasSum_multivariableLaurent_on_product` is the expansion on a finite product of circular +domains. `hasSum_multivariableLaurent` is the pointwise expansion at an arbitrary point of an +open Reinhardt domain. +-/ + +public noncomputable section + +open Complex Set Filter +open scoped Topology NNReal + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +omit [CompleteSpace F] in +/-- Fixing all but the first coordinate preserves analyticity on a product. -/ +private theorem analyticOnNhd_first_slice {V : Fin (n + 1) → Set ℂ} + {f : (Fin (n + 1) → ℂ) → F} (hf : AnalyticOnNhd ℂ f (Set.pi univ V)) + {y : Fin n → ℂ} (hy : y ∈ Set.pi univ (V ∘ Fin.succ)) : + AnalyticOnNhd ℂ (fun x => f (Fin.cons x y)) (V 0) := by + intro x hx + have hg : AnalyticAt ℂ (fun x : ℂ => (Fin.cons x y : Fin (n + 1) → ℂ)) x := by + apply AnalyticAt.pi + intro i + exact Fin.cases analyticAt_id (fun _ => analyticAt_const) i + apply (hf _ ?_).comp_of_eq hg rfl + intro i _ + exact Fin.cases hx (fun j => hy j (mem_univ _)) i + +/-- Successive one-variable Laurent expansions give the expansion on a circular product. -/ +theorem hasSum_multivariableLaurent_on_product {V : Fin n → Set ℂ} + (ho : ∀ i, IsOpen (V i)) (hc : ∀ i, IsConnected (V i)) + (hrot : ∀ i, ∀ x ∈ V i, ∀ w : ℂ, ‖w‖ = ‖x‖ → w ∈ V i) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f (Set.pi univ V)) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrV : ∀ i, (r i : ℂ) ∈ V i) + {z : Fin n → ℂ} (hz : z ∈ Set.pi univ V) : + HasSum (fun m => multivariableLaurentTerm (multivariableLaurentCoeff f r) m z) (f z) := by + induction n with + | zero => + convert hasSum_fintype (fun m => multivariableLaurentTerm (multivariableLaurentCoeff f r) m z) + using 1 + simp only [multivariableLaurentTerm, multivariableLaurentCoeff, torusIntegral_dim0, + Fin.prod_univ_zero, pow_zero, inv_one, one_smul, Finset.sum_const, Finset.card_univ, + Fintype.card_unique] + congr 1 + exact Subsingleton.elim _ _ + | succ n ih => + let a (k : ℤ) (y : Fin n → ℂ) := circleLaurentCoeff (fun x => f (Fin.cons x y)) (r 0) k + have ha (k : ℤ) : AnalyticOnNhd ℂ (a k) (Set.pi univ (V ∘ Fin.succ)) := + analyticOnNhd_circleLaurentCoeff_cons ho hrot hf (hr 0) (hrV 0) k + have hz' : z ∘ Fin.succ ∈ Set.pi univ (V ∘ Fin.succ) := fun i _ => hz i.succ (mem_univ _) + have hinner (k : ℤ) : HasSum + (fun m => z 0 ^ k • multivariableLaurentTerm + (multivariableLaurentCoeff (a k) (r ∘ Fin.succ)) m (z ∘ Fin.succ)) + (z 0 ^ k • a k (z ∘ Fin.succ)) := by + apply HasSum.const_smul + exact ih (V := V ∘ Fin.succ) (f := a k) (z := z ∘ Fin.succ) + (fun i => ho i.succ) (fun i => hc i.succ) (fun i => hrot i.succ) (ha k) + (r := r ∘ Fin.succ) (fun i => hr i.succ) (fun i => hrV i.succ) hz' + have houter := (circleLaurent_expansion (ho 0) (hc 0) (hrot 0) + (analyticOnNhd_first_slice hf hz') (hr 0) (hrV 0)).1 (z 0) (hz 0 (mem_univ _)) + have hR : IsReinhardt (Set.pi univ V) := by + intro x hx w hw i _ + exact hrot i _ (hx i (mem_univ _)) _ (hw i) + have habs := summable_norm_multivariableLaurent + (isOpen_set_pi finite_univ (fun i _ => ho i)) + (isPreconnected_univ_pi (fun i => (hc i).isPreconnected)) hR hf hr + (fun i _ => hrV i) hz + let e := Fin.consEquiv (fun _ : Fin (n + 1) => ℤ) + have hp := e.summable_iff.mpr habs.of_norm + have hcont : Continuous (fun θ => f (torusMap 0 r θ)) := + hf.continuousOn.comp_continuous (continuous_torusMap 0 r) + (torusMap_mem_product hrot hr hrV) + have hterm (k : ℤ) (m : Fin n → ℤ) : + multivariableLaurentTerm (multivariableLaurentCoeff f r) (e (k, m)) z = + z 0 ^ k • multivariableLaurentTerm (multivariableLaurentCoeff (a k) (r ∘ Fin.succ)) m + (z ∘ Fin.succ) := by + rw [multivariableLaurentTerm, multivariableLaurentCoeff_succ hr hcont] + simp [multivariableLaurentTerm, e, Fin.consEquiv, Fin.prod_univ_succ, a, + Function.comp_def, smul_smul] + have hsum := hp.hasSum.prod_fiberwise (fun k => + (hinner k).congr_fun (fun m => hterm k m)) + have heq := hsum.unique houter + apply e.hasSum_iff.mp + convert hp.hasSum using 1 + have hzcons : Fin.cons (z 0) (z ∘ Fin.succ) = z := Fin.cons_self_tail z + simpa only [hzcons] using heq.symm + +/-- Every analytic function on an open connected Reinhardt set equals its Laurent series. -/ +theorem hasSum_multivariableLaurent {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsPreconnected U) (hR : IsReinhardt U) + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hrU : (fun i => (r i : ℂ)) ∈ U) + {z : Fin n → ℂ} (hz : z ∈ U) : + HasSum (fun m => multivariableLaurentTerm (multivariableLaurentCoeff f r) m z) (f z) := by + obtain ⟨V, hVo, hVc, hVr, hzV, hVU⟩ := hR.exists_circular_product_neighborhood ho hz + have hprod : IsReinhardt (Set.pi univ V) := by + intro x hx y hy j _ + exact hVr j _ (hx j (mem_univ _)) _ (hy j) + obtain ⟨s, hsV, hs⟩ := hprod.exists_strict_modulus_majorant + (isOpen_set_pi finite_univ (fun i _ => hVo i)) hzV + have hspos (j : Fin n) : 0 < (s j : ℝ) := by + exact_mod_cast (show (0 : ℝ≥0) ≤ ‖z j‖₊ from zero_le).trans_lt (hs j) + rw [← multivariableLaurentCoeff_eq_of_radii ho hc hR hf hr hspos hrU (hVU hsV)] + exact hasSum_multivariableLaurent_on_product hVo hVc hVr (hf.mono hVU) hspos + (fun i => hsV i (mem_univ _)) hzV + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Uniqueness.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Uniqueness.lean new file mode 100644 index 0000000000..246b74a9e9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LaurentSeries/Uniqueness.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Uniqueness of analytic Laurent expansions + +Uniform convergence on one positive coordinate torus permits coefficient extraction. The +coefficients of a locally uniformly convergent Laurent series are therefore unique, +independently of the existence theorem and without a connectedness hypothesis. + +## Main results + +`tendsto_multivariableLaurentCoeff` extracts coefficients from uniform convergence on a torus. +`eq_multivariableLaurentCoeff_of_hasSumLocallyUniformlyOn` is uniqueness of the coefficient +family of a locally uniformly convergent expansion. +-/ + +public noncomputable section + +open Complex Set MeasureTheory Metric Filter +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +omit [CompleteSpace F] in +/-- Uniform convergence on a torus implies convergence of each Laurent coefficient. -/ +theorem tendsto_multivariableLaurentCoeff {α : Type*} {l : Filter α} + {f : α → (Fin n → ℂ) → F} {g : (Fin n → ℂ) → F} {K : Set (Fin n → ℂ)} + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (hK : ∀ θ, torusMap 0 r θ ∈ K) + (hf : ∀ᶠ a in l, Continuous (fun θ => f a (torusMap 0 r θ))) + (hg : Continuous (fun θ => g (torusMap 0 r θ))) + (hu : TendstoUniformlyOn f g l K) (m : Fin n → ℤ) : + Tendsto (fun a => multivariableLaurentCoeff (f a) r m) l + (𝓝 (multivariableLaurentCoeff g r m)) := by + let C := ∏ i, r i ^ (-m i) + have hC : 0 ≤ C := Finset.prod_nonneg fun i _ => zpow_nonneg (hr i).le _ + rw [Metric.tendsto_nhds] + intro ε hε + have hδ : 0 < ε / (C + 1) := div_pos hε (by positivity) + filter_upwards [Metric.tendstoUniformlyOn_iff.mp hu _ hδ, hf] with a ha hfa + rw [dist_eq_norm, ← multivariableLaurentCoeff_sub hr hfa hg] + calc + ‖multivariableLaurentCoeff (fun z => f a z - g z) r m‖ ≤ ε / (C + 1) * C := + norm_multivariableLaurentCoeff_le hr (fun θ => by + rw [norm_sub_rev] + simpa only [dist_eq_norm] using (ha _ (hK θ)).le) m + _ < ε := by + have he := div_mul_cancel₀ ε (show C + 1 ≠ 0 by positivity) + nlinarith + +/-- The coefficient of a finite Laurent sum is its corresponding summand coefficient. -/ +theorem multivariableLaurentCoeff_sum_terms (c : (Fin n → ℤ) → F) + (s : Finset (Fin n → ℤ)) {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) (m : Fin n → ℤ) : + multivariableLaurentCoeff (fun z => ∑ k ∈ s, multivariableLaurentTerm c k z) r m = + if m ∈ s then c m else 0 := by + classical + rw [multivariableLaurentCoeff_sum s hr (fun k _ => + show Continuous (fun θ => multivariableLaurentTerm c k (torusMap 0 r θ)) from + continuous_laurentMonomial_smul_torus (f := fun _ => c k) hr continuous_const k)] + change (∑ k ∈ s, multivariableLaurentCoeff (fun z => (∏ i, z i ^ k i) • c k) r m) = _ + simp [multivariableLaurentCoeff_monomial r hr] + +/-- A locally uniformly convergent Laurent expansion has the torus integral coefficients. Only +continuity of the limit and containment of a positive torus are needed. -/ +theorem eq_multivariableLaurentCoeff_of_hasSumLocallyUniformlyOn + {U : Set (Fin n → ℂ)} {f : (Fin n → ℂ) → F} (hf : ContinuousOn f U) + {r : Fin n → ℝ} (hr : ∀ i, 0 < r i) + (hTU : ∀ z, (∀ i, ‖z i‖ = r i) → z ∈ U) + {c : (Fin n → ℤ) → F} + (hs : HasSumLocallyUniformlyOn (multivariableLaurentTerm c) f U) : + c = multivariableLaurentCoeff f r := by + classical + let T : Set (Fin n → ℂ) := {z | ∀ i, z i ∈ sphere 0 (r i)} + have hT : IsCompact T := isCompact_pi_infinite (fun i => isCompact_sphere 0 (r i)) + have hTU' : T ⊆ U := fun z hz => hTU z (fun i => mem_sphere_zero_iff_norm.mp (hz i)) + have htor (θ : Fin n → ℝ) : torusMap 0 r θ ∈ T := by + intro i + simp [torusMap, abs_of_pos (hr i)] + have hfc : Continuous (fun θ => f (torusMap 0 r θ)) := + hf.comp_continuous (continuous_torusMap 0 r) (fun θ => hTU' (htor θ)) + have hcont (s : Finset (Fin n → ℤ)) : + Continuous (fun θ => ∑ k ∈ s, multivariableLaurentTerm c k (torusMap 0 r θ)) := + continuous_finsetSum s (fun k _ => + continuous_laurentMonomial_smul_torus (f := fun _ => c k) hr continuous_const k) + have hu := (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hT).mp (hs.mono hTU') + funext m + have hlim := tendsto_multivariableLaurentCoeff hr htor (.of_forall hcont) hfc hu m + have hvalue : Tendsto + (fun s : Finset (Fin n → ℤ) => + multivariableLaurentCoeff (fun z => ∑ k ∈ s, multivariableLaurentTerm c k z) r m) + atTop (𝓝 (c m)) := by + apply tendsto_const_nhds.congr' + filter_upwards [eventually_finset_mem_atTop m] with s hsm + rw [multivariableLaurentCoeff_sum_terms c s hr m, ite_eq_left hsm] + exact tendsto_nhds_unique hvalue hlim + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean new file mode 100644 index 0000000000..76b81c9ab6 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean @@ -0,0 +1,274 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.RCLike.Extend +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier + +/-! +# Levi convex boundaries + +A local `C²` defining function for an open set `U` at a boundary point `p` is a `C²` function +`ρ` on an open neighborhood `V` of `p`, vanishing at `p`, with nonzero derivative at `p`, such +that `U ∩ V` is the set where `ρ` is negative. The complex tangent space at `p` is the kernel of +the complex-linear part of the derivative of `ρ`. The set `U` satisfies the Levi condition at +`p` if the Levi form of every local defining function is positive semidefinite on the complex +tangent space; it is Levi pseudoconvex if this holds at every boundary point. Quantifying over +all defining functions avoids the lemma that two defining functions differ by a positive factor. + +This file proves that convex open sets are Levi pseudoconvex: along a real tangent line the +defining function vanishes to first order at `p`, so a negative second derivative would put two +symmetric points of the line into `U` and, by convexity, the boundary point itself. + +It also provides the complex-linear part `complexPart ℓ` of a real functional `ℓ`, with `ℓ (ζ • +c) = Re (ζ * complexPart ℓ c)`, and the decomposition of a symmetric real bilinear form along a +complex line into a Hermitian part, the Levi form, and the real part of a complex quadratic +term. Both are used for the Levi polynomial in `LeviConvexity.Necessity`. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 4; +[Range][Range1986] (1986), Chapter II, Sections 2.4–2.6. + +## Main definitions + +* `complexPart`: The complex-linear part of a real functional: `ℓ c - I * ℓ (I • c)`. +* `IsLocalDefiningFunction`: A local `C²` defining function for `U` at `p` on the open neighborhood + `V`: `ρ p = 0`, the real derivative of `ρ` at `p` is nonzero, and `U ∩ V` is the negative sublevel + set of `ρ` in `V`. +* `HasC2Boundary`: A set has `C²` boundary if every boundary point has a local defining function. +* `IsComplexTangent`: The complex tangent space of the level set of `ρ` at `p`: the kernel of the + complex-linear part of the derivative. +* `IsLeviPseudoconvexAt`: The Levi condition at a boundary point: the Levi form of every local + defining function is positive semidefinite on the complex tangent space. +* `IsLeviPseudoconvex`: Levi pseudoconvexity: the Levi condition at every boundary point. + +## Main results + +* `bilinear_smul_smul_eq`: **Quadratic decomposition along a complex line.** For a symmetric real + bilinear form `B`, `B (ζ • w) (ζ • w) / 2` is `‖ζ‖ ^ 2` times the Hermitian part `(B w w + B (I • + w) (I • w)) / 4` plus the real part of `ζ ^ 2` times the complex quadratic coefficient `(B w w - B + (I • w) (I • w)) / 4 - I / 2 * B w (I • w)`. +* `Convex.isLeviPseudoconvex`: **Convex open sets are Levi pseudoconvex** ([Range][Range1986], Lemma + 2.10). + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +section ComplexPart + +/-- The complex-linear part `c ↦ ℓ c - I * ℓ (I • c)` of a real functional: Mathlib's +`StrongDual.extendRCLike` with the scalar field fixed to `ℂ`. -/ +abbrev complexPart (ℓ : E →L[ℝ] ℝ) : E →L[ℂ] ℂ := StrongDual.extendRCLike ℓ + +/-- The defining formula of the complex-linear part. -/ +theorem complexPart_apply (ℓ : E →L[ℝ] ℝ) (c : E) : + complexPart ℓ c = (ℓ c : ℂ) - I * (ℓ (I • c) : ℂ) := rfl + +/-- A real functional on a complex multiple is the real part of the complex multiple of its +complex-linear part. -/ +theorem apply_smul_eq_re_mul_complexPart (ℓ : E →L[ℝ] ℝ) (ζ : ℂ) (c : E) : + ℓ (ζ • c) = (ζ * complexPart ℓ c).re := by + rw [Complex.smul_eq_re_smul_add_im_smul, map_add, map_smul, map_smul, smul_eq_mul, smul_eq_mul, + complexPart_apply] + simp [Complex.mul_re, Complex.mul_im] + +/-- The real part of the complex part of a real functional is the functional itself. -/ +theorem re_complexPart (ℓ : E →L[ℝ] ℝ) (c : E) : (complexPart ℓ c).re = ℓ c := by + simp [complexPart_apply] + +/-- A nonzero real functional has a vector on which its complex-linear part is nonzero. -/ +theorem exists_complexPart_ne_zero {ℓ : E →L[ℝ] ℝ} (hℓ : ℓ ≠ 0) : ∃ c, complexPart ℓ c ≠ 0 := by + obtain ⟨c, hc⟩ : ∃ c, ℓ c ≠ 0 := by + by_contra h + push Not at h + exact hℓ (ContinuousLinearMap.ext h) + refine ⟨c, fun h => hc ?_⟩ + rw [← re_complexPart, h, Complex.zero_re] + +/-- Every complex value is attained by the complex-linear part of a nonzero real functional. -/ +theorem exists_complexPart_eq {ℓ : E →L[ℝ] ℝ} (hℓ : ℓ ≠ 0) (q : ℂ) : + ∃ c, complexPart ℓ c = q := by + obtain ⟨c₀, hc₀⟩ := exists_complexPart_ne_zero hℓ + refine ⟨(q / complexPart ℓ c₀) • c₀, ?_⟩ + rw [map_smul, smul_eq_mul, div_mul_cancel₀ _ hc₀] + +/-- **Quadratic decomposition along a complex line.** For a symmetric real bilinear form `B`, +`B (ζ • w) (ζ • w) / 2` is `‖ζ‖ ^ 2` times the Hermitian part +`(B w w + B (I • w) (I • w)) / 4` plus the real part of `ζ ^ 2` times the complex quadratic +coefficient `(B w w - B (I • w) (I • w)) / 4 - I / 2 * B w (I • w)`. -/ +theorem bilinear_smul_smul_eq (B : E →L[ℝ] E →L[ℝ] ℝ) {w : E} + (hsymm : B w (I • w) = B (I • w) w) (ζ : ℂ) : + (1 / 2 : ℝ) * B (ζ • w) (ζ • w) = + ‖ζ‖ ^ 2 * ((B w w + B (I • w) (I • w)) / 4) + + (ζ ^ 2 * (((B w w - B (I • w) (I • w)) / 4 : ℝ) - I / 2 * B w (I • w))).re := by + rw [Complex.smul_eq_re_smul_add_im_smul] + simp only [map_add, map_smul, add_apply, smul_apply, smul_eq_mul, hsymm] + rw [Complex.sq_norm, Complex.normSq_apply] + simp [Complex.mul_re, Complex.mul_im, pow_two] + ring + +end ComplexPart + +section Defining + +/-- A local `C²` defining function for `U` at `p` on the open neighborhood `V`: `ρ p = 0`, the real +derivative of `ρ` at `p` is nonzero, and `U ∩ V` is the negative sublevel set of `ρ` in `V`. -/ +structure IsLocalDefiningFunction (U : Set E) (p : E) (ρ : E → ℝ) (V : Set E) : Prop where + /-- The defining neighborhood is open. -/ + isOpen : IsOpen V + /-- The boundary point lies in the defining neighborhood. -/ + mem : p ∈ V + /-- The defining function is twice continuously real differentiable. -/ + contDiffOn : ContDiffOn ℝ 2 ρ V + /-- The defining function vanishes at the boundary point. -/ + eq_zero : ρ p = 0 + /-- The real derivative is nonzero at the boundary point. -/ + fderiv_ne : fderiv ℝ ρ p ≠ 0 + /-- The domain is the negative sublevel set in the defining neighborhood. -/ + inter_eq : U ∩ V = {z | ρ z < 0} ∩ V + +/-- A set has `C²` boundary if every boundary point has a local defining function. -/ +@[expose] def HasC2Boundary (U : Set E) : Prop := + ∀ p ∈ frontier U, ∃ (ρ : E → ℝ) (V : Set E), IsLocalDefiningFunction U p ρ V + +/-- The complex tangent space of the level set of `ρ` at `p`: the kernel of the complex-linear part +of the derivative. -/ +@[expose] def IsComplexTangent (ρ : E → ℝ) (p w : E) : Prop := + fderiv ℝ ρ p w = 0 ∧ fderiv ℝ ρ p (I • w) = 0 + +/-- The Levi condition at a boundary point: the Levi form of every local defining function is +positive semidefinite on the complex tangent space. -/ +@[expose] def IsLeviPseudoconvexAt (U : Set E) (p : E) : Prop := + ∀ (ρ : E → ℝ) (V : Set E), IsLocalDefiningFunction U p ρ V → + ∀ w, IsComplexTangent ρ p w → 0 ≤ leviForm ρ p w + +/-- Levi pseudoconvexity: the Levi condition at every boundary point. -/ +@[expose] def IsLeviPseudoconvex (U : Set E) : Prop := + ∀ p ∈ frontier U, IsLeviPseudoconvexAt U p + +/-- The complex tangent space is closed under multiplication by `I`. -/ +theorem IsComplexTangent.smul_I {ρ : E → ℝ} {p w : E} (h : IsComplexTangent ρ p w) : + IsComplexTangent ρ p (I • w) := by + refine ⟨h.2, ?_⟩ + rw [smul_smul, Complex.I_mul_I, neg_one_smul, map_neg, h.1, neg_zero] + +/-- Points near `p` where the defining function is negative lie in `U`. -/ +theorem IsLocalDefiningFunction.mem_of_neg {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + (h : IsLocalDefiningFunction U p ρ V) {z : E} (hz : z ∈ V) (hρ : ρ z < 0) : z ∈ U := by + have : z ∈ {z | ρ z < 0} ∩ V := ⟨hρ, hz⟩ + rw [← h.inter_eq] at this + exact this.1 + +/-- Points of `V` in `U` have negative defining function. -/ +theorem IsLocalDefiningFunction.neg_of_mem {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + (h : IsLocalDefiningFunction U p ρ V) {z : E} (hz : z ∈ V) (hU : z ∈ U) : ρ z < 0 := by + have : z ∈ U ∩ V := ⟨hU, hz⟩ + rw [h.inter_eq] at this + exact this.1 + +end Defining + +section Convex + +variable {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + +/-- Along a real tangent direction, the second derivative of a defining function of a convex open +set is nonnegative. -/ +theorem IsLocalDefiningFunction.fderiv_fderiv_nonneg_of_convex (hU : IsOpen U) + (hconv : Convex ℝ U) (hp : p ∈ frontier U) (h : IsLocalDefiningFunction U p ρ V) + {w : E} (hw : fderiv ℝ ρ p w = 0) : 0 ≤ fderiv ℝ (fderiv ℝ ρ) p w w := by + by_contra hneg + push Not at hneg + set A := fderiv ℝ (fderiv ℝ ρ) p w w with hA + -- the slice along the complex line through `p` in direction `w` + set g : ℂ → ℝ := fun t => ρ (p + t • w) with hg + have hρp : ContDiffAt ℝ 2 ρ (p + (0 : ℂ) • w) := by + simpa using h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem) + have hgc : ContDiffAt ℝ 2 g 0 := hρp.comp 0 + (by fun_prop : ContDiff ℝ 2 fun t : ℂ => p + t • w).contDiffAt + obtain ⟨δ₁, hδ₁, htaylor⟩ := exists_taylor_bound hgc (ε := -A / 4) (by linarith) + obtain ⟨δ₂, hδ₂, hV⟩ := Metric.mem_nhds_iff.mp + ((by fun_prop : Continuous fun t : ℂ => p + t • w).continuousAt.preimage_mem_nhds (by + show V ∈ 𝓝 ((fun t : ℂ => p + t • w) 0) + simpa using h.isOpen.mem_nhds h.mem)) + have hD1 : fderiv ℝ g 0 = (fderiv ℝ ρ p).comp ((ContinuousLinearMap.id ℝ ℂ).smulRight w) := by + have := fderiv_slice (f := ρ) (a := p) (w := w) (t₀ := 0) (hρp.differentiableAt (by norm_num)) + simpa using this + have hD2 : ∀ s s' : ℂ, fderiv ℝ (fderiv ℝ g) 0 s s' = fderiv ℝ (fderiv ℝ ρ) p (s • w) (s' • w) + := by + intro s s' + have := fderiv_fderiv_slice (f := ρ) (a := p) (w := w) (t₀ := 0) hρp s s' + simpa using this + -- the slice is negative at small nonzero real parameters + have hneg' : ∀ x : ℝ, x ≠ 0 → |x| < min δ₁ δ₂ → p + (x : ℂ) • w ∈ U := by + intro x hx hxδ + have hxδ₁ : ‖(x : ℂ)‖ < δ₁ := by simpa using hxδ.trans_le (min_le_left _ _) + have hxδ₂ : (x : ℂ) ∈ ball (0 : ℂ) δ₂ := by + simpa using hxδ.trans_le (min_le_right _ _) + have ht := htaylor (x : ℂ) hxδ₁ + have hg0 : g 0 = 0 := by simp [hg, h.eq_zero] + have hlin : fderiv ℝ g 0 (x : ℂ) = 0 := by + rw [hD1, ContinuousLinearMap.comp_apply, ContinuousLinearMap.smulRight_apply, + ContinuousLinearMap.id_apply, Complex.coe_smul, map_smul, hw, + smul_zero] + have hquad : fderiv ℝ (fderiv ℝ g) 0 (x : ℂ) (x : ℂ) = x ^ 2 * A := by + rw [hD2, Complex.coe_smul, map_smul, map_smul] + simp only [smul_apply, smul_eq_mul] + rw [hA] + ring + rw [hg0, hlin, hquad, sub_zero, sub_zero, zero_add] at ht + have hxn : ‖(x : ℂ)‖ ^ 2 = x ^ 2 := by simp [sq_abs] + rw [hxn] at ht + have hx2 : 0 < x ^ 2 := by positivity + have : g (x : ℂ) < 0 := by + have := (abs_le.mp ht).2 + nlinarith + exact h.mem_of_neg (hV hxδ₂) this + -- convexity puts `p` into `U` + set x : ℝ := min δ₁ δ₂ / 2 with hx + have hx0 : 0 < x := by positivity + have hxlt : |x| < min δ₁ δ₂ := by + rw [abs_of_pos hx0, hx] + linarith [lt_min hδ₁ hδ₂] + have h1 := hneg' x hx0.ne' hxlt + have h2 := hneg' (-x) (neg_ne_zero.mpr hx0.ne') (by rwa [abs_neg]) + have hmid : p = (1 / 2 : ℝ) • (p + (x : ℂ) • w) + (1 / 2 : ℝ) • (p + ((-x : ℝ) : ℂ) • w) := by + simp only [Complex.coe_smul] + module + have : p ∈ U := by + rw [hmid] + exact hconv h1 h2 (by norm_num) (by norm_num) (by norm_num) + exact hU.notMem_of_mem_frontier hp this + +/-- **Convex open sets are Levi pseudoconvex** ([Range][Range1986], Lemma 2.10). -/ +theorem _root_.Convex.isLeviPseudoconvex (hU : IsOpen U) (hconv : Convex ℝ U) : + IsLeviPseudoconvex U := by + intro p hp ρ V h w hw + have h1 := h.fderiv_fderiv_nonneg_of_convex hU hconv hp hw.1 + have h2 := h.fderiv_fderiv_nonneg_of_convex hU hconv hp hw.smul_I.1 + rw [leviForm_eq_fderiv] + linarith + +end Convex + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Independence.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Independence.lean new file mode 100644 index 0000000000..9d705fda1b --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Independence.lean @@ -0,0 +1,318 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.Deriv.Comp +public import Mathlib.Analysis.Calculus.Deriv.Slope +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion + +/-! +# Independence of the defining function + +Two local `C²` defining functions of the same open set at the same boundary point have +positively proportional derivatives, and their second derivatives are proportional by the same +factor on tangent vectors. Consequently the complex tangent space and the sign of the Levi form +on it do not depend on the choice of defining function, and the Levi condition can be verified +on a single defining function. + +The proofs avoid the implicit function theorem and the positive-factor lemma of +[Range][Range1986] (Lemma 2.5). First derivatives are compared through one-sided difference +quotients along lines entering the set; second derivatives through second-order expansions along +parabolic curves `t ↦ p + t v + β t² ν`, whose sign is controlled by the defining property. + +References: [Range][Range1986] (1986), Chapter II, Lemma 2.5 and the discussion after (2.19); +[Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Lemma 4.1. + +## Main results + +* `IsLocalDefiningFunction.exists_fderiv_eq_smul`: **First-order comparison.** The derivatives of + two defining functions at the same boundary point are positively proportional. +* `IsLocalDefiningFunction.fderiv_fderiv_eq`: **Second-order comparison.** On tangent vectors, the + second derivatives of two defining functions are proportional with the same positive factor as + their first derivatives. +* `isLeviPseudoconvexAt_iff_of_defining`: **The Levi condition can be checked on one defining + function.** + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +open TaylorBounds + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + + +section Comparison + +variable {U : Set E} {p : E} {ρ ρ₁ ρ₂ : E → ℝ} {V V₁ V₂ : Set E} + +/-- Second-order expansion of a `C²` function along the parabolic curve `t ↦ p + t • v + (β * t ^ 2) +• ν`. -/ +theorem exists_parabola_bound (hρ : ContDiffAt ℝ 2 ρ p) (v ν : E) (β : ℝ) {η : ℝ} (hη : 0 < η) : + ∃ δ > 0, ∀ t : ℝ, 0 < t → t < δ → + |ρ (p + t • v + (β * t ^ 2) • ν) - ρ p - (t * fderiv ℝ ρ p v + β * t ^ 2 * fderiv ℝ ρ p ν + + t ^ 2 / 2 * fderiv ℝ (fderiv ℝ ρ) p v v)| ≤ η * t ^ 2 := by + set B := fderiv ℝ (fderiv ℝ ρ) p with hB + set M₀ : ℝ := ‖v‖ + |β| * ‖ν‖ with hM₀ + set M₁ : ℝ := |β| * ‖B‖ * ‖v‖ * ‖ν‖ + β ^ 2 * ‖B‖ * ‖ν‖ ^ 2 / 2 with hM₁ + have hM₀0 : 0 ≤ M₀ := by positivity + have hM₁0 : 0 ≤ M₁ := by positivity + obtain ⟨δ', hδ', htaylor⟩ := exists_taylor_bound hρ (ε := η / (2 * (M₀ ^ 2 + 1))) (by positivity) + refine ⟨min 1 (min (η / (2 * (M₁ + 1))) (δ' / (2 * (M₀ + 1)))), by positivity, fun t ht htδ => ?_⟩ + obtain ⟨ht1, htM₁, htδ'⟩ := + le_one_and_mul_add_le_of_le_min hM₀0 hM₁0 ht (le_of_lt htδ) + set k : E := t • v + (β * t ^ 2) • ν with hk + have hkn : ‖k‖ ≤ t * M₀ := by + calc ‖k‖ ≤ ‖t • v‖ + ‖(β * t ^ 2) • ν‖ := norm_add_le _ _ + _ = t * ‖v‖ + |β| * t ^ 2 * ‖ν‖ := by + rw [norm_smul, norm_smul, Real.norm_eq_abs, Real.norm_eq_abs, abs_of_pos ht, abs_mul, + abs_of_pos (by positivity : (0:ℝ) < t ^ 2)] + _ ≤ t * ‖v‖ + |β| * t * ‖ν‖ := by + have : t ^ 2 ≤ t := by nlinarith + gcongr + _ = t * M₀ := by rw [hM₀]; ring + have hklt : ‖k‖ < δ' := hkn.trans_lt (by nlinarith) + have htay : |ρ (p + k) - ρ p - fderiv ℝ ρ p k - (1 / 2 : ℝ) * B k k| ≤ + η / (2 * (M₀ ^ 2 + 1)) * ‖k‖ ^ 2 := htaylor k hklt + have hsplit : p + t • v + (β * t ^ 2) • ν = p + k := by rw [hk]; abel + have hlin : fderiv ℝ ρ p k = t * fderiv ℝ ρ p v + β * t ^ 2 * fderiv ℝ ρ p ν := by + rw [hk, map_add, map_smul, map_smul, smul_eq_mul, smul_eq_mul] + have hquad : (1 / 2 : ℝ) * B k k - t ^ 2 / 2 * B v v = + (1 / 2 : ℝ) * (β * t ^ 3 * (B v ν + B ν v) + β ^ 2 * t ^ 4 * B ν ν) := by + rw [hk] + simp only [map_add, map_smul, add_apply, smul_apply, smul_eq_mul] + ring + have hBn : 0 ≤ ‖B‖ := ContinuousLinearMap.opNorm_nonneg B + have hquad_bd : |(1 / 2 : ℝ) * B k k - t ^ 2 / 2 * B v v| ≤ M₁ * t ^ 3 := by + rw [hquad, abs_mul, abs_of_pos (by norm_num : (0:ℝ) < 1 / 2)] + have h1 : |B v ν| ≤ ‖B‖ * ‖v‖ * ‖ν‖ := by + have := B.le_opNorm₂ v ν; rwa [Real.norm_eq_abs] at this + have h2 : |B ν v| ≤ ‖B‖ * ‖ν‖ * ‖v‖ := by + have := B.le_opNorm₂ ν v; rwa [Real.norm_eq_abs] at this + have h3 : |B ν ν| ≤ ‖B‖ * ‖ν‖ * ‖ν‖ := by + have := B.le_opNorm₂ ν ν; rwa [Real.norm_eq_abs] at this + have ht3 : 0 ≤ t ^ 3 := by positivity + have ht4 : t ^ 4 ≤ t ^ 3 := by + calc t ^ 4 = t ^ 3 * t := by ring + _ ≤ t ^ 3 * 1 := by gcongr + _ = t ^ 3 := mul_one _ + calc 1 / 2 * |β * t ^ 3 * (B v ν + B ν v) + β ^ 2 * t ^ 4 * B ν ν| + ≤ 1 / 2 * (|β| * t ^ 3 * (|B v ν| + |B ν v|) + β ^ 2 * t ^ 4 * |B ν ν|) := by + gcongr + calc |β * t ^ 3 * (B v ν + B ν v) + β ^ 2 * t ^ 4 * B ν ν| + ≤ |β * t ^ 3 * (B v ν + B ν v)| + |β ^ 2 * t ^ 4 * B ν ν| := abs_add_le _ _ + _ = |β| * t ^ 3 * |B v ν + B ν v| + β ^ 2 * t ^ 4 * |B ν ν| := by + rw [abs_mul, abs_mul, abs_mul, abs_mul, abs_of_nonneg ht3, abs_pow, + abs_of_nonneg (by positivity : (0:ℝ) ≤ t ^ 4)] + simp [sq_abs] + _ ≤ |β| * t ^ 3 * (|B v ν| + |B ν v|) + β ^ 2 * t ^ 4 * |B ν ν| := by + gcongr + exact abs_add_le _ _ + _ ≤ 1 / 2 * (|β| * t ^ 3 * (‖B‖ * ‖v‖ * ‖ν‖ + ‖B‖ * ‖ν‖ * ‖v‖) + + β ^ 2 * t ^ 3 * (‖B‖ * ‖ν‖ * ‖ν‖)) := by + gcongr + _ = M₁ * t ^ 3 := by rw [hM₁]; ring + have hR : |ρ (p + k) - ρ p - fderiv ℝ ρ p k - (1 / 2 : ℝ) * B k k| ≤ + η / (2 * (M₀ ^ 2 + 1)) * (t * M₀) ^ 2 := by + refine htay.trans ?_ + gcongr + rw [hsplit] + have hkey : ρ (p + k) - ρ p - (t * fderiv ℝ ρ p v + β * t ^ 2 * fderiv ℝ ρ p ν + + t ^ 2 / 2 * B v v) = (ρ (p + k) - ρ p - fderiv ℝ ρ p k - (1 / 2 : ℝ) * B k k) + + ((1 / 2 : ℝ) * B k k - t ^ 2 / 2 * B v v) := by + rw [hlin]; ring + rw [hkey] + exact taylor_remainder_add_cubic_le ht hη htM₁ hR hquad_bd + +/-- A defining function is negative along a line entering the set, and the derivative of any other +defining function in that direction is nonpositive. -/ +theorem IsLocalDefiningFunction.fderiv_nonpos_of_fderiv_neg (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) {v : E} (hv : fderiv ℝ ρ₂ p v < 0) : + fderiv ℝ ρ₁ p v ≤ 0 := by + have hd : ∀ (ρ : E → ℝ) (V : Set E), IsLocalDefiningFunction U p ρ V → + HasDerivAt (fun t : ℝ => ρ (p + t • v)) (fderiv ℝ ρ p v) 0 := by + intro ρ V h + have hρ : DifferentiableAt ℝ ρ (p + (0 : ℝ) • v) := by + simpa using (h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem)).differentiableAt (by norm_num) + have hl : HasDerivAt (fun t : ℝ => p + t • v) v 0 := by + simpa using ((hasDerivAt_id (0 : ℝ)).smul_const v).const_add p + have := hρ.hasFDerivAt.comp_hasDerivAt (0 : ℝ) hl + convert this using 2 <;> simp + have h1 := (hasDerivAt_iff_tendsto_slope_zero.mp (hd ρ₁ V₁ h₁)).mono_left (nhdsGT_le_nhdsNE 0) + have h2 := (hasDerivAt_iff_tendsto_slope_zero.mp (hd ρ₂ V₂ h₂)).mono_left (nhdsGT_le_nhdsNE 0) + simp only [zero_add, zero_smul, add_zero, h₁.eq_zero, h₂.eq_zero, sub_zero, smul_eq_mul] at h1 h2 + -- the slopes of `ρ₂` are eventually negative, so the points lie in `U` + have hneg : ∀ᶠ t in 𝓝[>] (0 : ℝ), t⁻¹ * ρ₂ (p + t • v) < 0 := + h2.eventually (eventually_lt_nhds hv) + have hV : ∀ᶠ t in 𝓝[>] (0 : ℝ), p + t • v ∈ V₁ ∩ V₂ := by + have hc : ContinuousAt (fun t : ℝ => p + t • v) 0 := by fun_prop + have hVp : V₁ ∩ V₂ ∈ 𝓝 p := inter_mem (h₁.isOpen.mem_nhds h₁.mem) (h₂.isOpen.mem_nhds h₂.mem) + have := hc.preimage_mem_nhds (by convert hVp using 2; simp) + exact nhdsWithin_le_nhds this + have hle : ∀ᶠ t in 𝓝[>] (0 : ℝ), t⁻¹ * ρ₁ (p + t • v) ≤ 0 := by + filter_upwards [hneg, hV, self_mem_nhdsWithin] with t ht htV htpos + have ht0 : 0 < t := htpos + have hρ₂ : ρ₂ (p + t • v) < 0 := by + by_contra hcon + push Not at hcon + have : 0 ≤ t⁻¹ * ρ₂ (p + t • v) := mul_nonneg (inv_nonneg.mpr ht0.le) hcon + linarith + have hU : p + t • v ∈ U := h₂.mem_of_neg htV.2 hρ₂ + have hρ₁ : ρ₁ (p + t • v) < 0 := h₁.neg_of_mem htV.1 hU + exact mul_nonpos_of_nonneg_of_nonpos (inv_nonneg.mpr ht0.le) hρ₁.le + exact le_of_tendsto h1 hle + +/-- **First-order comparison.** The derivatives of two defining functions at the same boundary +point are positively proportional. -/ +theorem IsLocalDefiningFunction.exists_fderiv_eq_smul (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) : + ∃ c : ℝ, 0 < c ∧ fderiv ℝ ρ₁ p = c • fderiv ℝ ρ₂ p := + ContinuousLinearMap.exists_pos_smul_eq_of_neg_imp_nonpos h₁.fderiv_ne h₂.fderiv_ne fun _ hv => + h₁.fderiv_nonpos_of_fderiv_neg h₂ hv + +/-- One half of the second-order comparison on tangent vectors. -/ +theorem IsLocalDefiningFunction.fderiv_fderiv_le (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) {c : ℝ} (hc : 0 < c) + (hℓ : fderiv ℝ ρ₁ p = c • fderiv ℝ ρ₂ p) {v : E} (hv : fderiv ℝ ρ₂ p v = 0) : + fderiv ℝ (fderiv ℝ ρ₁) p v v ≤ c * fderiv ℝ (fderiv ℝ ρ₂) p v v := by + by_contra hlt + push Not at hlt + set a₁ := fderiv ℝ (fderiv ℝ ρ₁) p v v with ha₁ + set a₂ := fderiv ℝ (fderiv ℝ ρ₂) p v v with ha₂ + -- an inward direction for `ρ₂` + obtain ⟨u, hu⟩ : ∃ u, fderiv ℝ ρ₂ p u ≠ 0 := by + by_contra hcon + push Not at hcon + exact h₂.fderiv_ne (ContinuousLinearMap.ext hcon) + set ν : E := (1 / fderiv ℝ ρ₂ p u) • u with hν + have hν₂ : fderiv ℝ ρ₂ p ν = 1 := by + rw [hν, map_smul, smul_eq_mul, one_div, inv_mul_cancel₀ hu] + have hν₁ : fderiv ℝ ρ₁ p ν = c := by rw [hℓ, smul_apply, hν₂, smul_eq_mul, mul_one] + have hv₁ : fderiv ℝ ρ₁ p v = 0 := by rw [hℓ, smul_apply, hv, smul_zero] + -- the parabola parameter + set β : ℝ := (-a₂ / 2 + -a₁ / (2 * c)) / 2 with hβ + have hβ₂ : β + a₂ / 2 < 0 := by + rw [hβ] + have : -a₁ / (2 * c) < -a₂ / 2 := by + rw [div_lt_div_iff₀ (by positivity) (by norm_num)] + nlinarith + linarith + have hβ₁ : 0 < c * β + a₁ / 2 := by + rw [hβ] + have : -a₂ / 2 > -a₁ / (2 * c) := by + rw [gt_iff_lt, div_lt_div_iff₀ (by positivity) (by norm_num)] + nlinarith + have hc' : c * (-a₁ / (2 * c)) = -a₁ / 2 := by field_simp + nlinarith + set η : ℝ := min (-(β + a₂ / 2) / 2) ((c * β + a₁ / 2) / 2) with hη + have hη0 : 0 < η := lt_min (by linarith) (by linarith) + have hρ₁c : ContDiffAt ℝ 2 ρ₁ p := h₁.contDiffOn.contDiffAt (h₁.isOpen.mem_nhds h₁.mem) + have hρ₂c : ContDiffAt ℝ 2 ρ₂ p := h₂.contDiffOn.contDiffAt (h₂.isOpen.mem_nhds h₂.mem) + obtain ⟨δ₁, hδ₁, hb₁⟩ := exists_parabola_bound hρ₁c v ν β hη0 + obtain ⟨δ₂, hδ₂, hb₂⟩ := exists_parabola_bound hρ₂c v ν β hη0 + have hcont : ContinuousAt (fun t : ℝ => p + t • v + (β * t ^ 2) • ν) 0 := by fun_prop + have hVp : V₁ ∩ V₂ ∈ 𝓝 p := inter_mem (h₁.isOpen.mem_nhds h₁.mem) (h₂.isOpen.mem_nhds h₂.mem) + obtain ⟨δ₃, hδ₃, hV⟩ := Metric.mem_nhds_iff.mp (hcont.preimage_mem_nhds (by + convert hVp using 2 + simp)) + set t : ℝ := min δ₁ (min δ₂ δ₃) / 2 with ht + have ht0 : 0 < t := by positivity + have ht₁ : t < δ₁ := by + have := min_le_left δ₁ (min δ₂ δ₃) + rw [ht]; linarith [lt_min hδ₁ (lt_min hδ₂ hδ₃)] + have ht₂ : t < δ₂ := by + have := (min_le_right δ₁ (min δ₂ δ₃)).trans (min_le_left δ₂ δ₃) + rw [ht]; linarith [lt_min hδ₁ (lt_min hδ₂ hδ₃)] + have ht₃ : t < δ₃ := by + have := (min_le_right δ₁ (min δ₂ δ₃)).trans (min_le_right δ₂ δ₃) + rw [ht]; linarith [lt_min hδ₁ (lt_min hδ₂ hδ₃)] + set z := p + t • v + (β * t ^ 2) • ν with hz + have hzV : z ∈ V₁ ∩ V₂ := hV (by + rw [mem_ball, dist_zero_right, Real.norm_eq_abs, abs_of_pos ht0] + exact ht₃) + have e₁ := hb₁ t ht0 ht₁ + have e₂ := hb₂ t ht0 ht₂ + rw [h₁.eq_zero, hv₁, hν₁] at e₁ + rw [h₂.eq_zero, hv, hν₂] at e₂ + have hρ₂ : ρ₂ z < 0 := by + have := (abs_le.mp e₂).2 + have hη' : η ≤ -(β + a₂ / 2) / 2 := min_le_left _ _ + have ht2 : 0 < t ^ 2 := by positivity + nlinarith + have hρ₁ : 0 < ρ₁ z := by + have := (abs_le.mp e₁).1 + have hη' : η ≤ (c * β + a₁ / 2) / 2 := min_le_right _ _ + have ht2 : 0 < t ^ 2 := by positivity + nlinarith + have hU : z ∈ U := h₂.mem_of_neg hzV.2 hρ₂ + have := h₁.neg_of_mem hzV.1 hU + linarith + +/-- **Second-order comparison.** On tangent vectors, the second derivatives of two defining +functions are proportional with the same positive factor as their first derivatives. -/ +theorem IsLocalDefiningFunction.fderiv_fderiv_eq (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) {c : ℝ} (hc : 0 < c) + (hℓ : fderiv ℝ ρ₁ p = c • fderiv ℝ ρ₂ p) {v : E} (hv : fderiv ℝ ρ₂ p v = 0) : + fderiv ℝ (fderiv ℝ ρ₁) p v v = c * fderiv ℝ (fderiv ℝ ρ₂) p v v := by + have h1 := h₁.fderiv_fderiv_le h₂ hc hℓ hv + have hℓ' : fderiv ℝ ρ₂ p = c⁻¹ • fderiv ℝ ρ₁ p := by + rw [hℓ, smul_smul, inv_mul_cancel₀ hc.ne', one_smul] + have hv₁ : fderiv ℝ ρ₁ p v = 0 := by rw [hℓ, smul_apply, hv, smul_zero] + have h2 := h₂.fderiv_fderiv_le h₁ (inv_pos.mpr hc) hℓ' hv₁ + have : c * fderiv ℝ (fderiv ℝ ρ₂) p v v ≤ fderiv ℝ (fderiv ℝ ρ₁) p v v := by + have := mul_le_mul_of_nonneg_left h2 hc.le + rwa [← mul_assoc, mul_inv_cancel₀ hc.ne', one_mul] at this + exact le_antisymm h1 this + +/-- The complex tangent space does not depend on the defining function. -/ +theorem IsLocalDefiningFunction.isComplexTangent_iff (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) (w : E) : + IsComplexTangent ρ₁ p w ↔ IsComplexTangent ρ₂ p w := by + obtain ⟨c, hc, hℓ⟩ := h₁.exists_fderiv_eq_smul h₂ + simp only [IsComplexTangent, hℓ, smul_apply, smul_eq_mul, + mul_eq_zero, hc.ne', false_or] + +/-- On complex tangent vectors, the Levi forms of two defining functions are positively +proportional. -/ +theorem IsLocalDefiningFunction.exists_leviForm_eq (h₁ : IsLocalDefiningFunction U p ρ₁ V₁) + (h₂ : IsLocalDefiningFunction U p ρ₂ V₂) : + ∃ c : ℝ, 0 < c ∧ ∀ w, IsComplexTangent ρ₂ p w → leviForm ρ₁ p w = c * leviForm ρ₂ p w := by + obtain ⟨c, hc, hℓ⟩ := h₁.exists_fderiv_eq_smul h₂ + refine ⟨c, hc, fun w hw => ?_⟩ + rw [leviForm_eq_fderiv, leviForm_eq_fderiv, h₁.fderiv_fderiv_eq h₂ hc hℓ hw.1, + h₁.fderiv_fderiv_eq h₂ hc hℓ hw.smul_I.1] + ring + +/-- **The Levi condition can be checked on one defining function.** -/ +theorem isLeviPseudoconvexAt_iff_of_defining (h : IsLocalDefiningFunction U p ρ V) : + IsLeviPseudoconvexAt U p ↔ ∀ w, IsComplexTangent ρ p w → 0 ≤ leviForm ρ p w := by + constructor + · intro hL w hw + exact hL ρ V h w hw + · intro hL ρ' V' h' w hw + obtain ⟨c, hc, hlev⟩ := h'.exists_leviForm_eq h + have hw' : IsComplexTangent ρ p w := (h'.isComplexTangent_iff h w).mp hw + rw [hlev w hw'] + exact mul_nonneg hc.le (hL w hw') + +end Comparison + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Invariance.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Invariance.lean new file mode 100644 index 0000000000..4b5164c01a --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Invariance.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic + +/-! +# Invariance of the Levi condition under holomorphic maps + +A local defining function pulls back along a holomorphic map with surjective derivative to a +local defining function of the preimage. Complex tangent vectors correspond under the +derivative, and the Levi form transforms by the chain rule of `LeviForm.Holomorphic`. +Consequently, for a holomorphic map with invertible derivative at `p`, the Levi condition for a +defining function at `Φ p` is equivalent to the Levi condition for its pullback at `p`. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 4, Remark +after the definition of Levi convexity; [Range][Range1986] (1986), Chapter II, Lemma 2.12. + +## Main results + +* `leviCondition_comp_iff`: **Invariance of the Levi condition.** For a holomorphic map with + invertible derivative at `p`, the Levi condition for a defining function at `Φ p` holds exactly + when it holds for the pullback at `p`. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The derivative of a composition with a holomorphic map, over the reals. -/ +theorem fderiv_comp_analytic {ρ : F → ℝ} {Φ : E → F} {p : E} (hΦ : AnalyticAt ℂ Φ p) + (hρ : DifferentiableAt ℝ ρ (Φ p)) : + fderiv ℝ (ρ ∘ Φ) p = (fderiv ℝ ρ (Φ p)).comp ((fderiv ℂ Φ p).restrictScalars ℝ) := + (hρ.hasFDerivAt.comp p (hΦ.differentiableAt.hasFDerivAt.restrictScalars ℝ)).fderiv + +/-- Complex tangent vectors of a pullback correspond to complex tangent vectors of the image under +the derivative. -/ +theorem isComplexTangent_comp_iff {ρ : F → ℝ} {Φ : E → F} {p : E} (hΦ : AnalyticAt ℂ Φ p) + (hρ : DifferentiableAt ℝ ρ (Φ p)) (w : E) : + IsComplexTangent (ρ ∘ Φ) p w ↔ IsComplexTangent ρ (Φ p) (fderiv ℂ Φ p w) := by + simp only [IsComplexTangent, fderiv_comp_analytic hΦ hρ, ContinuousLinearMap.comp_apply, + ContinuousLinearMap.coe_restrictScalars', map_smul] + +variable {U : Set F} {q : F} {ρ : F → ℝ} {V : Set F} + +/-- A local defining function pulls back along a holomorphic map with surjective derivative to a +local defining function of the preimage. -/ +theorem IsLocalDefiningFunction.comp_analytic (h : IsLocalDefiningFunction U q ρ V) + {Φ : E → F} {W : Set E} (hW : IsOpen W) {p : E} (hp : p ∈ W) (hΦ : AnalyticOnNhd ℂ Φ W) + (hΦp : Φ p = q) (hsurj : Function.Surjective (fderiv ℂ Φ p)) : + IsLocalDefiningFunction (Φ ⁻¹' U) p (ρ ∘ Φ) (W ∩ Φ ⁻¹' V) := by + have hρd : DifferentiableAt ℝ ρ (Φ p) := by + rw [hΦp] + exact (h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem)).differentiableAt (by norm_num) + refine ⟨hΦ.continuousOn.isOpen_inter_preimage hW h.isOpen, ⟨hp, by simp [hΦp, h.mem]⟩, ?_, + by simp [Function.comp, hΦp, h.eq_zero], ?_, ?_⟩ + · exact h.contDiffOn.comp + (((hΦ.contDiffOn hW.uniqueDiffOn (n := 2)).restrict_scalars ℝ).mono inter_subset_left) + fun z hz => hz.2 + · intro hzero + apply h.fderiv_ne + ext v + obtain ⟨u, hu⟩ := hsurj v + have := congrArg (fun L : E →L[ℝ] ℝ => L u) hzero + simp only [fderiv_comp_analytic (hΦ p hp) hρd, ContinuousLinearMap.comp_apply, + ContinuousLinearMap.coe_restrictScalars', zero_apply] at this + rw [hΦp, hu] at this + simpa using this + · ext z + simp only [mem_inter_iff, mem_preimage, mem_ofPred_eq, Function.comp] + constructor + · rintro ⟨hzU, hzW, hzV⟩ + exact ⟨h.neg_of_mem hzV hzU, hzW, hzV⟩ + · rintro ⟨hneg, hzW, hzV⟩ + exact ⟨h.mem_of_neg hzV hneg, hzW, hzV⟩ + +/-- **Invariance of the Levi condition.** For a holomorphic map with invertible derivative +at `p`, the Levi condition for a defining function at `Φ p` holds exactly when it holds for +the pullback at `p`. -/ +theorem leviCondition_comp_iff [CompleteSpace F] (h : IsLocalDefiningFunction U q ρ V) + {Φ : E → F} {p : E} + (hΦ : AnalyticAt ℂ Φ p) (hΦp : Φ p = q) (L : E ≃L[ℂ] F) + (hL : HasFDerivAt Φ (L : E →L[ℂ] F) p) : + (∀ w, IsComplexTangent (ρ ∘ Φ) p w → 0 ≤ leviForm (ρ ∘ Φ) p w) ↔ + (∀ v, IsComplexTangent ρ q v → 0 ≤ leviForm ρ q v) := by + subst hΦp + have hρ2 : ContDiffAt ℝ 2 ρ (Φ p) := h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem) + have hfd : fderiv ℂ Φ p = L := hL.fderiv + have hlev : ∀ w, leviForm (ρ ∘ Φ) p w = leviForm ρ (Φ p) (L w) := fun w => by + rw [leviForm_comp_analytic hρ2 hΦ, hfd] + rfl + have htan : ∀ w, IsComplexTangent (ρ ∘ Φ) p w ↔ IsComplexTangent ρ (Φ p) (L w) := fun w => by + rw [isComplexTangent_comp_iff hΦ (hρ2.differentiableAt (by norm_num)), hfd] + rfl + constructor + · intro hcond v hv + have := hcond (L.symm v) ((htan _).mpr (by simpa using hv)) + rwa [hlev, L.apply_symm_apply] at this + · intro hcond w hw + rw [hlev] + exact hcond _ ((htan w).mp hw) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Necessity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Necessity.lean new file mode 100644 index 0000000000..8b3abdce9f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Necessity.lean @@ -0,0 +1,521 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.Deriv.MeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity + +/-! +# Levi's necessary condition + +A domain of holomorphy in any finite-dimensional complex normed space with `C²` boundary is Levi +pseudoconvex. The proof in coordinates is transported by a continuous linear equivalence. This is E. +E. Levi's theorem ([Range][Range1986], Theorem 2.11; [Fritzsche–Grauert][FritzscheGrauert2002], +Theorem 4.7, first half). + +The proof avoids holomorphic coordinate changes. If the Levi form of a defining function `ρ` +were negative in a complex tangent direction `w` at a boundary point `p`, the Levi polynomial +provides a quadratic analytic disc `ζ ↦ p + ζ • w + ζ ^ 2 • c + ε • ν` tangent to the boundary +from inside, on which `ρ` behaves like `-ε + ‖ζ‖ ^ 2 L` with `L < 0`. Its boundary circle is +therefore much deeper inside the domain than its center. The boundary distance is comparable to +`|ρ|` near `p`, the center lies in the holomorphic hull of the boundary circle by the maximum +modulus principle, and Thullen's radius bound for domains of holomorphy then forces the center +to be as deep as the circle, a contradiction for small radii. + +References: [Range][Range1986] (1986), Chapter II, Theorems 2.9 and 2.11; +[Hörmander][Hormander1973] (1973), Section 2.6; [Fritzsche–Grauert][FritzscheGrauert2002] +(2002), Chapter II, Theorem 4.7. + +## Main definitions + +* `leviQuadratic`: The complex quadratic coefficient of a real bilinear form along a complex line. + +## Main results + +* `IsLocalDefiningFunction.exists_disc_estimate`: **Disc estimate along the Levi polynomial.** With + `c` cancelling the complex quadratic term and `ν` an inward direction, the defining function along + the disc `ζ ↦ p + ζ • w + ζ ^ 2 • c + (κ r ^ 2) • ν` is `-κ r ^ 2 + ‖ζ‖ ^ 2 L` up to `η r ^ 2`, + for `‖ζ‖ ≤ r` and `r` small, and the disc lies in any prescribed neighborhood of `p`. +* `IsDomainOfHolomorphy.isLeviPseudoconvex_fin`: **Levi's theorem in coordinates.** A domain of + holomorphy in `Fin n → ℂ` is Levi pseudoconvex: the Levi form of every local defining function is + positive semidefinite on the complex tangent space at every boundary point. +* `IsDomainOfHolomorphy.isLeviPseudoconvex`: **Levi's theorem.** A domain of holomorphy in a + finite-dimensional complex normed space is Levi pseudoconvex: the Levi form of every local + defining function is positive semidefinite on the complex tangent space at every boundary point. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +open TaylorBounds + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +variable {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + +/-- An inward direction for a defining function: the real derivative equals `1`. -/ +theorem IsLocalDefiningFunction.exists_inward_direction (h : IsLocalDefiningFunction U p ρ V) : + ∃ ν : E, fderiv ℝ ρ p ν = 1 ∧ 0 < ‖ν‖ := + ContinuousLinearMap.exists_apply_eq_one_of_ne_zero h.fderiv_ne + +/-- A neighborhood of `p` on which the derivative is Lipschitz-bounded and still points inward. -/ +theorem IsLocalDefiningFunction.exists_ball_fderiv_bound_and_inward + (h : IsLocalDefiningFunction U p ρ V) {ν : E} (hν : fderiv ℝ ρ p ν = 1) : + ∃ Lip δ₀ : ℝ, 0 < Lip ∧ 0 < δ₀ ∧ ball p δ₀ ⊆ + {y | y ∈ V ∧ ‖fderiv ℝ ρ y‖ ≤ Lip ∧ (1 / 2 : ℝ) ≤ fderiv ℝ ρ y ν} := by + set ℓ := fderiv ℝ ρ p + set Lip := ‖ℓ‖ + 1 + have hLip0 : 0 < Lip := by positivity + have hDcont : ContinuousOn (fderiv ℝ ρ) V := + h.contDiffOn.continuousOn_fderiv_of_isOpen h.isOpen (by norm_num) + have hcontp : ContinuousAt (fderiv ℝ ρ) p := hDcont.continuousAt (h.isOpen.mem_nhds h.mem) + have hev : ∀ᶠ y in 𝓝 p, y ∈ V ∧ ‖fderiv ℝ ρ y‖ ≤ Lip ∧ (1 / 2 : ℝ) ≤ fderiv ℝ ρ y ν := by + have h1 : ∀ᶠ y in 𝓝 p, y ∈ V := h.isOpen.mem_nhds h.mem + have h2 : ∀ᶠ y in 𝓝 p, ‖fderiv ℝ ρ y‖ ≤ Lip := + (continuous_norm.continuousAt.comp hcontp).eventually + (eventually_le_nhds (show ‖fderiv ℝ ρ p‖ < Lip by linarith)) + have h3 : ∀ᶠ y in 𝓝 p, (1 / 2 : ℝ) ≤ fderiv ℝ ρ y ν := by + have hc : ContinuousAt (fun y => fderiv ℝ ρ y ν) p := + (ContinuousLinearMap.apply ℝ ℝ ν).continuous.continuousAt.comp hcontp + exact hc.eventually (eventually_ge_nhds (show (1 / 2 : ℝ) < fderiv ℝ ρ p ν by + rw [hν]; norm_num)) + exact h1.and (h2.and h3) |>.mono fun y hy => ⟨hy.1, hy.2.1, hy.2.2⟩ + obtain ⟨δ₀, hδ₀, hball₀⟩ := Metric.mem_nhds_iff.mp hev + exact ⟨Lip, δ₀, hLip0, hδ₀, hball₀⟩ + +/-- Lower bound: distance to the complement is at least a multiple of `|ρ|`. -/ +theorem IsLocalDefiningFunction.mul_abs_le_infDist (hU : IsOpen U) (hp : p ∈ frontier U) + (h : IsLocalDefiningFunction U p ρ V) {Lip δ₀ : ℝ} (hLip0 : 0 < Lip) (hδ₀ : 0 < δ₀) + (hball₀ : ball p δ₀ ⊆ {y | y ∈ V ∧ ‖fderiv ℝ ρ y‖ ≤ Lip}) + {z : E} (hz : z ∈ ball p (δ₀ / 2)) (hzU : z ∈ U) + (hρsmall : |ρ z| < Lip * δ₀ / 2) : |ρ z| / Lip ≤ infDist z Uᶜ := by + have hUc : Uᶜ.Nonempty := ⟨p, hU.notMem_of_mem_frontier hp⟩ + have hdiff : ∀ y ∈ V, DifferentiableAt ℝ ρ y := fun y hy => + (h.contDiffOn.contDiffAt (h.isOpen.mem_nhds hy)).differentiableAt (by norm_num) + have hρz : ρ z < 0 := h.neg_of_mem (hball₀ (ball_subset_ball (half_le_self hδ₀.le) hz)).1 hzU + have hρabs : |ρ z| = -ρ z := abs_of_neg hρz + rw [le_infDist hUc] + intro y hy + by_cases hyV : y ∈ ball p δ₀ + · have hρy : 0 ≤ ρ y := by + by_contra hneg + push Not at hneg + exact hy (h.mem_of_neg (hball₀ hyV).1 hneg) + have hmv := Convex.norm_image_sub_le_of_norm_fderiv_le (f := ρ) (s := ball p δ₀) (C := Lip) + (fun x hx => hdiff x (hball₀ hx).1) (fun x hx => (hball₀ hx).2) (convex_ball p δ₀) + (ball_subset_ball (half_le_self hδ₀.le) hz) hyV + rw [Real.norm_eq_abs, ← dist_eq_norm, dist_comm] at hmv + have : |ρ z| ≤ |ρ y - ρ z| := by + rw [hρabs, abs_of_nonneg (by linarith)] + linarith + rw [div_le_iff₀ hLip0] + linarith + · have hdz : δ₀ / 2 ≤ dist z y := by + have h1 : δ₀ ≤ dist y p := not_lt.mp (by simpa [mem_ball] using hyV) + have h2 : dist z p < δ₀ / 2 := mem_ball.mp hz + have := dist_triangle y z p + rw [dist_comm y z] at this + linarith + have : |ρ z| / Lip ≤ δ₀ / 2 := by + rw [div_le_iff₀ hLip0] + linarith + exact this.trans hdz + +/-- Upper bound: walking inward along `ν` reaches the complement at distance `O(|ρ|)`. -/ +theorem IsLocalDefiningFunction.infDist_le_mul_abs (h : IsLocalDefiningFunction U p ρ V) + {ν : E} {Lip δ₀ : ℝ} (hδ₀ : 0 < δ₀) (hν0 : 0 < ‖ν‖) + (hball₀ : ball p δ₀ ⊆ + {y | y ∈ V ∧ ‖fderiv ℝ ρ y‖ ≤ Lip ∧ (1 / 2 : ℝ) ≤ fderiv ℝ ρ y ν}) + {z : E} (hz : z ∈ ball p (δ₀ / 2)) (hzU : z ∈ U) + (hρsmall : |ρ z| < δ₀ / (4 * ‖ν‖)) : infDist z Uᶜ ≤ 2 * ‖ν‖ * |ρ z| := by + have hdiff : ∀ y ∈ V, DifferentiableAt ℝ ρ y := fun y hy => + (h.contDiffOn.contDiffAt (h.isOpen.mem_nhds hy)).differentiableAt (by norm_num) + have hzV : z ∈ V := (hball₀ (ball_subset_ball (half_le_self hδ₀.le) hz)).1 + have hρz : ρ z < 0 := h.neg_of_mem hzV hzU + have hρabs : |ρ z| = -ρ z := abs_of_neg hρz + set T : ℝ := 2 * |ρ z| + have hT0 : 0 ≤ T := by positivity + have hseg : ∀ t ∈ Icc (0 : ℝ) T, z + t • ν ∈ ball p δ₀ := by + intro t ht + have h1 : ‖t • ν‖ ≤ T * ‖ν‖ := by + rw [norm_smul, Real.norm_eq_abs, abs_of_nonneg ht.1] + exact mul_le_mul_of_nonneg_right ht.2 (norm_nonneg _) + have h2 : T * ‖ν‖ < δ₀ / 2 := by + rw [lt_div_iff₀ (by positivity)] at hρsmall + nlinarith + rw [mem_ball, dist_eq_norm] + calc ‖z + t • ν - p‖ ≤ ‖z - p‖ + ‖t • ν‖ := by + rw [add_sub_right_comm]; exact norm_add_le _ _ + _ < δ₀ / 2 + δ₀ / 2 := by + have := mem_ball.mp hz + rw [dist_eq_norm] at this + linarith + _ = δ₀ := by ring + have hderiv : ∀ t ∈ Icc (0 : ℝ) T, HasDerivAt (fun t : ℝ => ρ (z + t • ν)) + (fderiv ℝ ρ (z + t • ν) ν) t := by + intro t ht + have hl : HasDerivAt (fun t : ℝ => z + t • ν) ν t := by + simpa using ((hasDerivAt_id t).smul_const ν).const_add z + exact (hdiff _ (hball₀ (hseg t ht)).1).hasFDerivAt.comp_hasDerivAt t hl + have hmono := Convex.mul_sub_le_image_sub_of_le_deriv (convex_Icc 0 T) + (f := fun t : ℝ => ρ (z + t • ν)) (C := 1 / 2) + (fun t ht => (hderiv t ht).continuousAt.continuousWithinAt) + (fun t ht => (hderiv t (interior_subset ht)).differentiableAt.differentiableWithinAt) + (fun t ht => by + rw [(hderiv t (interior_subset ht)).deriv] + exact (hball₀ (hseg t (interior_subset ht))).2.2) + 0 (left_mem_Icc.mpr hT0) T (right_mem_Icc.mpr hT0) hT0 + simp only [zero_smul, add_zero, sub_zero] at hmono + have hρT : 0 ≤ ρ (z + T • ν) := by + dsimp [T] at hmono ⊢ + rw [hρabs] at hmono ⊢ + linarith + have hnot : z + T • ν ∉ U := fun hmem => + absurd (h.neg_of_mem (hball₀ (hseg T (right_mem_Icc.mpr hT0))).1 hmem) (not_lt.mpr hρT) + calc infDist z Uᶜ ≤ dist z (z + T • ν) := infDist_le_dist_of_mem hnot + _ = T * ‖ν‖ := by + rw [dist_eq_norm, sub_add_cancel_left, norm_neg, norm_smul, Real.norm_eq_abs, + abs_of_nonneg hT0] + _ = 2 * ‖ν‖ * |ρ z| := by dsimp [T]; ring + +/-- Near a boundary point, a defining function is comparable to the distance to the complement: `c₂ +* |ρ z| ≤ infDist z Uᶜ ≤ C₁ * |ρ z|` for `z ∈ U` near `p`. -/ +theorem IsLocalDefiningFunction.exists_infDist_bounds (hU : IsOpen U) (hp : p ∈ frontier U) + (h : IsLocalDefiningFunction U p ρ V) : + ∃ C₁ c₂ δ : ℝ, 0 < C₁ ∧ 0 < c₂ ∧ 0 < δ ∧ ∀ z ∈ ball p δ, z ∈ U → + c₂ * |ρ z| ≤ infDist z Uᶜ ∧ infDist z Uᶜ ≤ C₁ * |ρ z| := by + obtain ⟨ν, hℓν, hν0⟩ := h.exists_inward_direction + obtain ⟨Lip, δ₀, hLip0, hδ₀, hball₀⟩ := h.exists_ball_fderiv_bound_and_inward hℓν + have hdiff : ∀ y ∈ V, DifferentiableAt ℝ ρ y := fun y hy => + (h.contDiffOn.contDiffAt (h.isOpen.mem_nhds hy)).differentiableAt (by norm_num) + have hρcont : ContinuousAt ρ p := (hdiff p h.mem).continuousAt + have hsmall : ∀ᶠ z in 𝓝 p, |ρ z| < min (Lip * δ₀ / 2) (δ₀ / (4 * ‖ν‖)) := by + have hcabs : ContinuousAt (fun z => |ρ z|) p := hρcont.abs + exact hcabs.eventually (eventually_lt_nhds (show |ρ p| < min (Lip * δ₀ / 2) (δ₀ / (4 * ‖ν‖)) by + rw [h.eq_zero, abs_zero]; exact lt_min (by positivity) (by positivity))) + obtain ⟨δ₁, hδ₁, hball₁⟩ := Metric.mem_nhds_iff.mp hsmall + refine ⟨2 * ‖ν‖, 1 / Lip, min (δ₀ / 2) δ₁, by positivity, by positivity, by positivity, ?_⟩ + intro z hz hzU + have hzδ₀ : z ∈ ball p (δ₀ / 2) := ball_subset_ball (min_le_left _ _) hz + have hρsmall : |ρ z| < min (Lip * δ₀ / 2) (δ₀ / (4 * ‖ν‖)) := + hball₁ (ball_subset_ball (min_le_right _ _) hz) + refine ⟨?_, ?_⟩ + · rw [div_mul_eq_mul_div, one_mul] + exact h.mul_abs_le_infDist hU hp hLip0 hδ₀ + (fun y hy => ⟨(hball₀ hy).1, (hball₀ hy).2.1⟩) hzδ₀ hzU (lt_min_iff.mp hρsmall).1 + · exact h.infDist_le_mul_abs hδ₀ hν0 hball₀ hzδ₀ hzU (lt_min_iff.mp hρsmall).2 + +/-- The complex quadratic coefficient of a real bilinear form along a complex line. -/ +@[expose] def leviQuadratic (B : E →L[ℝ] E →L[ℝ] ℝ) (w : E) : ℂ := + (((B w w - B (I • w) (I • w)) / 4 : ℝ) : ℂ) - I / 2 * (B w (I • w) : ℝ) + +/-- **Disc estimate along the Levi polynomial.** With `c` cancelling the complex quadratic +term and `ν` an inward direction, the defining function along the disc +`ζ ↦ p + ζ • w + ζ ^ 2 • c + (κ r ^ 2) • ν` is `-κ r ^ 2 + ‖ζ‖ ^ 2 L` up to `η r ^ 2`, for +`‖ζ‖ ≤ r` and `r` small, and the disc lies in any prescribed neighborhood of `p`. -/ +theorem IsLocalDefiningFunction.exists_disc_estimate (h : IsLocalDefiningFunction U p ρ V) + {w : E} (hw : IsComplexTangent ρ p w) {c ν : E} + (hc : complexPart (fderiv ℝ ρ p) c = -leviQuadratic (fderiv ℝ (fderiv ℝ ρ) p) w) + (hν : fderiv ℝ ρ p ν = -1) {κ η : ℝ} (hκ : 0 ≤ κ) (hη : 0 < η) {W : Set E} (hW : W ∈ 𝓝 p) : + ∃ r₀ > 0, ∀ r, 0 < r → r ≤ r₀ → ∀ ζ : ℂ, ‖ζ‖ ≤ r → + p + ζ • w + ζ ^ 2 • c + (κ * r ^ 2) • ν ∈ W ∧ + |ρ (p + ζ • w + ζ ^ 2 • c + (κ * r ^ 2) • ν) - (-(κ * r ^ 2) + ‖ζ‖ ^ 2 * leviForm ρ p w)| + ≤ η * r ^ 2 := by + set ℓ := fderiv ℝ ρ p with hℓ + set B := fderiv ℝ (fderiv ℝ ρ) p with hB + have hρp : ContDiffAt ℝ 2 ρ p := h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem) + -- symmetry of the second derivative + have hev : ∀ᶠ y in 𝓝 p, HasFDerivAt ρ (fderiv ℝ ρ y) y := by + filter_upwards [h.isOpen.mem_nhds h.mem] with y hy + exact ((h.contDiffOn.contDiffAt (h.isOpen.mem_nhds hy)).differentiableAt (by + norm_num)).hasFDerivAt + have hBd : HasFDerivAt (fderiv ℝ ρ) B p := + ((hρp.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hsymm : ∀ v v', B v v' = B v' v := second_derivative_symmetric_of_eventually hev hBd + -- constants + set M₀ : ℝ := ‖w‖ + ‖c‖ + κ * ‖ν‖ with hM₀ + have hM₀0 : 0 ≤ M₀ := by positivity + set M₁ : ℝ := ‖B‖ * ‖w‖ * (‖c‖ + κ * ‖ν‖) + ‖B‖ * (‖c‖ + κ * ‖ν‖) ^ 2 / 2 with hM₁ + have hM₁0 : 0 ≤ M₁ := by positivity + obtain ⟨δ', hδ', htaylor⟩ := exists_taylor_bound hρp (ε := η / (2 * (M₀ ^ 2 + 1))) (by positivity) + obtain ⟨δW, hδW, hballW⟩ := Metric.mem_nhds_iff.mp hW + set δt := min δ' δW + have hδt : 0 < δt := lt_min hδ' hδW + refine ⟨min 1 (min (η / (2 * (M₁ + 1))) (δt / (2 * (M₀ + 1)))), by positivity, + fun r hr hr₀ ζ hζ => ?_⟩ + obtain ⟨hr1, hrM₁, hrδt⟩ := le_one_and_mul_add_le_of_le_min hM₀0 hM₁0 hr hr₀ + have hrδ' : r * (M₀ + 1) < δ' := hrδt.trans_le (min_le_left _ _) + have hrδW : r * (M₀ + 1) < δW := hrδt.trans_le (min_le_right _ _) + -- the increment and its pieces + set h₁ : E := ζ • w with hh₁ + set h₂ : E := ζ ^ 2 • c + (κ * r ^ 2) • ν with hh₂ + have hsplit : p + ζ • w + ζ ^ 2 • c + (κ * r ^ 2) • ν = p + (h₁ + h₂) := by + rw [hh₁, hh₂]; abel + have hζr2 : ‖ζ‖ ^ 2 ≤ r ^ 2 := by gcongr + have hn₁ : ‖h₁‖ ≤ r * ‖w‖ := by + rw [hh₁, norm_smul] + exact mul_le_mul_of_nonneg_right hζ (norm_nonneg _) + have hn₂ : ‖h₂‖ ≤ r ^ 2 * (‖c‖ + κ * ‖ν‖) := by + rw [hh₂] + calc ‖ζ ^ 2 • c + (κ * r ^ 2) • ν‖ ≤ ‖ζ ^ 2 • c‖ + ‖(κ * r ^ 2) • ν‖ := norm_add_le _ _ + _ = ‖ζ‖ ^ 2 * ‖c‖ + κ * r ^ 2 * ‖ν‖ := by + rw [norm_smul, norm_smul, norm_pow, Real.norm_eq_abs, abs_of_nonneg (by positivity)] + _ ≤ r ^ 2 * ‖c‖ + κ * r ^ 2 * ‖ν‖ := by gcongr + _ = r ^ 2 * (‖c‖ + κ * ‖ν‖) := by ring + have hn₂' : ‖h₂‖ ≤ r * (‖c‖ + κ * ‖ν‖) := by + refine hn₂.trans ?_ + have : r ^ 2 ≤ r := by nlinarith + exact mul_le_mul_of_nonneg_right this (by positivity) + have hn : ‖h₁ + h₂‖ ≤ r * M₀ := by + calc ‖h₁ + h₂‖ ≤ ‖h₁‖ + ‖h₂‖ := norm_add_le _ _ + _ ≤ r * ‖w‖ + r * (‖c‖ + κ * ‖ν‖) := add_le_add hn₁ hn₂' + _ = r * M₀ := by rw [hM₀]; ring + have hnlt : ‖h₁ + h₂‖ < δ' := hn.trans_lt (by nlinarith) + constructor + · rw [hsplit] + apply hballW + rw [mem_ball, dist_eq_norm, add_sub_cancel_left] + exact hn.trans_lt (by nlinarith) + -- the Taylor expansion + have ht := htaylor (h₁ + h₂) hnlt + -- linear term + have hℓw : complexPart ℓ w = 0 := by + have h1 : ℓ w = 0 := hw.1 + have h2 : ℓ (I • w) = 0 := hw.2 + simp [complexPart_apply, h1, h2] + have hlin : ℓ (h₁ + h₂) = (ζ ^ 2 * (-leviQuadratic B w)).re - κ * r ^ 2 := by + rw [hh₁, hh₂, map_add, map_add, apply_smul_eq_re_mul_complexPart ℓ ζ w, + apply_smul_eq_re_mul_complexPart ℓ (ζ ^ 2) c, hℓw, hc, map_smul, smul_eq_mul, hν] + simp + ring + -- quadratic term + have hquad : (1 / 2 : ℝ) * B (h₁ + h₂) (h₁ + h₂) = + (1 / 2 : ℝ) * B h₁ h₁ + B h₁ h₂ + (1 / 2 : ℝ) * B h₂ h₂ := by + simp only [map_add, add_apply, hsymm h₂ h₁] + ring + have hquad₁ : (1 / 2 : ℝ) * B h₁ h₁ = ‖ζ‖ ^ 2 * leviForm ρ p w + (ζ ^ 2 * leviQuadratic B w).re + := by + rw [hh₁, bilinear_smul_smul_eq B (hsymm w (I • w)) ζ, leviForm_eq_fderiv, leviQuadratic] + -- cancellation of the complex quadratic terms + have hcancel : (ζ ^ 2 * (-leviQuadratic B w)).re + (ζ ^ 2 * leviQuadratic B w).re = 0 := by + rw [mul_neg, Complex.neg_re]; ring + -- error bounds + have hBn : 0 ≤ ‖B‖ := ContinuousLinearMap.opNorm_nonneg B + have hB₁₂ : |B h₁ h₂| ≤ ‖B‖ * ‖w‖ * (‖c‖ + κ * ‖ν‖) * r ^ 3 := by + have := B.le_opNorm₂ h₁ h₂ + rw [Real.norm_eq_abs] at this + refine this.trans ?_ + calc ‖B‖ * ‖h₁‖ * ‖h₂‖ ≤ ‖B‖ * (r * ‖w‖) * (r ^ 2 * (‖c‖ + κ * ‖ν‖)) := + mul_le_mul (mul_le_mul_of_nonneg_left hn₁ hBn) hn₂ (norm_nonneg _) (by positivity) + _ = ‖B‖ * ‖w‖ * (‖c‖ + κ * ‖ν‖) * r ^ 3 := by ring + have hB₂₂ : |(1 / 2 : ℝ) * B h₂ h₂| ≤ ‖B‖ * (‖c‖ + κ * ‖ν‖) ^ 2 / 2 * r ^ 3 := by + rw [abs_mul, abs_of_pos (by norm_num : (0:ℝ) < 1 / 2)] + have := B.le_opNorm₂ h₂ h₂ + rw [Real.norm_eq_abs] at this + have h2 : ‖B‖ * ‖h₂‖ * ‖h₂‖ ≤ ‖B‖ * (r * (‖c‖ + κ * ‖ν‖)) * (r ^ 2 * (‖c‖ + κ * ‖ν‖)) := + mul_le_mul (mul_le_mul_of_nonneg_left hn₂' hBn) hn₂ (norm_nonneg _) (by positivity) + calc 1 / 2 * |B h₂ h₂| ≤ 1 / 2 * (‖B‖ * (r * (‖c‖ + κ * ‖ν‖)) * (r ^ 2 * (‖c‖ + κ * ‖ν‖))) := + mul_le_mul_of_nonneg_left (this.trans h2) (by norm_num) + _ = ‖B‖ * (‖c‖ + κ * ‖ν‖) ^ 2 / 2 * r ^ 3 := by ring + have hR : |ρ (p + (h₁ + h₂)) - ρ p - ℓ (h₁ + h₂) - (1 / 2 : ℝ) * B (h₁ + h₂) (h₁ + h₂)| + ≤ η / (2 * (M₀ ^ 2 + 1)) * (r * M₀) ^ 2 := + ht.trans (mul_le_mul_of_nonneg_left (pow_le_pow_left₀ (norm_nonneg _) hn 2) (by positivity)) + have hcub : |B h₁ h₂ + (1 / 2 : ℝ) * B h₂ h₂| ≤ M₁ * r ^ 3 := + (abs_add_le _ _).trans (by rw [hM₁, add_mul]; exact add_le_add hB₁₂ hB₂₂) + rw [hsplit] + have hkey : ρ (p + (h₁ + h₂)) - (-(κ * r ^ 2) + ‖ζ‖ ^ 2 * leviForm ρ p w) = + (ρ (p + (h₁ + h₂)) - ρ p - ℓ (h₁ + h₂) - (1 / 2 : ℝ) * B (h₁ + h₂) (h₁ + h₂)) + + (B h₁ h₂ + (1 / 2 : ℝ) * B h₂ h₂) := by + rw [h.eq_zero, hlin, hquad, hquad₁] + linarith [hcancel] + rw [hkey] + exact taylor_remainder_add_cubic_le hr hη hrM₁ hR hcub + +variable {n : ℕ} + +/-- The Levi polynomial disc of small radius lies in `U` when the Levi form is negative. -/ +theorem IsLocalDefiningFunction.disc_subset_of_estimate {U : Set (Fin n → ℂ)} + {p : Fin n → ℂ} {ρ : (Fin n → ℂ) → ℝ} {V : Set (Fin n → ℂ)} + (h : IsLocalDefiningFunction U p ρ V) {φ : ℂ → Fin n → ℂ} {r κ η L : ℝ} + (hr : 0 < r) (hκ : 0 < κ) (hL : L < 0) (hηκ : η ≤ κ / 2) + (hest : ∀ ζ, ‖ζ‖ ≤ r → φ ζ ∈ V ∧ + |ρ (φ ζ) - (-(κ * r ^ 2) + ‖ζ‖ ^ 2 * L)| ≤ η * r ^ 2) : + ∀ ζ ∈ closedBall (0 : ℂ) r, φ ζ ∈ U := by + intro ζ hζ + obtain ⟨hmem, hρ⟩ := hest ζ (mem_closedBall_zero_iff.mp hζ) + apply h.mem_of_neg hmem + have h1 := (abs_le.mp hρ).2 + have h2 : ‖ζ‖ ^ 2 * L ≤ 0 := mul_nonpos_of_nonneg_of_nonpos (by positivity) hL.le + have h3 : η * r ^ 2 ≤ κ / 2 * r ^ 2 := mul_le_mul_of_nonneg_right hηκ (by positivity) + have h4 : 0 < κ / 2 * r ^ 2 := by positivity + linarith + +/-- **Levi's theorem in coordinates.** A domain of holomorphy in `Fin n → ℂ` is Levi +pseudoconvex: the Levi form of every local defining function is positive semidefinite on the +complex tangent space at every boundary point. The coordinate-free version is +`IsDomainOfHolomorphy.isLeviPseudoconvex`. -/ +theorem IsDomainOfHolomorphy.isLeviPseudoconvex_fin {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : IsLeviPseudoconvex U := by + intro p hp ρ V h w hw + by_contra hneg + push Not at hneg + set L := leviForm ρ p w + set ℓ := fderiv ℝ ρ p + set B := fderiv ℝ (fderiv ℝ ρ) p + obtain ⟨c, hc⟩ := exists_complexPart_eq h.fderiv_ne (-leviQuadratic B w) + obtain ⟨ν0, hν0, _⟩ := ContinuousLinearMap.exists_apply_eq_one_of_ne_zero h.fderiv_ne + set ν : Fin n → ℂ := -ν0 + have hℓν : ℓ ν = -1 := by rw [map_neg, hν0] + obtain ⟨C₁, c₂, δ, hC₁, hc₂, hδ, hdist⟩ := h.exists_infDist_bounds ho hp + set κ : ℝ := c₂ * (-L) / (8 * C₁) with hκ + have hκ0 : 0 < κ := by + rw [hκ] + have : 0 < -L := by linarith + positivity + set η : ℝ := min (κ / 2) (-L / 2) with hη + have hη0 : 0 < η := lt_min (by positivity) (by linarith) + have hηκ : η ≤ κ / 2 := min_le_left _ _ + have hηL : η ≤ -L / 2 := min_le_right _ _ + obtain ⟨r, hr, hest⟩ := h.exists_disc_estimate hw hc hℓν hκ0.le hη0 + (W := V ∩ ball p δ) (inter_mem (h.isOpen.mem_nhds h.mem) (ball_mem_nhds p hδ)) + set φ : ℂ → Fin n → ℂ := fun ζ => p + ζ • w + ζ ^ 2 • c + (κ * r ^ 2) • ν with hφ + have hφan : AnalyticOnNhd ℂ φ (closedBall 0 r) := fun ζ _ => + ((analyticAt_const.add (analyticAt_id.smul analyticAt_const)).add + ((analyticAt_id.pow 2).smul analyticAt_const)).add analyticAt_const + have hest' : ∀ ζ : ℂ, ‖ζ‖ ≤ r → φ ζ ∈ V ∩ ball p δ ∧ + |ρ (φ ζ) - (-(κ * r ^ 2) + ‖ζ‖ ^ 2 * L)| ≤ η * r ^ 2 := hest r hr le_rfl + have hdiscU : ∀ ζ ∈ closedBall (0 : ℂ) r, φ ζ ∈ U := + h.disc_subset_of_estimate hr hκ0 hneg hηκ fun ζ hζ => + ⟨(hest' ζ hζ).1.1, (hest' ζ hζ).2⟩ + -- the boundary circle is deep inside + set m : ℝ := c₂ * (-L) / 2 * r ^ 2 with hm + have hm0 : 0 < m := by + have : 0 < -L := by linarith + positivity + have hcircle : ∀ ζ ∈ sphere (0 : ℂ) r, m ≤ infDist (φ ζ) Uᶜ := by + intro ζ hζ + have hζ' : ‖ζ‖ = r := mem_sphere_zero_iff_norm.mp hζ + obtain ⟨hmem, hρ⟩ := hest' ζ hζ'.le + have hin := hdiscU ζ (sphere_subset_closedBall hζ) + have hlow := (hdist (φ ζ) hmem.2 hin).1 + have h1 := (abs_le.mp hρ).2 + rw [hζ'] at h1 + have hρneg : ρ (φ ζ) ≤ L / 2 * r ^ 2 := by + have h3 : η * r ^ 2 ≤ -L / 2 * r ^ 2 := mul_le_mul_of_nonneg_right hηL (by positivity) + have h4 : 0 ≤ κ * r ^ 2 := by positivity + linarith + have habs : -L / 2 * r ^ 2 ≤ |ρ (φ ζ)| := by + rw [abs_of_nonpos (by nlinarith [pow_pos hr 2])] + linarith + calc m = c₂ * (-L / 2 * r ^ 2) := by rw [hm]; ring + _ ≤ c₂ * |ρ (φ ζ)| := mul_le_mul_of_nonneg_left habs hc₂.le + _ ≤ infDist (φ ζ) Uᶜ := hlow + -- the center is shallow + have hcenter : infDist (φ 0) Uᶜ ≤ C₁ * (2 * κ * r ^ 2) := by + obtain ⟨hmem, hρ⟩ := hest' 0 (by simp [hr.le]) + have hin := hdiscU 0 (mem_closedBall_self hr.le) + have hup := (hdist (φ 0) hmem.2 hin).2 + have habs : |ρ (φ 0)| ≤ 2 * κ * r ^ 2 := by + have h0 : ‖(0 : ℂ)‖ ^ 2 * L = 0 := by simp + rw [h0, add_zero, sub_neg_eq_add] at hρ + have h3 : η * r ^ 2 ≤ κ / 2 * r ^ 2 := mul_le_mul_of_nonneg_right hηκ (by positivity) + have hκr : 0 ≤ κ * r ^ 2 := by positivity + have := abs_le.mp hρ + rw [abs_le] + constructor <;> linarith + exact hup.trans (mul_le_mul_of_nonneg_left habs hC₁.le) + -- Thullen's radius bound + have hhull := mem_holomorphicHull_of_analytic_disc hr hφan hdiscU (mem_closedBall_self hr.le) + have hK : IsCompact (φ '' sphere 0 r) := + (isCompact_sphere (0 : ℂ) r).image_of_continuousOn + (hφan.continuousOn.mono sphere_subset_closedBall) + have hKU : φ '' sphere 0 r ⊆ U := by + rintro _ ⟨ζ, hζ, rfl⟩ + exact hdiscU ζ (sphere_subset_closedBall hζ) + have hrad := hU.holomorphic_radius_bound ho hK hKU (q := fun _ => (m : ℂ)) analyticOnNhd_const + (fun z hz => by + obtain ⟨ζ, hζ, rfl⟩ := hz + have : ‖(m : ℂ)‖ = m := by rw [Complex.norm_real, Real.norm_eq_abs, abs_of_pos hm0] + rw [this] + exact (ball_subset_ball (hcircle ζ hζ)).trans + (by simpa using ball_infDist_subset_compl (x := φ ζ) (s := Uᶜ))) + (φ 0) hhull + have hm' : ‖(m : ℂ)‖ = m := by rw [Complex.norm_real, Real.norm_eq_abs, abs_of_pos hm0] + rw [hm'] at hrad + have hUc : Uᶜ.Nonempty := ⟨p, ho.notMem_of_mem_frontier hp⟩ + have hmle : m ≤ infDist (φ 0) Uᶜ := by + by_contra hlt + push Not at hlt + obtain ⟨y, hy, hdy⟩ := (infDist_lt_iff hUc).mp hlt + exact hy (hrad (by rwa [mem_ball, dist_comm])) + have hfinal : m ≤ C₁ * (2 * κ * r ^ 2) := hmle.trans hcenter + rw [hm, hκ] at hfinal + have hC₁' : C₁ * (2 * (c₂ * (-L) / (8 * C₁)) * r ^ 2) = c₂ * (-L) / 4 * r ^ 2 := by + field_simp + ring + rw [hC₁'] at hfinal + have : 0 < c₂ * (-L) / 4 * r ^ 2 := by + have : 0 < -L := by linarith + positivity + linarith + +section Transport + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Levi pseudoconvexity pulls back along a continuous linear equivalence. -/ +theorem IsLeviPseudoconvex.of_image_equiv {U : Set E} (L : E ≃L[ℂ] F) + (h : IsLeviPseudoconvex (L '' U)) : IsLeviPseudoconvex U := by + intro p hp ρ V hρ + have hfr : L p ∈ frontier (L '' U) := by + have hfr' := L.toHomeomorph.image_frontier U + rw [ContinuousLinearEquiv.coe_toHomeomorph] at hfr' + rw [← hfr'] + exact mem_image_of_mem _ hp + have himg : L.symm ⁻¹' U = L '' U := by + ext z + constructor + · intro hz + exact ⟨L.symm z, hz, L.apply_symm_apply z⟩ + · rintro ⟨x, hx, rfl⟩ + simpa using hx + have hdef : IsLocalDefiningFunction (L '' U) (L p) (ρ ∘ L.symm) (univ ∩ L.symm ⁻¹' V) := by + rw [← himg] + exact hρ.comp_analytic isOpen_univ (mem_univ _) (L.symm.toContinuousLinearMap.analyticOnNhd _) + (L.symm_apply_apply p) (by rw [L.symm.fderiv]; exact L.symm.surjective) + have hcond := h (L p) hfr (ρ ∘ L.symm) _ hdef + exact (leviCondition_comp_iff hρ (L.symm.toContinuousLinearMap.analyticOnNhd univ _ (mem_univ _)) + (L.symm_apply_apply p) L.symm L.symm.hasFDerivAt).mp hcond + +/-- **Levi's theorem.** A domain of holomorphy in a finite-dimensional complex normed space is +Levi pseudoconvex: the Levi form of every local defining function is positive semidefinite on +the complex tangent space at every boundary point. -/ +theorem IsDomainOfHolomorphy.isLeviPseudoconvex [FiniteDimensional ℂ E] {U : Set E} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : IsLeviPseudoconvex U := by + let L := (Module.finBasis ℂ E).equivFunL + exact IsLeviPseudoconvex.of_image_equiv L + ((hU.image_equiv L).isLeviPseudoconvex_fin (L.isOpenMap U ho)) + +end Transport + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean new file mode 100644 index 0000000000..67035bec0c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean @@ -0,0 +1,498 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.FDeriv.Bilinear +public import Mathlib.Analysis.Calculus.FDeriv.Pow +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity + +/-! +# Peak functions at strictly Levi convex boundary points + +A boundary point `p` of an open set `U` is strictly Levi pseudoconvex if the Levi form of a +local defining function is positive definite on the complex tangent space. Adding a multiple of +the square of the defining function makes the Levi form positive definite on the whole space at +`p`, by a compactness argument on the unit sphere. The Levi polynomial of the modified defining +function `\tilde ρ` is the holomorphic quadratic function `F(z) = ∂\tilde ρ(p)(z - p) + Q(z - +p)`, where `Q` is the complex quadratic part of the real Hessian; the second-order Taylor +expansion gives `Re F(z) = \tilde ρ(z) - Lev \tilde ρ(p, z - p) + o(‖z - p‖²)`, so `Re F < 0` on +the domain near `p`, except at `p` where `F` vanishes. The reciprocal `1 / F` is then +holomorphic on the domain near `p` and unbounded at `p`: a local holomorphic blow-up function. +Exponentiating `F` gives a normalized local peak function with value one at `p` and modulus less +than one elsewhere on the closed side. + +References: [Range][Range1986] (1986), Chapter II, Lemma 2.13, Proposition 2.16 and Theorem +2.15; [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 4. + +## Main definitions + +* `IsStrictlyLeviPseudoconvexAt`: The strict Levi condition at a boundary point: the Levi form of + every local defining function is positive definite on the complex tangent space. +* `leviBilinear`: The complex bilinear part of a real bilinear form on a complex space. + +## Main results + +* `exists_leviForm_add_normSq_ge`: **Positive definiteness after modification.** If the Levi form is + positive definite on the complex tangent space at `p`, then adding a large multiple of the squared + modulus of the complex-linear part of the derivative makes it positive definite on the whole + space. +* `IsLocalDefiningFunction.exists_holomorphic_support`: **Levi polynomial as a peak function + ([Range][Range1986], Proposition 2.16).** At a boundary point with positive definite Levi form on + the complex tangent space there is an entire holomorphic function `F` vanishing at `p` whose real + part is negative at all nearby points where the defining function is nonpositive, except at `p`. +* `IsLocalDefiningFunction.exists_peak`: **Normalized local peak function.** Exponentiating a + holomorphic supporting function has value one at the boundary point and modulus strictly less than + one at every other nearby point on the closed side of the defining function. +* `IsLocalDefiningFunction.exists_tendsto_norm_atTop`: **Local holomorphic blow-up.** At a strictly + Levi convex boundary point of an open set there is a holomorphic function on the set near the + point whose modulus tends to infinity at the point. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +section StrictDefinition + +/-- The strict Levi condition at a boundary point: the Levi form of every local defining function is +positive definite on the complex tangent space. -/ +@[expose] def IsStrictlyLeviPseudoconvexAt (U : Set E) (p : E) : Prop := + ∀ (ρ : E → ℝ) (V : Set E), IsLocalDefiningFunction U p ρ V → + ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w + +/-- The strict Levi condition can be checked on one defining function. -/ +theorem isStrictlyLeviPseudoconvexAt_iff_of_defining {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + (h : IsLocalDefiningFunction U p ρ V) : + IsStrictlyLeviPseudoconvexAt U p ↔ ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w := + by + constructor + · intro hL w hw hw0 + exact hL ρ V h w hw hw0 + · intro hL ρ' V' h' w hw hw0 + obtain ⟨c, hc, hlev⟩ := h'.exists_leviForm_eq h + have hw' : IsComplexTangent ρ p w := (h'.isComplexTangent_iff h w).mp hw + rw [hlev w hw'] + exact mul_pos hc (hL w hw' hw0) + +end StrictDefinition + +section Bilinear + +/-- The complex bilinear part of a real bilinear form on a complex space. -/ +def leviBilinear (B : E →L[ℝ] E →L[ℝ] ℝ) (q : E × E) : ℂ := + (((B q.1 q.2 - B (I • q.1) (I • q.2)) / 4 : ℝ) : ℂ) - + I / 4 * (((B q.1 (I • q.2) + B (I • q.1) q.2) : ℝ) : ℂ) + +/-- Multiplying the first argument by `I` multiplies the complex bilinear part by `I`. -/ +theorem leviBilinear_I_smul_left (B : E →L[ℝ] E →L[ℝ] ℝ) (k k' : E) : + leviBilinear B (I • k, k') = I * leviBilinear B (k, k') := by + simp only [leviBilinear, smul_smul, Complex.I_mul_I, neg_one_smul, map_neg, + neg_apply] + apply Complex.ext <;> simp <;> ring + +/-- Multiplying the second argument by `I` multiplies the complex bilinear part by `I`. -/ +theorem leviBilinear_I_smul_right (B : E →L[ℝ] E →L[ℝ] ℝ) (k k' : E) : + leviBilinear B (k, I • k') = I * leviBilinear B (k, k') := by + simp only [leviBilinear, smul_smul, Complex.I_mul_I, neg_one_smul, map_neg] + apply Complex.ext <;> simp <;> ring + +/-- The complex bilinear part is a bounded complex bilinear map. -/ +theorem isBoundedBilinearMap_leviBilinear (B : E →L[ℝ] E →L[ℝ] ℝ) : + IsBoundedBilinearMap ℂ (leviBilinear B) := by + have hre : ∀ (r : ℝ) (k k' : E), leviBilinear B (r • k, k') = (r : ℂ) * leviBilinear B (k, k') + := by + intro r k k' + have h1 : I • r • k = r • I • k := smul_comm I r k + simp only [leviBilinear, h1, map_smul] + apply Complex.ext <;> simp <;> ring + have hre' : ∀ (r : ℝ) (k k' : E), leviBilinear B (k, r • k') = (r : ℂ) * leviBilinear B (k, k') + := by + intro r k k' + have h1 : I • r • k' = r • I • k' := smul_comm I r k' + simp only [leviBilinear, h1, map_smul] + apply Complex.ext <;> simp <;> ring + refine ⟨fun k₁ k₂ k' => ?_, fun c k k' => ?_, fun k k₁' k₂' => ?_, fun c k k' => ?_, ?_⟩ + · simp only [leviBilinear, smul_add, map_add] + apply Complex.ext <;> simp <;> ring + · rw [Complex.smul_eq_re_smul_add_im_smul c k] + have h1 : leviBilinear B (c.re • k + c.im • I • k, k') = + leviBilinear B (c.re • k, k') + leviBilinear B (c.im • I • k, k') := by + simp only [leviBilinear, smul_add, map_add] + apply Complex.ext <;> simp <;> ring + rw [h1, hre, hre, leviBilinear_I_smul_left, smul_eq_mul] + conv_rhs => rw [← Complex.re_add_im c] + ring + · simp only [leviBilinear, smul_add, map_add] + apply Complex.ext <;> simp <;> ring + · rw [Complex.smul_eq_re_smul_add_im_smul c k'] + have h1 : leviBilinear B (k, c.re • k' + c.im • I • k') = + leviBilinear B (k, c.re • k') + leviBilinear B (k, c.im • I • k') := by + simp only [leviBilinear, smul_add, map_add] + apply Complex.ext <;> simp <;> ring + rw [h1, hre', hre', leviBilinear_I_smul_right, smul_eq_mul] + conv_rhs => rw [← Complex.re_add_im c] + ring + · refine ⟨‖B‖ + 1, by positivity, fun k k' => ?_⟩ + have hB : ∀ x y : E, |B x y| ≤ ‖B‖ * ‖x‖ * ‖y‖ := fun x y => by + have := B.le_opNorm₂ x y + rwa [Real.norm_eq_abs] at this + have hI : ∀ x : E, ‖I • x‖ = ‖x‖ := fun x => by rw [norm_smul, Complex.norm_I, one_mul] + have h1 : |B k k' - B (I • k) (I • k')| ≤ 2 * (‖B‖ * ‖k‖ * ‖k'‖) := by + calc |B k k' - B (I • k) (I • k')| ≤ |B k k'| + |B (I • k) (I • k')| := abs_sub _ _ + _ ≤ ‖B‖ * ‖k‖ * ‖k'‖ + ‖B‖ * ‖I • k‖ * ‖I • k'‖ := add_le_add (hB _ _) (hB _ _) + _ = 2 * (‖B‖ * ‖k‖ * ‖k'‖) := by rw [hI, hI]; ring + have h2 : |B k (I • k') + B (I • k) k'| ≤ 2 * (‖B‖ * ‖k‖ * ‖k'‖) := by + calc |B k (I • k') + B (I • k) k'| ≤ |B k (I • k')| + |B (I • k) k'| := abs_add_le _ _ + _ ≤ ‖B‖ * ‖k‖ * ‖I • k'‖ + ‖B‖ * ‖I • k‖ * ‖k'‖ := add_le_add (hB _ _) (hB _ _) + _ = 2 * (‖B‖ * ‖k‖ * ‖k'‖) := by rw [hI, hI]; ring + have hnn : 0 ≤ ‖B‖ * ‖k‖ * ‖k'‖ := by positivity + calc ‖leviBilinear B (k, k')‖ + ≤ ‖(((B k k' - B (I • k) (I • k')) / 4 : ℝ) : ℂ)‖ + + ‖I / 4 * (((B k (I • k') + B (I • k) k') : ℝ) : ℂ)‖ := norm_sub_le _ _ + _ = |B k k' - B (I • k) (I • k')| / 4 + |B k (I • k') + B (I • k) k'| / 4 := by + rw [Complex.norm_real, Real.norm_eq_abs, abs_div, abs_of_pos (by norm_num : (0:ℝ) < 4), + norm_mul, norm_div, Complex.norm_I, Complex.norm_real, Real.norm_eq_abs] + norm_num + ring + _ ≤ 2 * (‖B‖ * ‖k‖ * ‖k'‖) / 4 + 2 * (‖B‖ * ‖k‖ * ‖k'‖) / 4 := by gcongr + _ = ‖B‖ * ‖k‖ * ‖k'‖ := by ring + _ ≤ (‖B‖ + 1) * ‖k‖ * ‖k'‖ := by gcongr; linarith + +/-- On the diagonal, the complex bilinear part of a symmetric form is the complex quadratic +coefficient of `LeviConvexity.Necessity`. -/ +theorem leviBilinear_self (B : E →L[ℝ] E →L[ℝ] ℝ) {k : E} (hsymm : B k (I • k) = B (I • k) k) : + leviBilinear B (k, k) = leviQuadratic B k := by + simp only [leviBilinear, leviQuadratic, hsymm] + apply Complex.ext + · simp + · simp + ring + +end Bilinear + +section Modification + +variable {ρ : E → ℝ} {p : E} + +/-- The Levi form of `ρ + A ρ ^ 2` at a zero of `ρ` adds `A / 2` times the squared modulus of the +complex-linear part of the derivative. -/ +theorem leviForm_add_mul_sq (hρ : ContDiffAt ℝ 2 ρ p) (hρ0 : ρ p = 0) (A : ℝ) (w : E) : + leviForm (fun z => ρ z + A * ρ z ^ 2) p w = + leviForm ρ p w + A / 2 * ‖complexPart (fderiv ℝ ρ p) w‖ ^ 2 := by + have hev : ∀ᶠ y in 𝓝 p, HasFDerivAt ρ (fderiv ℝ ρ y) y := by + filter_upwards [hρ.eventually (by simp)] with y hy + exact (hy.differentiableAt (by norm_num)).hasFDerivAt + have hD2 : HasFDerivAt (fderiv ℝ ρ) (fderiv ℝ (fderiv ℝ ρ) p) p := + ((hρ.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + -- first derivative of the modified function + have hD1 : (fun y => fderiv ℝ (fun z => ρ z + A * ρ z ^ 2) y) =ᶠ[𝓝 p] + fun y => fderiv ℝ ρ y + (A * (2 * ρ y)) • fderiv ℝ ρ y := by + filter_upwards [hev] with y hy + have h := hy.add ((hy.pow 2).const_mul A) + refine h.fderiv.trans ?_ + ext v + simp + ring + -- second derivative at `p` + have hℓ : HasFDerivAt ρ (fderiv ℝ ρ p) p := (hρ.differentiableAt (by norm_num)).hasFDerivAt + have hc : HasFDerivAt (fun y => A * (2 * ρ y)) ((A * 2) • fderiv ℝ ρ p) p := by + have h := (hℓ.const_mul (2 : ℝ)).const_mul A + convert h using 1 + ext v + simp + ring + have hsm := hc.smul hD2 + have hsum : HasFDerivAt (fun y => fderiv ℝ ρ y + (A * (2 * ρ y)) • fderiv ℝ ρ y) _ p := + hD2.add hsm + rw [leviForm_eq_fderiv, leviForm_eq_fderiv, hD1.fderiv_eq, hsum.fderiv] + have hn : ‖complexPart (fderiv ℝ ρ p) w‖ ^ 2 = + fderiv ℝ ρ p w ^ 2 + fderiv ℝ ρ p (I • w) ^ 2 := by + rw [Complex.sq_norm, Complex.normSq_apply] + simp [complexPart_apply] + ring + rw [hn] + simp [hρ0, add_apply, smul_apply, smul_eq_mul] + ring + +end Modification + +section Compactness + +variable {ρ : E → ℝ} {p : E} + +/-- The Levi form is homogeneous of degree two under real scaling. -/ +theorem leviForm_smul_real (f : E → ℝ) (p : E) (t : ℝ) (w : E) : + leviForm f p (t • w) = t ^ 2 * leviForm f p w := by + have h1 : I • t • w = t • I • w := smul_comm I t w + simp only [leviForm_eq_fderiv, h1, map_smul, smul_apply, smul_eq_mul] + ring + +/-- The Levi form is continuous in the direction. -/ +theorem continuous_leviForm (f : E → ℝ) (p : E) : Continuous fun w => leviForm f p w := by + simp only [leviForm_eq_fderiv] + have hB := (fderiv ℝ (fderiv ℝ f) p).isBoundedBilinearMap.continuous + fun_prop + +/-- Real scaling of the complex-linear part. -/ +theorem complexPart_real_smul (ℓ : E →L[ℝ] ℝ) (r : ℝ) (w : E) : + complexPart ℓ (r • w) = (r : ℂ) * complexPart ℓ w := by + rw [← Complex.coe_smul, map_smul, smul_eq_mul] + +/-- A vector is complex tangent exactly when the complex-linear part of the derivative vanishes on +it. -/ +theorem isComplexTangent_iff_complexPart_eq_zero (w : E) : + IsComplexTangent ρ p w ↔ complexPart (fderiv ℝ ρ p) w = 0 := by + simp only [IsComplexTangent, complexPart_apply, Complex.ext_iff] + simp + +/-- **Positive definiteness after modification.** If the Levi form is positive definite on +the complex tangent space at `p`, then adding a large multiple of the squared modulus of the +complex-linear part of the derivative makes it positive definite on the whole space. -/ +theorem exists_leviForm_add_normSq_ge [FiniteDimensional ℂ E] + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ A : ℝ, 0 ≤ A ∧ ∃ c : ℝ, 0 < c ∧ ∀ w, + c * ‖w‖ ^ 2 ≤ leviForm ρ p w + A / 2 * ‖complexPart (fderiv ℝ ρ p) w‖ ^ 2 := by + set ℓ := fderiv ℝ ρ p with hℓ + by_contra hcon + push Not at hcon + -- a sequence of bad unit vectors + have hbad : ∀ n : ℕ, ∃ u : E, ‖u‖ = 1 ∧ + leviForm ρ p u + (n : ℝ) / 2 * ‖complexPart ℓ u‖ ^ 2 < 1 / ((n : ℝ) + 1) := by + intro n + obtain ⟨w, hw⟩ := hcon n (Nat.cast_nonneg n) (1 / ((n : ℝ) + 1)) (by positivity) + have hw0 : w ≠ 0 := by + rintro rfl + have h0 : leviForm ρ p 0 = 0 := by simp [leviForm_eq_fderiv] + have h1 : complexPart ℓ 0 = 0 := by simp [complexPart_apply] + rw [h0, h1] at hw + simp at hw + have hn0 : 0 < ‖w‖ := norm_pos_iff.mpr hw0 + refine ⟨‖w‖⁻¹ • w, by rw [norm_smul, norm_inv, norm_norm, inv_mul_cancel₀ hn0.ne'], ?_⟩ + rw [leviForm_smul_real, complexPart_real_smul, norm_mul, Complex.norm_real, norm_inv, norm_norm, + mul_pow] + have h2 : 0 < ‖w‖ ^ 2 := by positivity + have hinv : (‖w‖⁻¹) ^ 2 = (‖w‖ ^ 2)⁻¹ := by rw [inv_pow] + rw [hinv] + rw [← sub_pos] at hw ⊢ + have : (‖w‖ ^ 2)⁻¹ * (1 / ((n : ℝ) + 1) * ‖w‖ ^ 2 - + (leviForm ρ p w + (n : ℝ) / 2 * ‖complexPart ℓ w‖ ^ 2)) > 0 := by positivity + convert this using 1 + field_simp + choose u hu using hbad + have huS : ∀ n, u n ∈ sphere (0 : E) 1 := fun n => by simpa using (hu n).1 + -- bound on the Levi form over the unit sphere + obtain ⟨M, hM⟩ := (isCompact_sphere (0 : E) 1).exists_bound_of_continuousOn + (continuous_leviForm ρ p).continuousOn + have hM' : ∀ n, -M ≤ leviForm ρ p (u n) := fun n => by + have := hM _ (huS n) + rw [Real.norm_eq_abs] at this + linarith [neg_abs_le (leviForm ρ p (u n))] + -- the complex parts tend to zero + have hpart : ∀ n : ℕ, (n : ℝ) / 2 * ‖complexPart ℓ (u n)‖ ^ 2 ≤ M + 1 := fun n => by + have h1 := (hu n).2 + have h2 : (1 : ℝ) / ((n : ℝ) + 1) ≤ 1 := by + rw [div_le_one (by positivity)]; linarith [(Nat.cast_nonneg n : (0:ℝ) ≤ n)] + linarith [hM' n] + -- a convergent subsequence + obtain ⟨v, hvS, φ, hφ, hlim⟩ := (isCompact_sphere (0 : E) 1).tendsto_subseq huS + have hv0 : v ≠ 0 := by + rintro rfl + simp at hvS + -- the limit is complex tangent + have hcp : Tendsto (fun n => ‖complexPart ℓ (u (φ n))‖ ^ 2) atTop (𝓝 (‖complexPart ℓ v‖ ^ 2)) := + (((complexPart ℓ).continuous.norm.pow 2).continuousAt.tendsto.comp hlim) + have hφtop : Tendsto (fun n => (φ n : ℝ)) atTop atTop := + tendsto_natCast_atTop_atTop.comp hφ.tendsto_atTop + have hcp0 : ‖complexPart ℓ v‖ ^ 2 = 0 := by + apply le_antisymm _ (by positivity) + have hg : Tendsto (fun n => 2 * (M + 1) / (φ n : ℝ)) atTop (𝓝 0) := + (tendsto_const_div_atTop_nhds_zero_nat (2 * (M + 1))).comp hφ.tendsto_atTop + refine le_of_tendsto_of_tendsto hcp hg ?_ + filter_upwards [hφtop.eventually (eventually_gt_atTop (0 : ℝ))] with n hn + have h := hpart (φ n) + rw [le_div_iff₀ hn] + linarith + have hv_tan : IsComplexTangent ρ p v := by + rw [isComplexTangent_iff_complexPart_eq_zero] + have : ‖complexPart ℓ v‖ = 0 := pow_eq_zero_iff (two_ne_zero) |>.mp hcp0 + exact norm_eq_zero.mp this + -- the limit has nonpositive Levi form + have hlev : leviForm ρ p v ≤ 0 := by + have hl : Tendsto (fun n => leviForm ρ p (u (φ n))) atTop (𝓝 (leviForm ρ p v)) := + (continuous_leviForm ρ p).continuousAt.tendsto.comp hlim + have hg : Tendsto (fun n => 1 / ((φ n : ℝ) + 1)) atTop (𝓝 0) := + tendsto_one_div_add_atTop_nhds_zero_nat.comp hφ.tendsto_atTop + refine le_of_tendsto_of_tendsto hl hg (Filter.Eventually.of_forall fun n => ?_) + have := (hu (φ n)).2 + have hnn : 0 ≤ ((φ n : ℕ) : ℝ) / 2 * ‖complexPart ℓ (u (φ n))‖ ^ 2 := by positivity + linarith + exact absurd (hstrict v hv_tan hv0) (not_lt.mpr hlev) + +end Compactness + +section PeakFunction + +variable [FiniteDimensional ℂ E] {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + +/-- **Levi polynomial as a peak function ([Range][Range1986], Proposition 2.16).** At a boundary +point with +positive definite Levi form on the complex tangent space there is an entire holomorphic function +`F` vanishing at `p` whose real part is negative at all nearby points where the defining +function is nonpositive, except at `p`. -/ +theorem IsLocalDefiningFunction.exists_holomorphic_support (h : IsLocalDefiningFunction U p ρ V) + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ W ∈ 𝓝 p, ∃ F : E → ℂ, AnalyticOnNhd ℂ F univ ∧ F p = 0 ∧ + ∀ z ∈ W, z ≠ p → ρ z ≤ 0 → (F z).re < 0 := by + set ℓ := fderiv ℝ ρ p with hℓ + have hρc : ContDiffAt ℝ 2 ρ p := h.contDiffOn.contDiffAt (h.isOpen.mem_nhds h.mem) + obtain ⟨A, hA, c, hc, hpos⟩ := exists_leviForm_add_normSq_ge hstrict + -- the modified defining function + set σ : E → ℝ := fun z => ρ z + A * ρ z ^ 2 with hσ + have hσc : ContDiffAt ℝ 2 σ p := hρc.add (contDiffAt_const.mul (hρc.pow 2)) + have hσ0 : σ p = 0 := by simp [hσ, h.eq_zero] + have hσlev : ∀ w, c * ‖w‖ ^ 2 ≤ leviForm σ p w := fun w => by + rw [hσ, leviForm_add_mul_sq hρc h.eq_zero] + exact hpos w + have hd : HasFDerivAt ρ ℓ p := (hρc.differentiableAt (by norm_num)).hasFDerivAt + have hσℓ : fderiv ℝ σ p = ℓ := by + have := hd.add ((hd.pow 2).const_mul A) + refine this.fderiv.trans ?_ + ext v + simp [h.eq_zero] + set B := fderiv ℝ (fderiv ℝ σ) p with hB + have hev : ∀ᶠ y in 𝓝 p, HasFDerivAt σ (fderiv ℝ σ y) y := by + filter_upwards [hσc.eventually (by simp)] with y hy + exact (hy.differentiableAt (by norm_num)).hasFDerivAt + have hBd : HasFDerivAt (fderiv ℝ σ) B p := + ((hσc.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hsymm : ∀ v v', B v v' = B v' v := second_derivative_symmetric_of_eventually hev hBd + -- the Levi polynomial + set F : E → ℂ := fun z => complexPart ℓ (z - p) + leviBilinear B (z - p, z - p) with hF + have hFd : Differentiable ℂ F := by + have h1 : Differentiable ℂ (complexPart ℓ) := fun x => + (complexPart ℓ).differentiableAt + have h2 : Differentiable ℂ (leviBilinear B) := fun q => + (isBoundedBilinearMap_leviBilinear B).differentiableAt q + have hsub : Differentiable ℂ (fun z : E => z - p) := differentiable_id.sub_const p + exact (h1.comp hsub).add (h2.comp (hsub.prodMk hsub)) + have hFan : AnalyticOnNhd ℂ F univ := hFd.analyticOnNhd_of_finiteDimensional + have hF0 : F p = 0 := by simp [hF, leviBilinear] + -- Taylor expansion of the modified defining function + obtain ⟨δ, hδ, htaylor⟩ := exists_taylor_bound hσc (ε := c / 2) (by positivity) + have hsmall : ∀ᶠ z in 𝓝 p, |ρ z| < 1 / (A + 1) := by + have hcont : ContinuousAt (fun z => |ρ z|) p := hρc.continuousAt.abs + exact hcont.eventually (eventually_lt_nhds (by + show |ρ p| < 1 / (A + 1) + rw [h.eq_zero, abs_zero] + positivity)) + refine ⟨ball p δ ∩ {z | |ρ z| < 1 / (A + 1)}, inter_mem (ball_mem_nhds p hδ) hsmall, F, hFan, + hF0, ?_⟩ + rintro z ⟨hzδ, hzρ⟩ hzp hρz + have hzρ' : |ρ z| < 1 / (A + 1) := hzρ + set k := z - p with hk + have hk0 : k ≠ 0 := sub_ne_zero.mpr hzp + have hkδ : ‖k‖ < δ := by rw [hk, ← dist_eq_norm]; exact mem_ball.mp hzδ + have ht := htaylor k hkδ + have hpk : p + k = z := by rw [hk]; abel + rw [hpk, hσ0, sub_zero, hσℓ] at ht + -- the real part of the Levi polynomial + have hlin : ℓ k = (complexPart ℓ k).re := by + have := apply_smul_eq_re_mul_complexPart ℓ 1 k + simpa using this + have hquad : (1 / 2 : ℝ) * B k k = leviForm σ p k + (leviQuadratic B k).re := by + have := bilinear_smul_smul_eq B (hsymm k (I • k)) 1 + simpa [leviForm_eq_fderiv, leviQuadratic] using this + have hFre : (F z).re = ℓ k + (leviQuadratic B k).re := by + simp only [hF, Complex.add_re] + rw [← hk, hlin, leviBilinear_self B (hsymm k (I • k))] + -- the modified function is nonpositive at `z` + have hσz : σ z ≤ 0 := by + have h1 : 0 < 1 + A * ρ z := by + have hlow := (abs_lt.mp hzρ').1 + have : A * (1 / (A + 1)) < 1 := by + rw [mul_one_div, div_lt_one (by positivity)] + linarith + nlinarith + have : σ z = (1 + A * ρ z) * ρ z := by simp only [hσ]; ring + rw [this] + exact mul_nonpos_of_nonneg_of_nonpos h1.le hρz + have hknorm : 0 < c / 2 * ‖k‖ ^ 2 := by positivity + have h1 := (abs_le.mp ht).1 + rw [hFre] + linarith [hσlev k] + +/-- **Normalized local peak function.** Exponentiating a holomorphic supporting function +has value one at the boundary point and modulus strictly less than one at every other nearby +point on the closed side of the defining function. -/ +theorem IsLocalDefiningFunction.exists_peak + (h : IsLocalDefiningFunction U p ρ V) + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ W ∈ 𝓝 p, ∃ f : E → ℂ, AnalyticOnNhd ℂ f univ ∧ f p = 1 ∧ + ∀ z ∈ W, z ≠ p → ρ z ≤ 0 → ‖f z‖ < 1 := by + obtain ⟨W, hW, F, hF, hFp, hneg⟩ := h.exists_holomorphic_support hstrict + refine ⟨W, hW, fun z => Complex.exp (F z), ?_, by simp [hFp], ?_⟩ + · exact fun z hz => (hF z hz).cexp + · intro z hz hzp hρ + rw [Complex.norm_exp, Real.exp_lt_one_iff] + exact hneg z hz hzp hρ + +/-- On the domain near a strictly Levi convex boundary point, the Levi polynomial has negative real +part. -/ +theorem IsLocalDefiningFunction.exists_holomorphic_support_of_mem (hU : IsOpen U) (hp : p ∈ + frontier U) + (h : IsLocalDefiningFunction U p ρ V) + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ W ∈ 𝓝 p, ∃ F : E → ℂ, AnalyticOnNhd ℂ F univ ∧ F p = 0 ∧ ∀ z ∈ W ∩ U, (F z).re < 0 := by + obtain ⟨W, hW, F, hFan, hF0, hneg⟩ := h.exists_holomorphic_support hstrict + refine ⟨W ∩ V, inter_mem hW (h.isOpen.mem_nhds h.mem), F, hFan, hF0, ?_⟩ + rintro z ⟨⟨hzW, hzV⟩, hzU⟩ + have hzp : z ≠ p := fun hzp => hU.notMem_of_mem_frontier hp (hzp ▸ hzU) + exact hneg z hzW hzp (h.neg_of_mem hzV hzU).le + +/-- **Local holomorphic blow-up.** At a strictly Levi convex boundary point of an open set there is +a +holomorphic function on the set near the point whose modulus tends to infinity at the point. -/ +theorem IsLocalDefiningFunction.exists_tendsto_norm_atTop (hU : IsOpen U) (hp : p ∈ frontier U) + (h : IsLocalDefiningFunction U p ρ V) + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ W ∈ 𝓝 p, ∃ f : E → ℂ, AnalyticOnNhd ℂ f (W ∩ U) ∧ + Tendsto (fun z => ‖f z‖) (𝓝[U] p) atTop := by + obtain ⟨W, hW, F, hFan, hF0, hneg⟩ := h.exists_holomorphic_support_of_mem hU hp hstrict + have hFne : ∀ z ∈ W ∩ U, F z ≠ 0 := fun z hz hzero => by + have := hneg z hz + rw [hzero, Complex.zero_re] at this + exact lt_irrefl _ this + refine ⟨W, hW, fun z => (F z)⁻¹, fun z hz => (hFan z (mem_univ z)).inv (hFne z hz), ?_⟩ + have hF : Tendsto (fun z => ‖F z‖) (𝓝[U] p) (𝓝[>] 0) := by + rw [tendsto_nhdsWithin_iff] + constructor + · have := ((hFan p (mem_univ p)).continuousAt.norm).tendsto + rw [hF0, norm_zero] at this + exact this.mono_left nhdsWithin_le_nhds + · filter_upwards [nhdsWithin_le_nhds hW, self_mem_nhdsWithin] with z hzW hzU + exact norm_pos_iff.mpr (hFne z ⟨hzW, hzU⟩) + have := tendsto_inv_nhdsGT_zero.comp hF + simpa [Function.comp_def, norm_inv] using this + +end PeakFunction + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm.lean new file mode 100644 index 0000000000..5e148bfeb6 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm.lean @@ -0,0 +1,149 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion + +/-! +# The Levi form + +The Levi form of a real `C²` function on a complex normed space, at a point `a` in a direction +`w`, is defined here in coordinate-free form as one quarter of the sum of the real Hessian +evaluated on `(w, w)` and on `(I • w, I • w)`. On `ℂⁿ` this is the classical Hermitian form `∑ +∂²f/∂z_ν∂\bar z_μ w_ν \bar w_μ`; the definition avoids Wirtinger derivatives. + +The Levi form in direction `w` is one quarter of the Laplacian of the slice `t ↦ f (a + t • w)` +at `t = 0`. Together with the Laplacian criterion for subharmonicity this gives the `C²` +criterion: a `C²` function on an open set is plurisubharmonic exactly when its Levi form is +positive semidefinite at every point. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 2 ("The Levi +Form", Theorem 2.8); [Hörmander][Hormander1973] (1973), Theorem 2.6.2; [Range][Range1986] +(1986), Chapter II, Section 2.6. + +## Main definitions + +* `leviForm`: The Levi form of a real function at `a` in direction `w`: one quarter of the sum of + the real Hessian evaluated on `(w, w)` and on `(I • w, I • w)`. + +## Main results + +* `PlurisubharmonicOn.leviForm_nonneg`: **Necessity.** The Levi form of a `C²` plurisubharmonic + function is positive semidefinite. +* `plurisubharmonicOn_of_leviForm_nonneg`: **Sufficiency.** A `C²` function on an open set with + positive semidefinite Levi form is plurisubharmonic. +* `plurisubharmonicOn_iff_leviForm_nonneg`: **The `C²` criterion for plurisubharmonicity.** A `C²` + function on an open set is plurisubharmonic exactly when its Levi form is positive semidefinite + everywhere. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology Laplacian + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- The Levi form of a real function at `a` in direction `w`: one quarter of the sum of the real +Hessian evaluated on `(w, w)` and on `(I • w, I • w)`. -/ +@[expose] def leviForm (f : E → ℝ) (a w : E) : ℝ := + (iteratedFDeriv ℝ 2 f a ![w, w] + iteratedFDeriv ℝ 2 f a ![I • w, I • w]) / 4 + +/-- The Levi form in terms of the second Fréchet derivative. -/ +theorem leviForm_eq_fderiv (f : E → ℝ) (a w : E) : + leviForm f a w = (fderiv ℝ (fderiv ℝ f) a w w + fderiv ℝ (fderiv ℝ f) a (I • w) (I • w)) / 4 + := by + simp [leviForm, iteratedFDeriv_two_apply] + +variable {f : E → ℝ} {U : Set E} + +/-- The second derivative of a complex-line slice of a `C²` function is the second derivative of the +function evaluated on the direction vectors. -/ +theorem fderiv_fderiv_slice {a w : E} {t₀ : ℂ} (hf : ContDiffAt ℝ 2 f (a + t₀ • w)) (s s' : ℂ) : + fderiv ℝ (fderiv ℝ (fun t : ℂ => f (a + t • w))) t₀ s s' = + fderiv ℝ (fderiv ℝ f) (a + t₀ • w) (s • w) (s' • w) := by + set φ : ℂ → E := fun t => a + ((ContinuousLinearMap.id ℝ ℂ).smulRight w) t with hφdef + have hφ : ∀ t, HasFDerivAt φ ((ContinuousLinearMap.id ℝ ℂ).smulRight w) t := fun t => + ((ContinuousLinearMap.id ℝ ℂ).smulRight w).hasFDerivAt.const_add a + have hφc : Continuous φ := ((ContinuousLinearMap.id ℝ ℂ).smulRight w).continuous.const_add a + have hev : ∀ᶠ t in 𝓝 t₀, ContDiffAt ℝ 2 f (φ t) := + hφc.continuousAt.eventually (hf.eventually (by simp)) + have hg : (fun t => fderiv ℝ (f ∘ φ) t) =ᶠ[𝓝 t₀] + fun t => (fderiv ℝ f (φ t)).comp ((ContinuousLinearMap.id ℝ ℂ).smulRight w) := by + filter_upwards [hev] with t ht + exact ((ht.differentiableAt (by norm_num)).hasFDerivAt.comp t (hφ t)).fderiv + have hD2 : HasFDerivAt (fderiv ℝ f) (fderiv ℝ (fderiv ℝ f) (φ t₀)) (φ t₀) := + ((hf.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hcomp : HasFDerivAt (fun t => fderiv ℝ f (φ t)) + ((fderiv ℝ (fderiv ℝ f) (φ t₀)).comp ((ContinuousLinearMap.id ℝ ℂ).smulRight w)) t₀ + := hD2.comp t₀ (hφ t₀) + have hfin := hcomp.clm_comp (hasFDerivAt_const ((ContinuousLinearMap.id ℝ ℂ).smulRight w) t₀) + have hgφ : (fun t : ℂ => f (a + t • w)) = f ∘ φ := rfl + rw [hgφ, hg.fderiv_eq, hfin.fderiv] + simp [ContinuousLinearMap.compL_apply] + rfl + +/-- The first derivative of a complex-line slice of a differentiable function. -/ +theorem fderiv_slice {a w : E} {t₀ : ℂ} (hf : DifferentiableAt ℝ f (a + t₀ • w)) : + fderiv ℝ (fun t : ℂ => f (a + t • w)) t₀ = (fderiv ℝ f (a + t₀ • w)).comp + ((ContinuousLinearMap.id ℝ ℂ).smulRight w) := by + have hφ : HasFDerivAt (fun t : ℂ => a + ((ContinuousLinearMap.id ℝ ℂ).smulRight w) t) + ((ContinuousLinearMap.id ℝ ℂ).smulRight w) t₀ := + ((ContinuousLinearMap.id ℝ ℂ).smulRight w).hasFDerivAt.const_add a + exact (hf.hasFDerivAt.comp t₀ hφ).fderiv + +/-- The Laplacian of a complex-line slice is four times the Levi form in that direction. -/ +theorem laplacian_slice {a w : E} {t₀ : ℂ} (hf : ContDiffAt ℝ 2 f (a + t₀ • w)) : + Δ (fun t : ℂ => f (a + t • w)) t₀ = 4 * leviForm f (a + t₀ • w) w := by + rw [laplacian_eq_fderiv_fderiv, fderiv_fderiv_slice hf, fderiv_fderiv_slice hf, + leviForm_eq_fderiv, one_smul] + ring + +/-- **Necessity.** The Levi form of a `C²` plurisubharmonic function is positive semidefinite. -/ +theorem PlurisubharmonicOn.leviForm_nonneg (hU : IsOpen U) (hf : ContDiffOn ℝ 2 f U) + (hpsh : PlurisubharmonicOn f U) {a : E} (ha : a ∈ U) (w : E) : 0 ≤ leviForm f a w := by + have ha' : a + (0 : ℂ) • w ∈ U := by simpa using ha + have hc : ContDiffAt ℝ 2 (fun t : ℂ => f (a + t • w)) 0 := + (hf.contDiffAt (hU.mem_nhds ha')).comp 0 + (by fun_prop : ContDiff ℝ 2 fun t : ℂ => a + t • w).contDiffAt + have := (hpsh.hasSubmeanAt_slice ha w).laplacian_nonneg hc + rw [laplacian_slice (hf.contDiffAt (hU.mem_nhds ha'))] at this + simp only [zero_smul, add_zero] at this + linarith + +/-- **Sufficiency.** A `C²` function on an open set with positive semidefinite Levi form is +plurisubharmonic. -/ +theorem plurisubharmonicOn_of_leviForm_nonneg (hU : IsOpen U) (hf : ContDiffOn ℝ 2 f U) + (h : ∀ a ∈ U, ∀ w : E, 0 ≤ leviForm f a w) : PlurisubharmonicOn f U := by + refine ⟨hf.continuousOn.upperSemicontinuousOn, fun a ha w => ?_⟩ + apply subharmonicOn_of_laplacian_nonneg + (hU.preimage (by fun_prop : Continuous fun t : ℂ => a + t • w)) + · exact hf.comp (by fun_prop : ContDiff ℝ 2 fun t : ℂ => a + t • w).contDiffOn fun _ ht => ht + · intro t ht + rw [laplacian_slice (hf.contDiffAt (hU.mem_nhds ht))] + exact mul_nonneg (by norm_num) (h _ ht w) + +/-- **The `C²` criterion for plurisubharmonicity.** A `C²` function on an open set is +plurisubharmonic exactly when its Levi form is positive semidefinite everywhere. -/ +theorem plurisubharmonicOn_iff_leviForm_nonneg (hU : IsOpen U) (hf : ContDiffOn ℝ 2 f U) : + PlurisubharmonicOn f U ↔ ∀ a ∈ U, ∀ w : E, 0 ≤ leviForm f a w := + ⟨fun hpsh _ ha w => hpsh.leviForm_nonneg hU hf ha w, + fun h => plurisubharmonicOn_of_leviForm_nonneg hU hf h⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm/Holomorphic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm/Holomorphic.lean new file mode 100644 index 0000000000..393f5b2cca --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviForm/Holomorphic.lean @@ -0,0 +1,123 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.ContDiff.Operations +public import Mathlib.Analysis.Calculus.ContDiff.RestrictScalars +public import Mathlib.Analysis.Calculus.FDeriv.RestrictScalars +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm + +/-! +# The Levi form under holomorphic maps + +The Levi form transforms under a holomorphic map `Φ` by the chain rule `Lev (g ∘ Φ) (a, w) = Lev +g (Φ a, Φ'(a) w)`: the second derivative of `Φ` contributes `Dg (D²Φ (w, w) + D²Φ (I • w, I • +w))`, which vanishes because the second derivative of a holomorphic map is complex bilinear. +Consequently `C²` plurisubharmonic functions compose with holomorphic maps to `C²` +plurisubharmonic functions. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 2, Example 4 +after the definition of the Levi form; [Hörmander][Hormander1973] (1973), Theorem 2.6.4 (smooth +case). + +## Main results + +* `leviForm_comp_analytic`: **Chain rule for the Levi form.** For a `C²` function `g` and a + holomorphic map `Φ`, `Lev (g ∘ Φ) (a, w) = Lev g (Φ a, Φ'(a) w)`. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The real second derivative of a holomorphic map is complex bilinear: it changes sign when both +arguments are multiplied by `I`. -/ +theorem fderiv_fderiv_smul_I_smul_I {Φ : E → F} {a : E} (hΦ : AnalyticAt ℂ Φ a) (s t : E) : + fderiv ℝ (fderiv ℝ Φ) a (I • s) (I • t) = -fderiv ℝ (fderiv ℝ Φ) a s t := by + have hc : ContDiffAt ℂ 2 Φ a := hΦ.contDiffAt + have hr := hc.restrictScalars_iteratedFDeriv (𝕜 := ℝ) (n := 2) + have h1 : fderiv ℝ (fderiv ℝ Φ) a (I • s) (I • t) = iteratedFDeriv ℝ 2 Φ a ![I • s, I • t] := by + rw [iteratedFDeriv_two_apply]; rfl + have h2 : fderiv ℝ (fderiv ℝ Φ) a s t = iteratedFDeriv ℝ 2 Φ a ![s, t] := by + rw [iteratedFDeriv_two_apply]; rfl + have hv : (![I • s, I • t] : Fin 2 → E) = fun i => I • (![s, t] : Fin 2 → E) i := by + funext i; fin_cases i <;> rfl + rw [h1, h2, ← hr, hv] + change (iteratedFDeriv ℂ 2 Φ a) (fun i => I • (![s, t] : Fin 2 → E) i) = + -(iteratedFDeriv ℂ 2 Φ a) ![s, t] + rw [ContinuousMultilinearMap.map_smul_univ] + simp + +/-- **Chain rule for the Levi form.** For a `C²` function `g` and a holomorphic map `Φ`, +`Lev (g ∘ Φ) (a, w) = Lev g (Φ a, Φ'(a) w)`. -/ +theorem leviForm_comp_analytic {g : F → ℝ} {Φ : E → F} {a : E} (hg : ContDiffAt ℝ 2 g (Φ a)) + (hΦ : AnalyticAt ℂ Φ a) (w : E) : + leviForm (g ∘ Φ) a w = leviForm g (Φ a) (fderiv ℂ Φ a w) := by + have hΦc : ContDiffAt ℝ 2 Φ a := (hΦ.contDiffAt (n := 2)).restrict_scalars ℝ + -- first derivatives near `a` + have hΦev : ∀ᶠ x in 𝓝 a, HasFDerivAt Φ (fderiv ℝ Φ x) x := by + filter_upwards [hΦc.eventually (by simp)] with x hx + exact (hx.differentiableAt (by norm_num)).hasFDerivAt + have hgev : ∀ᶠ x in 𝓝 a, HasFDerivAt g (fderiv ℝ g (Φ x)) (Φ x) := by + have hcont : ContinuousAt Φ a := hΦc.continuousAt + filter_upwards [hcont.eventually (hg.eventually (by simp))] with x hx + exact (hx.differentiableAt (by norm_num)).hasFDerivAt + have hD1 : (fun x => fderiv ℝ (g ∘ Φ) x) =ᶠ[𝓝 a] + fun x => (fderiv ℝ g (Φ x)).comp (fderiv ℝ Φ x) := by + filter_upwards [hΦev, hgev] with x hx1 hx2 + exact (hx2.comp x hx1).fderiv + -- second derivatives + have hD2Φ : HasFDerivAt (fderiv ℝ Φ) (fderiv ℝ (fderiv ℝ Φ) a) a := + ((hΦc.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hD2g : HasFDerivAt (fderiv ℝ g) (fderiv ℝ (fderiv ℝ g) (Φ a)) (Φ a) := + ((hg.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hΦa : HasFDerivAt Φ (fderiv ℝ Φ a) a := hΦc.differentiableAt (by norm_num) |>.hasFDerivAt + have hcomp : HasFDerivAt (fun x => fderiv ℝ g (Φ x)) + ((fderiv ℝ (fderiv ℝ g) (Φ a)).comp (fderiv ℝ Φ a)) a := hD2g.comp a hΦa + have hfin := hcomp.clm_comp hD2Φ + have hD2 : ∀ s t : E, fderiv ℝ (fderiv ℝ (g ∘ Φ)) a s t = + fderiv ℝ g (Φ a) (fderiv ℝ (fderiv ℝ Φ) a s t) + + fderiv ℝ (fderiv ℝ g) (Φ a) (fderiv ℝ Φ a s) (fderiv ℝ Φ a t) := by + intro s t + rw [hD1.fderiv_eq, hfin.fderiv] + simp [ContinuousLinearMap.compL_apply] + -- complex linearity of the first derivative + have hlin : fderiv ℝ Φ a (I • w) = I • fderiv ℂ Φ a w := by + rw [hΦ.differentiableAt.fderiv_restrictScalars (𝕜 := ℝ), + ContinuousLinearMap.coe_restrictScalars', + map_smul] + have hlin' : fderiv ℝ Φ a w = fderiv ℂ Φ a w := by + rw [hΦ.differentiableAt.fderiv_restrictScalars (𝕜 := ℝ), + ContinuousLinearMap.coe_restrictScalars'] + rw [leviForm_eq_fderiv, leviForm_eq_fderiv, hD2, hD2, fderiv_fderiv_smul_I_smul_I hΦ, map_neg, + hlin, hlin'] + ring + +/-- `C²` plurisubharmonic functions compose with holomorphic maps. -/ +theorem PlurisubharmonicOn.comp_analyticOnNhd {g : F → ℝ} {V : Set F} (hV : IsOpen V) + (hgc : ContDiffOn ℝ 2 g V) (hg : PlurisubharmonicOn g V) {Φ : E → F} {U : Set E} + (hU : IsOpen U) (hΦ : AnalyticOnNhd ℂ Φ U) (hmaps : MapsTo Φ U V) : + PlurisubharmonicOn (g ∘ Φ) U := by + have hΦc : ContDiffOn ℝ 2 Φ U := (hΦ.contDiffOn hU.uniqueDiffOn (n := 2)).restrict_scalars ℝ + refine plurisubharmonicOn_of_leviForm_nonneg hU (hgc.comp hΦc hmaps) fun a ha w => ?_ + rw [leviForm_comp_analytic (hgc.contDiffAt (hV.mem_nhds (hmaps ha))) (hΦ a ha)] + exact hg.leviForm_nonneg hV hgc (hmaps ha) _ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyBounded.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyBounded.lean new file mode 100644 index 0000000000..fc84a25e3e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyBounded.lean @@ -0,0 +1,161 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.MeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates + +/-! +# Locally bounded separate holomorphy + +Coordinate Cauchy estimates give joint local Lipschitz bounds for locally bounded, separately +holomorphic functions. This supplies the continuity hypothesis of Osgood's theorem and the +equicontinuity estimate used in Montel's theorem. + +## Main results + +`exists_lipschitzOnWith_of_separately_analytic_locally_bounded` converts a local bound on a +separately holomorphic map into a joint local Lipschitz bound, hence into joint continuity. +`analyticOnNhd_of_separately_analytic_locally_bounded` is the corresponding analyticity +statement, using Osgood after that continuity. +-/ + +public section + +open Complex Filter Function Metric Set +open scoped NNReal Topology + +namespace SeveralComplexVariables + +variable {ι F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [NormedSpace ℂ F] + +omit [NormedSpace ℂ F] in +/-- Coordinate variation bounds telescope to a joint bound on a product set. This also includes the +empty product, where every function is constant. -/ +theorem norm_sub_le_sum_of_update {s : ι → Set ℂ} {f : (ι → ℂ) → F} {C : ℝ} + (hf : ∀ z ∈ Set.pi univ s, ∀ i, ∀ w ∈ s i, + ‖f (update z i w) - f z‖ ≤ C * ‖w - z i‖) + {x y : ι → ℂ} (hx : x ∈ Set.pi univ s) (hy : y ∈ Set.pi univ s) : + ‖f y - f x‖ ≤ ∑ i, C * ‖y i - x i‖ := by + have hmem (t : Finset ι) : (fun i => if i ∈ t then y i else x i) ∈ Set.pi univ s := by + intro i hi + dsimp only + split_ifs <;> [exact hy i hi; exact hx i hi] + have hstep (t : Finset ι) : + ‖f (fun i => if i ∈ t then y i else x i) - f x‖ ≤ ∑ i ∈ t, C * ‖y i - x i‖ := by + induction t using Finset.induction_on with + | empty => simp + | @insert i t hi ih => + have heq : (fun j => if j ∈ insert i t then y j else x j) = + update (fun j => if j ∈ t then y j else x j) i (y i) := by + funext j + by_cases hji : j = i <;> simp [hji] + rw [heq, Finset.sum_insert hi] + refine (norm_sub_le_norm_sub_add_norm_sub _ (f (fun j => if j ∈ t then y j else x j)) _).trans + (add_le_add ?_ ih) + simpa [hi] using hf _ (hmem t) i (y i) (hy i (mem_univ i)) + simpa using hstep Finset.univ + +/-- Updating a coordinate within its disc preserves a closed sup-norm ball. -/ +theorem update_mem_closedBall_of_mem {c z : ι → ℂ} {r : ℝ} (hr : 0 ≤ r) + (hz : z ∈ closedBall c r) (i : ι) {w : ℂ} (hw : w ∈ closedBall (c i) r) : + update z i w ∈ closedBall c r := by + rw [mem_closedBall, dist_pi_le_iff hr] at hz ⊢ + intro j + by_cases hji : j = i + · simpa [hji] using hw + · simpa [hji] using hz j + +/-- A bounded separately holomorphic map is jointly Lipschitz on a smaller polydisc. The constant is +explicit and uniform over families with the same bound. -/ +theorem norm_sub_le_of_separately_analytic_bounded {f : (ι → ℂ) → F} + {c : ι → ℂ} {r M : ℝ} (hr : 0 < r) + (hf : ∀ z ∈ closedBall c (2 * r), ∀ i, + AnalyticAt ℂ (fun w => f (update z i w)) (z i)) + (hM : ∀ z ∈ closedBall c (2 * r), ‖f z‖ ≤ M) + {x y : ι → ℂ} (hx : x ∈ closedBall c r) (hy : y ∈ closedBall c r) : + ‖f y - f x‖ ≤ (Fintype.card ι : ℝ) * (M / r) * ‖y - x‖ := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans (hM c (mem_closedBall_self (by positivity))) + have hsmall : closedBall c r ⊆ closedBall c (2 * r) := closedBall_subset_closedBall (by linarith) + have hdiff (z : ι → ℂ) (i : ι) (w : ℂ) (hw : update z i w ∈ closedBall c (2 * r)) : + DifferentiableAt ℂ (fun v => f (update z i v)) w := by + simpa only [update_idem, update_self] using (hf _ hw i).differentiableAt + have hcoord (z : ι → ℂ) (hz : z ∈ closedBall c r) (i : ι) (w : ℂ) + (hw : w ∈ closedBall (c i) r) : + ‖f (update z i w) - f z‖ ≤ (M / r) * ‖w - z i‖ := by + have hder (v : ℂ) (hv : v ∈ closedBall (c i) r) : + ‖deriv (fun a => f (update z i a)) v‖ ≤ M / r := by + have hp := update_mem_closedBall_of_mem hr.le hz i hv + have hball : closedBall (update z i v) r ⊆ closedBall c (2 * r) := + closedBall_subset_closedBall' (by linarith [mem_closedBall.mp hp]) + have hslice := norm_partialDeriv_le_of_slice (f := f) (z := update z i v) i hr + (fun a ha => (hdiff (update z i v) i a + (hball (update_mem_closedBall hr.le ha))).differentiableWithinAt) + (fun a ha => hM _ (hball (update_mem_closedBall hr.le (sphere_subset_closedBall ha)))) + simpa only [partialDeriv, update_idem, update_self] using hslice + have hzi : z i ∈ closedBall (c i) r := (dist_pi_le_iff hr.le).mp (mem_closedBall.mp hz) i + simpa only [update_eq_self] using + (convex_closedBall (c i) r).norm_image_sub_le_of_norm_deriv_le + (fun v hv => hdiff z i v (hsmall (update_mem_closedBall_of_mem hr.le hz i hv))) + hder hzi hw + have hprod : closedBall c r = Set.pi univ (fun i => closedBall (c i) r) := closedBall_pi c hr.le + have hsum := norm_sub_le_sum_of_update (C := M / r) + (fun z hz i w hw => hcoord z (hprod.symm ▸ hz) i w hw) (hprod ▸ hx) (hprod ▸ hy) + refine hsum.trans ?_ + calc + ∑ i, (M / r) * ‖y i - x i‖ ≤ ∑ i : ι, (M / r) * ‖y - x‖ := + Finset.sum_le_sum (fun i _ => mul_le_mul_of_nonneg_left (norm_le_pi_norm (y - x) i) + (div_nonneg hM0 hr.le)) + _ = _ := by simp [mul_assoc] + +/-- Local bounds and separate holomorphy give a Lipschitz neighborhood of each point. -/ +theorem exists_lipschitzOnWith_of_separately_analytic_locally_bounded + {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) + {c : ι → ℂ} (hc : c ∈ U) (hb : ∃ M : ℝ, ∀ᶠ z in 𝓝 c, ‖f z‖ ≤ M) : + ∃ r > 0, ∃ C : ℝ≥0, LipschitzOnWith C f (closedBall c r) := by + obtain ⟨M, hM⟩ := hb + obtain ⟨R, hR, hball⟩ := nhds_basis_closedBall.mem_iff.mp (inter_mem (hU.mem_nhds hc) hM) + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans + (hball (mem_closedBall_self hR.le)).2 + have hr : 0 < R / 2 := by positivity + have htwo : 2 * (R / 2) = R := by ring + have hfa : ∀ z ∈ closedBall c (2 * (R / 2)), ∀ i, + AnalyticAt ℂ (fun w => f (update z i w)) (z i) := by + intro z hz + exact hf z (hball (by simpa only [htwo] using hz)).1 + have hbound : ∀ z ∈ closedBall c (2 * (R / 2)), ‖f z‖ ≤ M := by + intro z hz + exact (hball (by simpa only [htwo] using hz)).2 + refine ⟨R / 2, hr, ⟨(Fintype.card ι : ℝ) * (M / (R / 2)), by positivity⟩, ?_⟩ + apply lipschitzOnWith_iff_norm_sub_le.mpr + intro x hx y hy + exact norm_sub_le_of_separately_analytic_bounded hr hfa hbound hy hx + +variable [CompleteSpace F] + +/-- **Locally bounded Osgood theorem.** Joint continuity need not be assumed when a +separately holomorphic map is locally bounded on its open domain. + +This is weaker than Hartogs' theorem `analyticOnNhd_of_separately_analytic`, which drops the +local boundedness hypothesis. It is a step in the proof of that theorem, applied after Baire's +theorem provides local bounds, and therefore cannot be derived from it. -/ +theorem analyticOnNhd_of_separately_analytic_locally_bounded + {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) + (hb : ∀ c ∈ U, ∃ M : ℝ, ∀ᶠ z in 𝓝 c, ‖f z‖ ≤ M) : AnalyticOnNhd ℂ f U := by + apply analyticOnNhd_pi_of_analyticOnNhd_update hU _ hf + apply continuousOn_of_forall_continuousAt + intro c hc + obtain ⟨r, hr, C, hC⟩ := exists_lipschitzOnWith_of_separately_analytic_locally_bounded + hU hf hc (hb c hc) + exact hC.continuousOn.continuousAt (closedBall_mem_nhds _ hr) + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean new file mode 100644 index 0000000000..26de2b762d --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean @@ -0,0 +1,278 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.LocallyUniformLimit +public import Mathlib.Analysis.Normed.Group.FunctionSeries +public import Mathlib.Topology.Algebra.InfiniteSum.TsumUniformlyOn +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Locally uniform limits of analytic maps in several variables + +This file proves the Weierstrass convergence theorem for finite-dimensional complex domains, its +normally summable series consequences, and locally uniform convergence of all mixed coordinate +and iterated Fréchet derivatives. The topological notion `TendstoLocallyUniformlyOn` is +Mathlib's. + +This is a temporary project home for material ultimately intended for a Mathlib location such as +`Mathlib.Analysis.Complex.SeveralVariables.LocallyUniform`. + +## Main results + +* `TendstoLocallyUniformlyOn.analyticOnNhd_pi` is the several-variable Weierstrass convergence + theorem for finite complex coordinate spaces. +* `HasSumLocallyUniformlyOn.analyticOnNhd_pi` is its series form. +* `TendstoLocallyUniformlyOn.partialDeriv` and + `TendstoLocallyUniformlyOn.iteratedPartialDeriv` give convergence of coordinate derivatives. +* `HasSumLocallyUniformlyOn.iteratedPartialDeriv` gives termwise differentiation of series. +* `TendstoLocallyUniformlyOn.analyticOnNhd_of_finiteDimensional` and + `TendstoLocallyUniformlyOn.iteratedFDeriv_of_finiteDimensional` are the coordinate-independent + formulations, with multilinear operator norm for the latter. + +Derivative convergence uses a one-variable Cauchy estimate on compact thickenings, followed by +finite sums, currying, and transport along a continuous linear choice of coordinates. +-/ + +public section + +open Filter Set + +variable {ι κ F : Type*} [Fintype ι] [DecidableEq ι] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- **Weierstrass convergence theorem, finite-coordinate form.** A locally uniform limit of +analytic maps on an open subset of a finite complex coordinate space is analytic. -/ +theorem TendstoLocallyUniformlyOn.analyticOnNhd_pi + {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] + {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : + AnalyticOnNhd ℂ g U := by + classical + have hg : ContinuousOn g U := + hlim.continuousOn (hf.frequently.mono fun _ hn => hn.continuousOn) + apply SeveralComplexVariables.analyticOnNhd_pi_of_analyticOnNhd_update hU hg + intro z hz i + let update : ℂ → (ι → ℂ) := fun w ↦ Function.update z i w + let V : Set ℂ := update ⁻¹' U + have hupdate : Continuous update := by + dsimp only [update] + fun_prop + have hupdate_diff : Differentiable ℂ update := + fun w => (hasDerivAt_update z i w).differentiableAt + have hV : IsOpen V := hU.preimage hupdate + have hmap : Set.MapsTo update V U := fun _ hw ↦ hw + have hlim' : TendstoLocallyUniformlyOn + (fun n ↦ f n ∘ update) (g ∘ update) l V := + hlim.comp update hmap hupdate.continuousOn + have hfdiff : ∀ᶠ n in l, DifferentiableOn ℂ (f n ∘ update) V := by + filter_upwards [hf] with n hn + intro w hw + exact (((hn.differentiableOn _ hw).differentiableAt + (hU.mem_nhds (hmap hw))).comp w hupdate_diff.differentiableAt).differentiableWithinAt + exact (hlim'.differentiableOn hfdiff hV).analyticAt + (hV.mem_nhds (show update (z i) ∈ U by simpa [update] using hz)) + +/-- A locally uniformly convergent sum of analytic maps on an open finite complex coordinate space +is analytic. -/ +theorem HasSumLocallyUniformlyOn.analyticOnNhd_pi + {U : Set (ι → ℂ)} {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hsum : HasSumLocallyUniformlyOn f g U) + (hf : ∀ n, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : + AnalyticOnNhd ℂ g U := by + apply TendstoLocallyUniformlyOn.analyticOnNhd_pi hsum _ hU + filter_upwards with s + exact Finset.analyticOnNhd_fun_sum s fun n _ ↦ hf n + +/-- A series of analytic maps is analytic when its terms admit a summable uniform majorant on every +compact subset of the domain. -/ +theorem analyticOnNhd_tsum_of_summable_norm_on_compacts + {U : Set (ι → ℂ)} {f : κ → (ι → ℂ) → F} + (hU : IsOpen U) (hf : ∀ n, AnalyticOnNhd ℂ (f n) U) + (hmajorant : ∀ K ⊆ U, IsCompact K → ∃ M : κ → ℝ, + Summable M ∧ ∀ n x, x ∈ K → ‖f n x‖ ≤ M n) : + AnalyticOnNhd ℂ (fun x ↦ ∑' n, f n x) U := by + have hs : SummableLocallyUniformlyOn f U := + SummableLocallyUniformlyOn_of_locally_bounded hU hmajorant + exact hs.hasSumLocallyUniformlyOn.analyticOnNhd_pi hf hU + +/-- Locally uniform convergence of holomorphic maps implies locally uniform convergence of each +coordinate derivative. The Cauchy estimate is applied on a compact thickening. -/ +theorem TendstoLocallyUniformlyOn.partialDeriv + {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] + {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (i : ι) : + TendstoLocallyUniformlyOn (fun n => SeveralComplexVariables.partialDeriv i (f n)) + (SeveralComplexVariables.partialDeriv i g) l U := by + have hg := hlim.analyticOnNhd_pi hf hU + rw [tendstoLocallyUniformlyOn_iff_forall_isCompact hU] + intro K hKU hK + obtain ⟨δ, hδ, hKδ⟩ := hK.exists_cthickening_subset_open hU hKU + have hc := (tendstoLocallyUniformlyOn_iff_forall_isCompact hU).mp hlim + (Metric.cthickening δ K) hKδ hK.cthickening + rw [Metric.tendstoUniformlyOn_iff] at hc ⊢ + intro ε hε + filter_upwards [hf, hc (ε * δ / 2) (by positivity)] with n hn hbound z hz + have hball : Metric.closedBall z δ ⊆ Metric.cthickening δ K := + Metric.closedBall_subset_cthickening hz δ + have hnorm := SeveralComplexVariables.norm_partialDeriv_le (hg.sub hn) i hδ + (hball.trans hKδ) (M := ε * δ / 2) (fun w hw => by + exact le_of_lt (by simpa [dist_eq_norm] using hbound w (hball hw))) + rw [SeveralComplexVariables.partialDeriv_sub (hg z (hKU hz)).differentiableAt + (hn z (hKU hz)).differentiableAt i] at hnorm + rw [dist_eq_norm] + exact hnorm.trans_lt ((div_lt_iff₀ hδ).mpr (by nlinarith [mul_pos hε hδ])) + +/-- All mixed coordinate derivatives converge locally uniformly on the original domain. -/ +theorem TendstoLocallyUniformlyOn.iteratedPartialDeriv + {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] + {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (is : List ι) : + TendstoLocallyUniformlyOn (fun n => SeveralComplexVariables.iteratedPartialDeriv is (f n)) + (SeveralComplexVariables.iteratedPartialDeriv is g) l U := by + induction is with + | nil => exact hlim + | cons i is ih => + exact ih.partialDeriv (hf.mono fun n hn => hn.iteratedPartialDeriv hU is) hU i + +/-- Locally uniform convergence of holomorphic maps gives locally uniform convergence of their +Fréchet derivatives in operator norm. -/ +theorem TendstoLocallyUniformlyOn.fderiv_pi + {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] + {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : + TendstoLocallyUniformlyOn (fun n => fderiv ℂ (f n)) (fderiv ℂ g) l U := by + classical + let L (i : ι) : F →L[ℂ] ((ι → ℂ) →L[ℂ] F) := + ContinuousLinearMap.smulRightL ℂ (ι → ℂ) F (ContinuousLinearMap.proj i) + have hi (i : ι) := (L i).uniformContinuous.comp_tendstoLocallyUniformlyOn + (hlim.partialDeriv hf hU i) + have hs (s : Finset ι) : TendstoLocallyUniformlyOn + (fun n z => ∑ i ∈ s, L i (SeveralComplexVariables.partialDeriv i (f n) z)) + (fun z => ∑ i ∈ s, L i (SeveralComplexVariables.partialDeriv i g z)) l U := by + induction s using Finset.induction_on with + | empty => + simpa using (tendsto_const_nhds.tendstoUniformlyOn_const U).tendstoLocallyUniformlyOn + | @insert i s his ih => + simpa only [Finset.sum_insert his, Function.comp_def] using (hi i).fun_add ih + have heq {a : (ι → ℂ) → F} {z : ι → ℂ} (ha : DifferentiableAt ℂ a z) : + (∑ i, L i (SeveralComplexVariables.partialDeriv i a z)) = fderiv ℂ a z := by + ext v + simpa [L] using (SeveralComplexVariables.fderiv_eq_sum_partialDeriv ha v).symm + have h := (hs Finset.univ).congr_inseparable (hf.mono fun n hn z hz => + Inseparable.of_eq (heq (hn z hz).differentiableAt)) + exact h.congr_right fun z hz => heq ((hlim.analyticOnNhd_pi hf hU) z hz).differentiableAt + +/-- All iterated Fréchet derivatives converge locally uniformly in multilinear operator norm. -/ +theorem TendstoLocallyUniformlyOn.iteratedFDeriv_pi + {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] + {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (k : ℕ) : + TendstoLocallyUniformlyOn (fun n => iteratedFDeriv ℂ k (f n)) + (iteratedFDeriv ℂ k g) l U := by + induction k with + | zero => + simpa only [iteratedFDeriv_zero_eq_comp] using + (continuousMultilinearCurryFin0 ℂ (ι → ℂ) + F).symm.isometry.uniformContinuous.comp_tendstoLocallyUniformlyOn hlim + | succ k ih => + have hd := ih.fderiv_pi (hf.mono fun n hn => hn.iteratedFDeriv_of_isOpen hU k) hU + simpa only [iteratedFDeriv_succ_eq_comp_left] using + (continuousMultilinearCurryLeftEquiv ℂ (fun _ : Fin (k + 1) => ι → ℂ) + F).symm.isometry.uniformContinuous.comp_tendstoLocallyUniformlyOn hd + +/-- A locally uniformly convergent holomorphic series may be differentiated term by term any finite +number of times, with locally uniform convergence of the differentiated series. -/ +theorem HasSumLocallyUniformlyOn.iteratedPartialDeriv + {U : Set (ι → ℂ)} {f : κ → (ι → ℂ) → F} {g : (ι → ℂ) → F} + (hsum : HasSumLocallyUniformlyOn f g U) + (hf : ∀ n, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (is : List ι) : + HasSumLocallyUniformlyOn (fun n => SeveralComplexVariables.iteratedPartialDeriv is (f n)) + (SeveralComplexVariables.iteratedPartialDeriv is g) U := by + have h := TendstoLocallyUniformlyOn.iteratedPartialDeriv hsum + (Eventually.of_forall fun t => Finset.analyticOnNhd_fun_sum t fun n _ => hf n) hU is + exact h.congr_inseparable (Eventually.of_forall fun t z hz => Inseparable.of_eq + (SeveralComplexVariables.iteratedPartialDeriv_finset_sum t (fun n _ => hf n) hU is hz)) + +section FiniteDimensional + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + +/-- The Weierstrass convergence theorem on any finite-dimensional complex normed domain. -/ +theorem TendstoLocallyUniformlyOn.analyticOnNhd_of_finiteDimensional + {U : Set E} {l : Filter κ} [l.NeBot] {f : κ → E → F} {g : E → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : + AnalyticOnNhd ℂ g U := by + let e := (Module.finBasis ℂ E).equivFunL + have hc := hlim.comp e.symm (fun _ hx => hx) e.symm.continuous.continuousOn + have ha := hc.analyticOnNhd_pi (hf.mono fun n hn => + hn.comp (e.symm.toContinuousLinearMap.analyticOnNhd _) (fun _ hx => hx)) + (hU.preimage e.symm.continuous) + intro x hx + have hmem : e x ∈ e.symm ⁻¹' U := by simpa using hx + simpa [Function.comp_def] using + (ha (e x) hmem).comp_of_eq (e.toContinuousLinearMap.analyticAt x) rfl + +/-- Locally uniform convergence of the Fréchet derivatives, without a choice of coordinates in the +statement. The target carries the operator norm. -/ +theorem TendstoLocallyUniformlyOn.fderiv_of_finiteDimensional + {U : Set E} {l : Filter κ} [l.NeBot] {f : κ → E → F} {g : E → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : + TendstoLocallyUniformlyOn (fun n => fderiv ℂ (f n)) (fderiv ℂ g) l U := by + let e := (Module.finBasis ℂ E).equivFunL + have hc := hlim.comp e.symm (fun _ hx => hx) e.symm.continuous.continuousOn + have hd := hc.fderiv_pi (hf.mono fun n hn => + hn.comp (e.symm.toContinuousLinearMap.analyticOnNhd _) (fun _ hx => hx)) + (hU.preimage e.symm.continuous) + let L := (ContinuousLinearMap.compL ℂ E (Fin (Module.finrank ℂ E) → ℂ) F).flip + e.toContinuousLinearMap + have H := (L.uniformContinuous.comp_tendstoLocallyUniformlyOn hd).comp e + (fun x hx => show e x ∈ e.symm ⁻¹' U by simpa using hx) e.continuous.continuousOn + have heq {a : E → F} {x : E} (ha : DifferentiableAt ℂ a x) : + L (fderiv ℂ (a ∘ e.symm) (e x)) = fderiv ℂ a x := by + have ha' : DifferentiableAt ℂ a (e.symm (e x)) := by simpa using ha + rw [fderiv_comp _ ha' e.symm.differentiableAt, e.symm.fderiv] + ext v + simp [L] + have H' := H.congr_inseparable (hf.mono fun n hn x hx => + Inseparable.of_eq (heq (hn x hx).differentiableAt)) + exact H'.congr_right fun x hx => heq + ((hlim.analyticOnNhd_of_finiteDimensional hf hU) x hx).differentiableAt + +/-- All iterated Fréchet derivatives converge locally uniformly on a finite-dimensional complex +domain, in multilinear operator norm. -/ +theorem TendstoLocallyUniformlyOn.iteratedFDeriv_of_finiteDimensional + {U : Set E} {l : Filter κ} [l.NeBot] {f : κ → E → F} {g : E → F} + (hlim : TendstoLocallyUniformlyOn f g l U) + (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (k : ℕ) : + TendstoLocallyUniformlyOn (fun n => iteratedFDeriv ℂ k (f n)) + (iteratedFDeriv ℂ k g) l U := by + induction k with + | zero => + simpa only [iteratedFDeriv_zero_eq_comp] using + (continuousMultilinearCurryFin0 ℂ E + F).symm.isometry.uniformContinuous.comp_tendstoLocallyUniformlyOn hlim + | succ k ih => + have hd := ih.fderiv_of_finiteDimensional + (hf.mono fun n hn => hn.iteratedFDeriv_of_isOpen hU k) hU + simpa only [iteratedFDeriv_succ_eq_comp_left] using + (continuousMultilinearCurryLeftEquiv ℂ (fun _ : Fin (k + 1) => E) + F).symm.isometry.uniformContinuous.comp_tendstoLocallyUniformlyOn hd + +end FiniteDimensional + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/MaximumModulus.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/MaximumModulus.lean new file mode 100644 index 0000000000..9437f2c4ec --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/MaximumModulus.lean @@ -0,0 +1,70 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.AbsMax +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple + +/-! +# The maximum modulus principle in several variables + +If the modulus of a scalar holomorphic function on an open, preconnected set has a local maximum +at an interior point, then the function is constant on the set. This is +[Fritzsche–Grauert][FritzscheGrauert2002] (2002), I.4.11, p. 22. A local maximum suffices; a +maximum over the whole domain is not required. The proof combines Mathlib's local maximum +modulus principle with the holomorphic identity theorem. + +The source is any finite-dimensional complex normed space, including `ι → ℂ` for any finite +index type (also empty). The supporting norm theorem permits strictly convex complex Banach +targets. Strict convexity cannot be dropped for constancy of the map: on the unit disc, `z ↦ (1, +z)` is nonconstant but has constant supremum norm. + +## Main results + +* `eqOn_const_of_holomorphic_of_isLocalMax_norm`: **Maximum modulus principle + ([Fritzsche–Grauert][FritzscheGrauert2002] I.4.11).** A holomorphic map into a strictly convex + complex Banach space, in particular a scalar holomorphic function, is constant on an open, + preconnected domain if its norm has a local maximum at an interior point. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +-/ + +public section + +open Set Filter Function +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + +/-- **Maximum modulus principle ([Fritzsche–Grauert][FritzscheGrauert2002] I.4.11).** A holomorphic +map into a strictly convex complex Banach space, in particular a scalar holomorphic function, is +constant on an open, preconnected domain if its norm has a local maximum at an interior point. -/ +theorem eqOn_const_of_holomorphic_of_isLocalMax_norm + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + [StrictConvexSpace ℝ F] {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) + {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hmax : IsLocalMax (norm ∘ f) a) : EqOn f (const E (f a)) U := + hf.eqOn_of_preconnected_of_eventuallyEq hU hconn (differentiableOn_const (f a)) ha + (Complex.eventually_eq_of_isLocalMax_norm + (hf.eventually_differentiableAt (hU.mem_nhds ha)) hmax) + +/-- The maximum principle with the local maximum expressed relative to the domain. Since the point +is interior, this agrees with the ambient local-maximum formulation. -/ +theorem eqOn_const_of_holomorphic_of_isLocalMaxOn_norm + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + [StrictConvexSpace ℝ F] {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) + {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hmax : IsLocalMaxOn (norm ∘ f) U a) : EqOn f (const E (f a)) U := + eqOn_const_of_holomorphic_of_isLocalMax_norm hU hconn hf ha (hmax.isLocalMax (hU.mem_nhds ha)) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Montel.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Montel.lean new file mode 100644 index 0000000000..42d89f712e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Montel.lean @@ -0,0 +1,245 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Schwarz +public import Mathlib.Topology.MetricSpace.Equicontinuity +public import Mathlib.Topology.UniformSpace.Ascoli +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded + +/-! +# Montel's and Vitali's theorems + +A family of holomorphic maps which is bounded uniformly on each compact subset of its domain is +equicontinuous. For finite-dimensional targets it has compact closure in the compact-open +topology. Compactness is supplied by Mathlib's Arzelà–Ascoli theorem. For uniformly bounded +sequences, a subsequence theorem is also provided on arbitrary finite-dimensional complex source +spaces. Vitali convergence follows from compactness and the identity theorem: pointwise +convergence on a nonempty open subset determines every cluster limit uniquely. + +## Main results + +`equicontinuous_of_holomorphic_bounded_on_compacts` is equicontinuity of a family bounded on compact +sets. `isCompact_closure_of_holomorphic_bounded_on_compacts` is Montel's theorem for +finite-dimensional targets. `exists_tendstoLocallyUniformlyOn_of_forall_exists_tendsto` is Vitali +convergence from pointwise convergence on a nonempty open subset. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public section + +open Complex Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +omit [CompleteSpace F] in +/-- Compact-local bounds on a holomorphic family give equicontinuity. Banach targets are allowed +here; finite dimensionality is needed only for compactness in Montel's theorem. -/ +theorem equicontinuous_of_holomorphic_bounded_on_compacts + {U : TopologicalSpace.Opens E} {S : Set (HolomorphicMap U F)} + (hb : ∀ K ⊆ (U : Set E), IsCompact K → ∃ M : ℝ, + ∀ f ∈ S, ∀ z ∈ K, ‖openExtension U f.val z‖ ≤ M) : + Equicontinuous (fun f : S => (f.val.val : U → F)) := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + intro c + rw [Metric.equicontinuousAt_iff] + intro ε hε + obtain ⟨R, hR, hRU⟩ := nhds_basis_closedBall.mem_iff.mp (U.isOpen.mem_nhds c.property) + obtain ⟨M, hM⟩ := hb (closedBall (c : E) R) hRU (isCompact_closedBall _ _) + let C : ℝ := 2 * max M 0 / R + have hC : 0 ≤ C := div_nonneg (by positivity) hR.le + refine ⟨min R (ε / (C + 1)), lt_min hR (div_pos hε (by positivity)), ?_⟩ + intro w hw f + have hwr : dist (w : E) c < R := (lt_min_iff.mp hw).1 + have hwe : dist (w : E) c < ε / (C + 1) := (lt_min_iff.mp hw).2 + have hmaps : MapsTo (openExtension U f.val.val) (ball (c : E) R) + (closedBall (openExtension U f.val.val c) (2 * max M 0)) := by + intro z hz + rw [mem_closedBall, dist_eq_norm] + calc + ‖openExtension U f.val.val z - openExtension U f.val.val c‖ ≤ + ‖openExtension U f.val.val z‖ + ‖openExtension U f.val.val c‖ := norm_sub_le _ _ + _ ≤ max M 0 + max M 0 := add_le_add + ((hM f.val f.property z (ball_subset_closedBall hz)).trans (le_max_left _ _)) + ((hM f.val f.property c (mem_closedBall_self hR.le)).trans (le_max_left _ _)) + _ = 2 * max M 0 := by ring + have hn := dist_le_div_mul_dist_of_mapsTo_ball + (f.val.property.differentiableOn.mono (ball_subset_closedBall.trans hRU)) hmaps hwr + simp only [openExtension_coe] at hn + have hlt : (C + 1) * dist (w : E) c < ε := by + nlinarith [(lt_div_iff₀ (by positivity : 0 < C + 1)).mp hwe] + rw [dist_comm] + change dist (f.val.val w) (f.val.val c) < ε + change dist (f.val.val w) (f.val.val c) ≤ C * dist (w : E) c at hn + nlinarith [show 0 ≤ dist (w : E) (c : E) from dist_nonneg] + +/-- **Montel's theorem.** A compact-locally bounded family of holomorphic maps into a +finite-dimensional complex normed space has compact closure in the compact-open topology. -/ +theorem isCompact_closure_of_holomorphic_bounded_on_compacts + [FiniteDimensional ℂ F] {U : TopologicalSpace.Opens E} + {S : Set (HolomorphicMap U F)} + (hb : ∀ K ⊆ (U : Set E), IsCompact K → ∃ M : ℝ, + ∀ f ∈ S, ∀ z ∈ K, ‖openExtension U f.val z‖ ≤ M) : IsCompact (closure S) := by + let := FiniteDimensional.proper ℂ F + let := UniformOnFun.t2Space_of_covering (β := F) + (𝔖 := {K : Set U | IsCompact K}) (by + apply eq_univ_iff_forall.mpr + intro z + exact mem_sUnion_of_mem (mem_singleton z) isCompact_singleton) + have he : Topology.IsClosedEmbedding + (UniformOnFun.ofFun {K : Set U | IsCompact K} ∘ + (fun f : HolomorphicMap U F => (f.val : U → F))) := by + exact (ContinuousMap.isUniformEmbedding_toUniformOnFunIsCompact.comp + isUniformEmbedding_subtype_val).isClosedEmbedding + apply ArzelaAscoli.isCompact_closure_of_isClosedEmbedding (fun K hK => hK) he + · intro K hK + exact (equicontinuous_of_holomorphic_bounded_on_compacts hb).equicontinuousOn K + · intro K hK z hz + obtain ⟨M, hM⟩ := hb {(z : E)} (singleton_subset_iff.mpr z.property) isCompact_singleton + refine ⟨closedBall (0 : F) (max M 0), isCompact_closedBall _ _, ?_⟩ + intro f hf + have h := (hM f hf z (mem_singleton _)).trans (le_max_left M 0) + simpa using h + +/-- **Vitali's theorem ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.4.24)** in the compact-open +function space. +A locally bounded sequence converging pointwise on a nonempty open subset of a +preconnected domain converges in the whole holomorphic-map space. -/ +theorem exists_tendsto_of_holomorphic_bounded_on_compacts + [FiniteDimensional ℂ F] {U : TopologicalSpace.Opens E} + (hconn : IsPreconnected (U : Set E)) (f : ℕ → HolomorphicMap U F) + (hb : ∀ K ⊆ (U : Set E), IsCompact K → ∃ M : ℝ, + ∀ n, ∀ z ∈ K, ‖openExtension U (f n).val z‖ ≤ M) + {V : Set E} (hV : IsOpen V) (hne : V.Nonempty) (hVU : V ⊆ U) + (hp : ∀ z ∈ V, ∃ y : F, + Tendsto (fun n => openExtension U (f n).val z) atTop (𝓝 y)) : + ∃ g : HolomorphicMap U F, Tendsto f atTop (𝓝 g) := by + have hc : IsCompact (closure (range f)) := + isCompact_closure_of_holomorphic_bounded_on_compacts (by + intro K hKU hK + obtain ⟨M, hM⟩ := hb K hKU hK + exact ⟨M, by rintro _ ⟨n, rfl⟩; exact hM n⟩) + have hm : ∀ᶠ n in atTop, f n ∈ closure (range f) := + .of_forall fun n => subset_closure (mem_range_self n) + obtain ⟨g, _, hg⟩ := hc.exists_mapClusterPt_of_frequently hm.frequently + refine ⟨g, hc.tendsto_nhds_of_unique_mapClusterPt hm ?_⟩ + intro q _ hq + have hvalue : ∀ (r : HolomorphicMap U F), MapClusterPt r atTop f → + ∀ z ∈ V, ∀ y : F, + Tendsto (fun n => openExtension U (f n).val z) atTop (𝓝 y) → + openExtension U r.val z = y := by + intro r hr z hz y hy + have he := hr.continuousAt_comp + (continuous_holomorphicMap_eval U ⟨z, hVU hz⟩).continuousAt + obtain ⟨φ, hφ, hlim⟩ := he.tendsto_subseq + have hy' : Tendsto (fun n => (f n).val ⟨z, hVU hz⟩) atTop (𝓝 y) := by + simpa only [openExtension_apply U _ (hVU hz)] using hy + simpa only [openExtension_apply U _ (hVU hz)] using + tendsto_nhds_unique hlim (hy'.comp hφ.tendsto_atTop) + have heq : EqOn (openExtension U q.val) (openExtension U g.val) U := + DifferentiableOn.eqOn_of_preconnected_of_eqOn U.isOpen hconn q.property.differentiableOn + g.property.differentiableOn hV hne hVU (by + intro z hz + obtain ⟨y, hy⟩ := hp z hz + exact (hvalue q hq z hz y hy).trans (hvalue g hg z hz y hy).symm) + apply Subtype.ext + apply ContinuousMap.ext + intro z + simpa only [openExtension_coe] using heq z.property + +/-- **Vitali's theorem** for holomorphic functions on a finite-dimensional complex normed space. +The limit is holomorphic and convergence is locally uniform on the whole domain. +Finite-dimensional complex targets, including scalar-valued functions, are allowed. -/ +theorem exists_tendstoLocallyUniformlyOn_of_forall_exists_tendsto [FiniteDimensional ℂ F] + {D V : Set E} + (hD : IsOpen D) (hconn : IsPreconnected D) {f : ℕ → E → F} + (hf : ∀ n, DifferentiableOn ℂ (f n) D) + (hb : ∀ K ⊆ D, IsCompact K → ∃ M : ℝ, ∀ n, ∀ z ∈ K, ‖f n z‖ ≤ M) + (hV : IsOpen V) (hne : V.Nonempty) (hVD : V ⊆ D) + (hp : ∀ z ∈ V, ∃ y : F, Tendsto (fun n => f n z) atTop (𝓝 y)) : + ∃ g : E → F, DifferentiableOn ℂ g D ∧ + TendstoLocallyUniformlyOn f g atTop D := by + let U : TopologicalSpace.Opens E := ⟨D, hD⟩ + let s : ℕ → HolomorphicMap U F := fun n => + ⟨⟨fun z => f n z, (hf n).continuousOn.domRestrict⟩, + by + apply AnalyticOnNhd.congr hD ((hf n).analyticOnNhd_of_finiteDimensional hD) + intro z hz + simp [openExtension, U, hz] + rfl⟩ + have hs : ∀ n, ∀ z ∈ D, openExtension U (s n).val z = f n z := by + intro n z hz + exact openExtension_apply U _ hz + obtain ⟨g, hg⟩ := exists_tendsto_of_holomorphic_bounded_on_compacts hconn s + (by + intro K hKD hK + obtain ⟨M, hM⟩ := hb K hKD hK + refine ⟨M, fun n z hz => ?_⟩ + rw [hs n z (hKD hz)] + exact hM n z hz) hV hne hVD (by + intro z hz + simpa only [hs _ z (hVD hz)] using hp z hz) + refine ⟨openExtension U g.val, g.property.differentiableOn, ?_⟩ + exact (holomorphicMap_tendsto_iff.mp hg).congr + (fun n z hz => hs n z hz) + +/-- A uniformly bounded holomorphic sequence on a finite-dimensional complex space has a locally +uniformly convergent subsequence, with holomorphic limit. -/ +theorem exists_subseq_tendstoLocallyUniformlyOn_of_uniform_bound + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [FiniteDimensional ℂ F] {U : Set E} (hU : IsOpen U) {f : ℕ → E → F} + (hf : ∀ n, AnalyticOnNhd ℂ (f n) U) {M : ℝ} + (hM : ∀ n z, z ∈ U → ‖f n z‖ ≤ M) : + ∃ (g : E → F) (φ : ℕ → ℕ), StrictMono φ ∧ AnalyticOnNhd ℂ g U ∧ + TendstoLocallyUniformlyOn (fun n => f (φ n)) g atTop U := by + let e := (Module.finBasis ℂ E).equivFunL + let V : TopologicalSpace.Opens (Fin (Module.finrank ℂ E) → ℂ) := + ⟨e.symm ⁻¹' U, hU.preimage e.symm.continuous⟩ + let : LocallyCompactSpace V := V.isOpen.locallyCompactSpace + have hA (n) : AnalyticOnNhd ℂ (f n ∘ e.symm) V := + (hf n).comp (e.symm.toContinuousLinearMap.analyticOnNhd _) (fun _ hz => hz) + let G (n : ℕ) : HolomorphicMap V F := + ⟨⟨fun z => f n (e.symm z), (hA n).continuousOn.domRestrict⟩, + (hA n).congr V.isOpen (fun z hz => by rw [openExtension_apply V _ hz]; rfl)⟩ + have hc : IsCompact (closure (range G)) := + isCompact_closure_of_holomorphic_bounded_on_compacts (by + intro K hKV _ + refine ⟨M, ?_⟩ + rintro _ ⟨n, rfl⟩ z hz + rw [openExtension_apply V _ (hKV hz)] + exact hM n _ (hKV hz)) + have : (uniformity C(V, F)).IsCountablyGenerated := inferInstance + have : (uniformity (HolomorphicMap V F)).IsCountablyGenerated := + Filter.comap.isCountablyGenerated _ _ + have hm : ∀ᶠ n in atTop, G n ∈ closure (range G) := + .of_forall fun n => subset_closure (mem_range_self n) + obtain ⟨g, _, hg⟩ := hc.exists_mapClusterPt_of_frequently hm.frequently + obtain ⟨φ, hφ, hlim⟩ := hg.tendsto_subseq + let g' : E → F := fun z => openExtension V g.val (e z) + have hmaps : MapsTo e U V := fun z hz => by simpa [V] using hz + refine ⟨g', φ, hφ, g.property.comp (e.toContinuousLinearMap.analyticOnNhd U) hmaps, ?_⟩ + have hl := (holomorphicMap_tendsto_iff.mp hlim).comp e hmaps e.continuous.continuousOn + apply hl.congr + intro n z hz + simp only [Function.comp_apply, openExtension_apply V _ (hmaps hz), G] + change f (φ n) (e.symm (e z)) = f (φ n) z + rw [e.symm_apply_apply] + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Osgood.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Osgood.lean new file mode 100644 index 0000000000..f3ea1c8fdc --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Osgood.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.LinearAlgebra.FiniteDimensional.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries + +/-! +# Osgood's theorem in finite products + +Joint continuity and separate holomorphy imply joint analyticity on an open subset of a finite +complex coordinate space. The stronger Hartogs theorem without continuity is not proved here. +The polydisc Cauchy formula and its series construction live in the imported modules and remain +available through this file. + +## Main results + +`analyticOnNhd_pi_of_analyticOnNhd_update` is Osgood's theorem on an arbitrary finite coordinate +space `ι → ℂ`: continuity on an open set together with holomorphy in each coordinate separately +yields joint analyticity. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped ENNReal NNReal Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-- Osgood's theorem on `Fin d → ℂ`, before reindexing to an arbitrary finite coordinate type. -/ +private theorem analyticOnNhd_fin_of_analyticOnNhd_update {d : ℕ} + {U : Set (Fin d → ℂ)} {f : (Fin d → ℂ) → E} + (hU : IsOpen U) (hfc : ContinuousOn f U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + intro c hc + obtain ⟨R, hR, hRU⟩ := nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hc) + have hP : closedPolydisc c (fun _ => R) ⊆ U := by + rw [closedPolydisc_eq_closedBall hR.le] + exact hRU + have hfcP : ContinuousOn f (closedPolydisc c (fun _ => R)) := hfc.mono hP + have hfaP : ∀ z ∈ closedPolydisc c (fun _ => R), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i) := fun z hz => hf z (hP hz) + have hPcpt : IsCompact (closedPolydisc c (fun _ => R)) := by + rw [closedPolydisc_eq_closedBall hR.le] + exact isCompact_closedBall _ _ + obtain ⟨M, hM⟩ := hPcpt.bddAbove_image hfcP.norm + exact (hasFPowerSeriesOnBall_polydiscCauchy hR hfcP hfaP + (fun z hz => hM (mem_image_of_mem _ hz))).analyticAt + +/-- **Osgood's theorem, finite-product form.** A jointly continuous function on an open subset of +a finite product of copies of `ℂ` is jointly analytic when all of its one-coordinate restrictions +are analytic. + +This is weaker than Hartogs' theorem `analyticOnNhd_of_separately_analytic`, which drops the +continuity hypothesis. It is the first step in the proof of that theorem, through the locally +bounded version `analyticOnNhd_of_separately_analytic_locally_bounded`, and therefore cannot be +derived from it. Continuity is present in every application preceding Hartogs' theorem in this +library. -/ +theorem analyticOnNhd_pi_of_analyticOnNhd_update + {ι : Type*} [Fintype ι] [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → E} + (hU : IsOpen U) (hfc : ContinuousOn f U) + (hf : ∀ z ∈ U, ∀ i, + AnalyticAt ℂ (fun w => f (Function.update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + let e : Fin (Fintype.card ι) ≃ ι := (Fintype.equivFin ι).symm + let L : (Fin (Fintype.card ι) → ℂ) ≃L[ℂ] (ι → ℂ) := + ContinuousLinearEquiv.piCongrLeft ℂ (fun _ : ι => ℂ) e + let V : Set (Fin (Fintype.card ι) → ℂ) := L ⁻¹' U + let g : (Fin (Fintype.card ι) → ℂ) → E := f ∘ L + have hV : IsOpen V := hU.preimage L.continuous + have hgc : ContinuousOn g V := + hfc.comp L.continuous.continuousOn (fun _ hz => hz) + have hL_apply (z : Fin (Fintype.card ι) → ℂ) + (j : Fin (Fintype.card ι)) : L z (e j) = z j := by + change (Equiv.piCongrLeft (fun _ : ι => ℂ) e) z (e j) = z j + exact Equiv.piCongrLeft_apply_apply (fun _ : ι => ℂ) e z j + have hL_update (z : Fin (Fintype.card ι) → ℂ) + (j : Fin (Fintype.card ι)) (w : ℂ) : + L (update z j w) = update (L z) (e j) w := by + funext i + obtain ⟨k, rfl⟩ := e.surjective i + by_cases hkj : k = j + · subst k + simp [hL_apply] + · have hek : e k ≠ e j := fun he => hkj (e.injective he) + simp [hkj, hek, hL_apply] + have hga : ∀ z ∈ V, ∀ j, + AnalyticAt ℂ (fun w => g (update z j w)) (z j) := by + intro z hz j + have h := hf (L z) hz (e j) + convert h using 1 + · funext w + simp only [g, Function.comp_apply] + rw [hL_update] + · exact (hL_apply z j).symm + have hg := analyticOnNhd_fin_of_analyticOnNhd_update hV hgc hga + intro z hz + have hzV : L.symm z ∈ V := by + change L (L.symm z) ∈ U + simpa + have hcomp : AnalyticAt ℂ (g ∘ ⇑L.symm.toContinuousLinearMap) z := + AnalyticAt.compContinuousLinearMap (u := L.symm.toContinuousLinearMap) + (hg (L.symm z) hzV) + simpa [g, Function.comp_def] using hcomp + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ParametricIntegral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ParametricIntegral.lean new file mode 100644 index 0000000000..51548bbdb1 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ParametricIntegral.lean @@ -0,0 +1,181 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.ParametricIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Analytic dependence of integrals on several complex parameters + +This file combines Mathlib's dominated differentiation-under-the-integral API with +finite-dimensional complex analyticity from `SeveralComplexVariables.Analyticity`. A +compact-domain criterion derives the required domination from joint continuity of the pointwise +derivative. + +The parameter space in the analyticity criterion is an arbitrary finite-dimensional complex +normed space: the statement uses Fréchet derivatives and requires no coordinates. The compact +integral criteria below concern a single complex parameter and arbitrary compact integration +sets, not a particular integration geometry. This material is ultimately intended near +`Mathlib.Analysis.Calculus.ParametricIntegral`. + +## Main results + +`analyticOnNhd_integral_of_dominated_of_fderiv_le` packages the existing local dominated +Fréchet-derivative criterion at every point of an open finite-dimensional parameter domain. + +`hasDerivAt_integral_of_continuousOn_compact` identifies the derivative of a compact set +integral with the integral of its pointwise complex derivative. +`hasDerivAt_integral_smul_of_continuousOn_compact` allows a fixed scalar weight with Banach-valued +kernels; `hasDerivAt_integral_mul_of_continuousOn_compact` is its scalar specialization, including a +weight singular on the boundary. The general dominated Fréchet derivative identification is +already Mathlib's `hasFDerivAt_integral_of_dominated_of_fderiv_le`. The integral theorem names +remain in the root namespace, consistently with that API. +-/ + +public section + +open Filter MeasureTheory Set +open scoped Topology + +variable {α E : Type*} [MeasurableSpace α] + [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-- An integral on a finite-dimensional complex parameter space is analytic if, locally at every +parameter, its pointwise Fréchet derivatives have an integrable uniform bound. The hypotheses +are grouped pointwise so that the dominating function and neighborhood may depend on the base +parameter. -/ +theorem analyticOnNhd_integral_of_dominated_of_fderiv_le + {P : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] [FiniteDimensional ℂ P] + {μ : Measure α} {U : Set P} {F : P → α → E} + (hU : IsOpen U) + (hdom : ∀ x ∈ U, ∃ (s : Set P) (bound : α → ℝ) + (F' : P → α → P →L[ℂ] E), + s ∈ nhds x ∧ + (∀ᶠ y in nhds x, AEStronglyMeasurable (F y) μ) ∧ + Integrable (F x) μ ∧ AEStronglyMeasurable (F' x) μ ∧ + (∀ᵐ a ∂μ, ∀ y ∈ s, ‖F' y a‖ ≤ bound a) ∧ Integrable bound μ ∧ + (∀ᵐ a ∂μ, ∀ y ∈ s, HasFDerivAt (F · a) (F' y a) y)) : + AnalyticOnNhd ℂ (fun x ↦ ∫ a, F x a ∂μ) U := by + apply DifferentiableOn.analyticOnNhd_of_finiteDimensional _ hU + intro x hx + obtain ⟨s, bound, F', hs, hmeas, hint, hF'meas, hbound, hboundInt, hdiff⟩ := hdom x hx + exact (hasFDerivAt_integral_of_dominated_of_fderiv_le hs hmeas hint hF'meas + hbound hboundInt hdiff).differentiableAt.differentiableWithinAt + +omit [CompleteSpace E] in +/-- Differentiation under an integral over a compact set when the integrand and its pointwise +complex derivative are jointly continuous. Compactness supplies domination. -/ +theorem hasDerivAt_integral_of_continuousOn_compact + [TopologicalSpace α] [BorelSpace α] [T2Space α] + {μ : Measure α} [IsLocallyFiniteMeasure μ] {K : Set α} (hK : IsCompact K) + {U : Set ℂ} (hU : IsOpen U) {x : ℂ} (hx : x ∈ U) + {F F' : ℂ → α → E} + (hF : ContinuousOn (fun p : ℂ × α => F p.1 p.2) (U ×ˢ K)) + (hF' : ContinuousOn (fun p : ℂ × α => F' p.1 p.2) (U ×ˢ K)) + (hd : ∀ z ∈ U, ∀ a ∈ K, HasDerivAt (fun w => F w a) (F' z a) z) : + HasDerivAt (fun z => ∫ a in K, F z a ∂μ) (∫ a in K, F' x a ∂μ) x := by + obtain ⟨r, hr, hball⟩ := Metric.nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hx) + have hc : IsCompact (Metric.closedBall x r ×ˢ K) := (isCompact_closedBall _ _).prod hK + have hcont := hF'.mono (Set.prod_mono hball Subset.rfl) + obtain ⟨M, hM⟩ := hc.bddAbove_image hcont.norm + have hslice {z : ℂ} (hz : z ∈ U) : ContinuousOn (F z) K := + hF.comp (continuous_const.prodMk continuous_id).continuousOn (fun a ha => ⟨hz, ha⟩) + have hslice' {z : ℂ} (hz : z ∈ U) : ContinuousOn (F' z) K := + hF'.comp (continuous_const.prodMk continuous_id).continuousOn (fun a ha => ⟨hz, ha⟩) + apply (hasDerivAt_integral_of_dominated_loc_of_deriv_le + (μ := μ.restrict K) (F := F) (F' := F') (bound := fun _ => M) + (Metric.closedBall_mem_nhds x hr) ?_ ((hslice hx).integrableOn_compact hK) + ((hslice' hx).integrableOn_compact hK).aestronglyMeasurable ?_ + (integrableOn_const hK.measure_ne_top) ?_).2 + · filter_upwards [hU.eventually_mem hx] with z hz + exact ((hslice hz).integrableOn_compact hK).aestronglyMeasurable + · filter_upwards [ae_restrict_mem hK.measurableSet] with a ha + intro z hz + exact hM (mem_image_of_mem (fun p : ℂ × α => ‖F' p.1 p.2‖) + (show (z, a) ∈ Metric.closedBall x r ×ˢ K from ⟨hz, ha⟩)) + · filter_upwards [ae_restrict_mem hK.measurableSet] with a ha + intro z hz + exact hd z (hball hz) a ha + +omit [CompleteSpace E] in +/-- An integrable scalar weight times a continuous Banach-valued function on a compact set is +integrable. Compactness gives both boundedness and a separable image, so no countability +assumption on either ambient space is required. -/ +theorem MeasureTheory.IntegrableOn.smul_continuousOn_of_isCompact + [TopologicalSpace α] [BorelSpace α] [T2Space α] + {μ : Measure α} {K : Set α} {g : α → ℂ} {H : α → E} + (hg : IntegrableOn g K μ) (hH : ContinuousOn H K) (hK : IsCompact K) : + IntegrableOn (fun t => g t • H t) K μ := by + obtain ⟨M, hM⟩ := hK.bddAbove_image hH.norm + apply (hg.norm.mul_const M).mono' + (hg.aestronglyMeasurable.smul (hH.aestronglyMeasurable_of_isCompact hK hK.measurableSet)) + filter_upwards [ae_restrict_mem hK.measurableSet] with t ht + change ‖g t • H t‖ ≤ ‖g t‖ * M + rw [norm_smul] + exact mul_le_mul_of_nonneg_left (hM ⟨t, ht, rfl⟩) (norm_nonneg _) + +omit [CompleteSpace E] in +/-- A fixed integrable scalar weight can be included in compact-domain differentiation. Only the +kernel and its derivative must be jointly continuous; the weight may be singular on the boundary +of the integration domain. -/ +theorem hasDerivAt_integral_smul_of_continuousOn_compact + [TopologicalSpace α] [BorelSpace α] [T2Space α] + {μ : Measure α} {K : Set α} (hK : IsCompact K) + {g : α → ℂ} (hg : IntegrableOn g K μ) + {U : Set ℂ} (hU : IsOpen U) {x : ℂ} (hx : x ∈ U) + {F F' : ℂ → α → E} + (hF : ContinuousOn (fun p : ℂ × α => F p.1 p.2) (U ×ˢ K)) + (hF' : ContinuousOn (fun p : ℂ × α => F' p.1 p.2) (U ×ˢ K)) + (hd : ∀ z ∈ U, ∀ a ∈ K, HasDerivAt (fun w => F w a) (F' z a) z) : + HasDerivAt (fun z => ∫ a in K, g a • F z a ∂μ) + (∫ a in K, g a • F' x a ∂μ) x := by + obtain ⟨r, hr, hball⟩ := Metric.nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hx) + have hc : IsCompact (Metric.closedBall x r ×ˢ K) := (isCompact_closedBall _ _).prod hK + obtain ⟨M, hM⟩ := hc.bddAbove_image + (hF'.mono (Set.prod_mono hball Subset.rfl)).norm + have hslice {z : ℂ} (hz : z ∈ U) : ContinuousOn (F z) K := + hF.comp (continuous_const.prodMk continuous_id).continuousOn (fun a ha => ⟨hz, ha⟩) + have hslice' {z : ℂ} (hz : z ∈ U) : ContinuousOn (F' z) K := + hF'.comp (continuous_const.prodMk continuous_id).continuousOn (fun a ha => ⟨hz, ha⟩) + apply (hasDerivAt_integral_of_dominated_loc_of_deriv_le + (μ := μ.restrict K) (F := fun z a => g a • F z a) + (F' := fun z a => g a • F' z a) (bound := fun a => ‖g a‖ * M) + (Metric.closedBall_mem_nhds x hr) ?_ (hg.smul_continuousOn_of_isCompact (hslice hx) hK) + (hg.smul_continuousOn_of_isCompact (hslice' hx) hK).aestronglyMeasurable ?_ + (hg.norm.mul_const M) ?_).2 + · filter_upwards [hU.eventually_mem hx] with z hz + exact (hg.smul_continuousOn_of_isCompact (hslice hz) hK).aestronglyMeasurable + · filter_upwards [ae_restrict_mem hK.measurableSet] with a ha + intro z hz + rw [norm_smul] + exact mul_le_mul_of_nonneg_left + (hM (mem_image_of_mem (fun p : ℂ × α => ‖F' p.1 p.2‖) + (show (z, a) ∈ Metric.closedBall x r ×ˢ K from ⟨hz, ha⟩))) (norm_nonneg _) + · filter_upwards [ae_restrict_mem hK.measurableSet] with a ha + intro z hz + exact (hd z (hball hz) a ha).const_smul (g a) + +/-- A fixed integrable scalar weight can be included in compact-domain differentiation. Only the +kernel and its derivative must be jointly continuous; the weight may be singular on the boundary +of the integration domain. -/ +theorem hasDerivAt_integral_mul_of_continuousOn_compact + [TopologicalSpace α] [BorelSpace α] [T2Space α] + {μ : Measure α} {K : Set α} (hK : IsCompact K) + {g : α → ℂ} (hg : IntegrableOn g K μ) + {U : Set ℂ} (hU : IsOpen U) {x : ℂ} (hx : x ∈ U) + {F F' : ℂ → α → ℂ} + (hF : ContinuousOn (fun p : ℂ × α => F p.1 p.2) (U ×ˢ K)) + (hF' : ContinuousOn (fun p : ℂ × α => F' p.1 p.2) (U ×ˢ K)) + (hd : ∀ z ∈ U, ∀ a ∈ K, HasDerivAt (fun w => F w a) (F' z a) z) : + HasDerivAt (fun z => ∫ a in K, g a * F z a ∂μ) + (∫ a in K, g a * F' x a ∂μ) x := by + simpa only [smul_eq_mul] using + hasDerivAt_integral_smul_of_continuousOn_compact hK hg hU hx hF hF' hd + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean new file mode 100644 index 0000000000..cb6cb9ff1f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean @@ -0,0 +1,255 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Module.Convex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic + +/-! +# Plurisubharmonic functions + +A real function on an open subset of a complex normed space is plurisubharmonic if it is upper +semicontinuous and its restriction to every complex line is subharmonic, in the local submean +sense of `Subharmonic`. This file proves closure under sums, nonnegative multiples, maxima and +complex affine substitutions, shows that continuous convex functions are plurisubharmonic, and +gives the holomorphic examples: real parts, positive powers of norms, and logarithms of +nonvanishing moduli of holomorphic functions. + +Only real-valued functions are considered. The characterization of `C²` plurisubharmonic +functions through the Levi form is proved in `LeviForm`. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 2; +[Hörmander][Hormander1973] (1973), Definition 2.6.1; [Range][Range1986] (1986), Chapter II, +Section 5. + +## Main definitions + +* `PlurisubharmonicOn`: A real function is plurisubharmonic on a set if it is upper semicontinuous + there and its restriction to every complex line is subharmonic on the corresponding parameter set. + +## Main results + +* `PlurisubharmonicOn.add`: Sums of plurisubharmonic functions are plurisubharmonic. +* `PlurisubharmonicOn.sup`: The pointwise maximum of two plurisubharmonic functions is + plurisubharmonic. +* `PlurisubharmonicOn.comp_affine`: Plurisubharmonicity is preserved by complex affine + substitutions. +* `ConvexOn.plurisubharmonicOn`: A continuous convex function on an open set is plurisubharmonic. +* `plurisubharmonicOn_norm`: The norm is plurisubharmonic. +* `AnalyticOnNhd.plurisubharmonicOn_re`: Real parts of holomorphic functions are plurisubharmonic. +* `AnalyticOnNhd.plurisubharmonicOn_norm_rpow`: Positive powers of the norm of a holomorphic map are + plurisubharmonic. +* `AnalyticOnNhd.plurisubharmonicOn_log_norm`: The logarithm of the modulus of a nonvanishing + holomorphic function is plurisubharmonic. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public section + +open Filter Metric Set Real +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A real function is plurisubharmonic on a set if it is upper semicontinuous there and its +restriction to every complex line is subharmonic on the corresponding parameter set. -/ +@[expose] def PlurisubharmonicOn (f : E → ℝ) (U : Set E) : Prop := + UpperSemicontinuousOn f U ∧ + ∀ a ∈ U, ∀ w : E, SubharmonicOn (fun t : ℂ => f (a + t • w)) {t | a + t • w ∈ U} + +variable {f g : E → ℝ} {U V : Set E} + +/-- A plurisubharmonic function is upper semicontinuous. -/ +theorem PlurisubharmonicOn.upperSemicontinuousOn (h : PlurisubharmonicOn f U) : + UpperSemicontinuousOn f U := h.1 + +/-- Complex-line slices of a plurisubharmonic function are subharmonic. -/ +theorem PlurisubharmonicOn.slice (h : PlurisubharmonicOn f U) {a : E} (ha : a ∈ U) (w : E) : + SubharmonicOn (fun t : ℂ => f (a + t • w)) {t | a + t • w ∈ U} := h.2 a ha w + +/-- The local submean property of the slice through a point of the domain. -/ +theorem PlurisubharmonicOn.hasSubmeanAt_slice (h : PlurisubharmonicOn f U) {a : E} (ha : a ∈ U) + (w : E) : HasSubmeanAt (fun t : ℂ => f (a + t • w)) 0 := + (h.slice ha w).hasSubmeanAt (by simpa using ha) + +/-- Plurisubharmonicity restricts to subsets. -/ +theorem PlurisubharmonicOn.mono (h : PlurisubharmonicOn f U) (hV : V ⊆ U) : + PlurisubharmonicOn f V := + ⟨h.1.mono hV, fun a ha w => (h.2 a (hV ha) w).mono fun _ ht => hV ht⟩ + +/-- The slice of an upper semicontinuous function is upper semicontinuous. -/ +theorem upperSemicontinuousOn_slice (h : UpperSemicontinuousOn f U) (a w : E) : + UpperSemicontinuousOn (fun t : ℂ => f (a + t • w)) {t | a + t • w ∈ U} := + h.comp (by fun_prop : Continuous fun t : ℂ => a + t • w).continuousOn fun _ ht => ht + +/-- Translating the parameter of a function with the local submean property. -/ +theorem HasSubmeanAt.comp_add_right {u : ℂ → ℝ} {t₀ : ℂ} + (h : HasSubmeanAt (fun t => u (t + t₀)) 0) : HasSubmeanAt u t₀ := by + filter_upwards [h] with r ⟨hint, hle⟩ + have hmap : ∀ θ : ℝ, circleMap 0 r θ + t₀ = circleMap t₀ r θ := fun θ => by + simp [circleMap, add_comm] + refine ⟨?_, ?_⟩ + · rw [circleIntegrable_def] at hint ⊢ + simpa only [hmap] using hint + · simpa only [zero_add, circleAverage_map_add_const] using hle + +/-- Plurisubharmonicity follows from upper semicontinuity and the local submean property of the +slices through each point of the domain. -/ +theorem plurisubharmonicOn_of_hasSubmeanAt (husc : UpperSemicontinuousOn f U) + (h : ∀ a ∈ U, ∀ w : E, HasSubmeanAt (fun t : ℂ => f (a + t • w)) 0) : + PlurisubharmonicOn f U := by + refine ⟨husc, fun a ha w => ⟨upperSemicontinuousOn_slice husc a w, fun t₀ ht₀ => ?_⟩⟩ + apply HasSubmeanAt.comp_add_right + have := h (a + t₀ • w) ht₀ w + convert this using 2 with t + simp only [add_smul, add_assoc, add_comm (t • w) (t₀ • w)] + +section Algebra + +/-- Constants are plurisubharmonic. -/ +theorem plurisubharmonicOn_const (c : ℝ) (U : Set E) : PlurisubharmonicOn (fun _ => c) U := + ⟨continuousOn_const.upperSemicontinuousOn, fun _ _ _ => subharmonicOn_const c _⟩ + +/-- Sums of plurisubharmonic functions are plurisubharmonic. -/ +theorem PlurisubharmonicOn.add (hf : PlurisubharmonicOn f U) (hg : PlurisubharmonicOn g U) : + PlurisubharmonicOn (fun z => f z + g z) U := + ⟨hf.1.add hg.1, fun a ha w => (hf.2 a ha w).add (hg.2 a ha w)⟩ + +/-- Nonnegative multiples of plurisubharmonic functions are plurisubharmonic. -/ +theorem PlurisubharmonicOn.const_mul {c : ℝ} (hc : 0 ≤ c) (hf : PlurisubharmonicOn f U) : + PlurisubharmonicOn (fun z => c * f z) U := + ⟨(hf.1.const_mul hc), fun a ha w => (hf.2 a ha w).const_mul hc⟩ + +/-- The pointwise maximum of two plurisubharmonic functions is plurisubharmonic. -/ +theorem PlurisubharmonicOn.sup (hf : PlurisubharmonicOn f U) (hg : PlurisubharmonicOn g U) : + PlurisubharmonicOn (fun z => max (f z) (g z)) U := + ⟨hf.1.sup hg.1, fun a ha w => (hf.2 a ha w).sup (hg.2 a ha w)⟩ + +/-- Plurisubharmonicity is preserved by complex affine substitutions. -/ +theorem PlurisubharmonicOn.comp_affine {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + (hf : PlurisubharmonicOn f U) (L : F →L[ℂ] E) (b : E) : + PlurisubharmonicOn (fun z => f (b + L z)) {z | b + L z ∈ U} := by + refine ⟨hf.1.comp (by fun_prop) fun _ hz => hz, fun a ha w => ?_⟩ + have := hf.2 (b + L a) ha (L w) + convert this using 2 with t <;> simp [map_add, map_smul, add_assoc] + +end Algebra + +section Convex + +/-- A continuous function that is convex on an open set of `ℂ` is subharmonic there. -/ +theorem _root_.ConvexOn.subharmonicOn {u : ℂ → ℝ} {W : Set ℂ} (hW : IsOpen W) + (hu : ConvexOn ℝ W u) (hc : ContinuousOn u W) : SubharmonicOn u W := by + refine ⟨hc.upperSemicontinuousOn, fun a ha => ?_⟩ + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hW.mem_nhds ha) + refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ + have hsub : closedBall a r ⊆ W := (closedBall_subset_ball hrρ).trans hball + have hint : CircleIntegrable u a r := + (hc.mono (sphere_subset_closedBall.trans hsub)).circleIntegrable hr.le + have hrefl : ∀ t ∈ sphere a r, 2 * a - t ∈ sphere a r := by + intro t ht + rw [mem_sphere, dist_eq_norm] at ht ⊢ + rw [← ht, ← norm_neg] + congr 1 + ring + have hint' : CircleIntegrable (fun t => u (2 * a - t)) a r := by + refine ContinuousOn.circleIntegrable hr.le ?_ + exact (hc.mono (sphere_subset_closedBall.trans hsub)).comp (by fun_prop) fun t ht => + hrefl t (by simpa [abs_of_pos hr] using ht) + refine ⟨hint, ?_⟩ + have hmid : ∀ t ∈ sphere a r, u a ≤ (1 / 2 : ℝ) • u t + (1 / 2 : ℝ) • u (2 * a - t) := by + intro t ht + have h1 : t ∈ W := hsub (sphere_subset_closedBall ht) + have h2 : 2 * a - t ∈ W := hsub (sphere_subset_closedBall (hrefl t ht)) + have := hu.2 h1 h2 (by norm_num : (0 : ℝ) ≤ 1 / 2) (by norm_num : (0 : ℝ) ≤ 1 / 2) (by norm_num) + convert this using 2 + simp only [Complex.real_smul] + push_cast + ring + have hi₁ : CircleIntegrable (fun t => (1 / 2 : ℝ) • u t) a r := hint.const_smul + have hi₂ : CircleIntegrable (fun t => (1 / 2 : ℝ) • u (2 * a - t)) a r := hint'.const_smul + have hle := circleAverage_mono (circleIntegrable_const (u a) a r) (hi₁.add hi₂) + (fun t ht => hmid t (by simpa [abs_of_pos hr] using ht)) + rw [circleAverage_const, circleAverage_add hi₁ hi₂, circleAverage_fun_smul, + circleAverage_fun_smul, Real.circleAverage_reflect] at hle + simp only [smul_eq_mul] at hle + linarith + +/-- A real convex combination of two points of a complex line, in line coordinates. -/ +private theorem line_combo (a w : E) (s t : ℂ) {α β : ℝ} (hαβ : α + β = 1) : + a + (α • s + β • t) • w = α • (a + s • w) + β • (a + t • w) := by + have ha : a = α • a + β • a := by rw [← add_smul, hαβ, one_smul] + conv_lhs => rw [ha] + simp only [smul_add, add_smul, Complex.real_smul, mul_smul, Complex.coe_smul] + abel + +/-- A continuous convex function on an open set is plurisubharmonic. -/ +theorem _root_.ConvexOn.plurisubharmonicOn (hU : IsOpen U) (hf : ConvexOn ℝ U f) + (hc : ContinuousOn f U) : PlurisubharmonicOn f U := by + refine ⟨hc.upperSemicontinuousOn, fun a ha w => ?_⟩ + apply ConvexOn.subharmonicOn (hU.preimage (by fun_prop : Continuous fun t : ℂ => a + t • w)) + · refine ⟨fun s hs t ht α β hα hβ hαβ => ?_, fun s hs t ht α β hα hβ hαβ => ?_⟩ + · show a + (α • s + β • t) • w ∈ U + rw [line_combo a w s t hαβ] + exact hf.1 hs ht hα hβ hαβ + · have := hf.2 hs ht hα hβ hαβ + simpa only [line_combo a w s t hαβ] using this + · exact hc.comp (by fun_prop : Continuous fun t : ℂ => a + t • w).continuousOn fun _ ht => ht + +/-- The norm is plurisubharmonic. -/ +theorem plurisubharmonicOn_norm : PlurisubharmonicOn (fun z : E => ‖z‖) univ := + ConvexOn.plurisubharmonicOn isOpen_univ (convexOn_norm convex_univ) + continuous_norm.continuousOn + +end Convex + +section Holomorphic + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- The slice of a holomorphic map along a complex line is holomorphic. -/ +theorem analyticOnNhd_slice {h : E → F} (hh : AnalyticOnNhd ℂ h U) (a w : E) : + AnalyticOnNhd ℂ (fun t : ℂ => h (a + t • w)) {t | a + t • w ∈ U} := fun _ ht => + (hh _ ht).comp_of_eq (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) rfl + +/-- Real parts of holomorphic functions are plurisubharmonic. -/ +theorem _root_.AnalyticOnNhd.plurisubharmonicOn_re {h : E → ℂ} (hh : AnalyticOnNhd ℂ h U) : + PlurisubharmonicOn (fun z => (h z).re) U := + ⟨(Complex.continuous_re.comp_continuousOn hh.continuousOn).upperSemicontinuousOn, + fun a _ w => AnalyticOnNhd.subharmonicOn_re (analyticOnNhd_slice hh a w)⟩ + +/-- Positive powers of the norm of a holomorphic map are plurisubharmonic. -/ +theorem _root_.AnalyticOnNhd.plurisubharmonicOn_norm_rpow (hU : IsOpen U) {h : E → F} {p : ℝ} + (hp : 0 < p) (hh : AnalyticOnNhd ℂ h U) : PlurisubharmonicOn (fun z => ‖h z‖ ^ p) U := + ⟨(hh.continuousOn.norm.rpow_const fun _ _ => Or.inr hp.le).upperSemicontinuousOn, + fun a _ w => AnalyticOnNhd.subharmonicOn_norm_rpow + (hU.preimage (by fun_prop : Continuous fun t : ℂ => a + t • w)) hp + (analyticOnNhd_slice hh a w)⟩ + +/-- The logarithm of the modulus of a nonvanishing holomorphic function is plurisubharmonic. -/ +theorem _root_.AnalyticOnNhd.plurisubharmonicOn_log_norm (hU : IsOpen U) {h : E → ℂ} + (hh : AnalyticOnNhd ℂ h U) (hne : ∀ z ∈ U, h z ≠ 0) : + PlurisubharmonicOn (fun z => Real.log ‖h z‖) U := + ⟨(ContinuousOn.log hh.continuousOn.norm fun z hz => + norm_ne_zero_iff.mpr (hne z hz)).upperSemicontinuousOn, + fun a _ w => AnalyticOnNhd.subharmonicOn_log_norm + (hU.preimage (by fun_prop : Continuous fun t : ℂ => a + t • w)) + (analyticOnNhd_slice hh a w) fun _ ht => hne _ ht⟩ + +end Holomorphic + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polydisc.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polydisc.lean new file mode 100644 index 0000000000..b5299517d1 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polydisc.lean @@ -0,0 +1,232 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.CauchyIntegral +public import Mathlib.MeasureTheory.Integral.TorusIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt + +/-! +# Polydiscs and distinguished boundaries + +Geometry for the polydisc Cauchy formula. Equal-radius polydiscs use the supremum norm; these +are not Euclidean balls. Origin-centred open and closed polydiscs are complete Reinhardt sets. +Containment of the closed polydisc determined by each point's moduli characterizes the complete +Reinhardt property. + +## Notation + +`polydisc c r` and `closedPolydisc c r` are products of coordinate balls of radii `r i`. The +definitions and their elementary topology allow any family of pseudo-metric spaces as factors; the +Reinhardt and torus statements are specific to `ℂ`. The equal-radius case `r = fun _ => R` coincides +with the sup-norm ball; see `polydisc_const_eq_ball` and `closedPolydisc_eq_closedBall`. The +distinguished boundary is parametrized by `torusMap`. + +## Main results + +`isCompleteReinhardt_iff_closedPolydisc_subset` characterizes complete Reinhardt sets. +`polydisc_const_eq_ball` identifies equal positive radii with the open sup-norm ball. +`closure_polydisc` identifies the closure of a positive-radius open polydisc with the +corresponding closed polydisc. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped ENNReal NNReal Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-! +### Closed polydiscs +-/ + +/-- An open polydisc with a separate radius in each coordinate: the product of the open balls +`ball (c i) (r i)`. The factors may be any pseudo-metric spaces; the several-complex-variables +theory uses `X i = ℂ`. -/ +@[expose] def polydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + (c : ∀ i, X i) (r : ι → ℝ) : Set (∀ i, X i) := + Set.pi univ fun i => ball (c i) (r i) + +/-- A closed polydisc with a separate radius in each coordinate: the product of the closed balls +`closedBall (c i) (r i)`. -/ +@[expose] def closedPolydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + (c : ∀ i, X i) (r : ι → ℝ) : Set (∀ i, X i) := + Set.pi univ fun i => closedBall (c i) (r i) + +/-- Membership in a polydisc is a coordinatewise strict distance bound. -/ +@[simp] lemma mem_polydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + {c z : ∀ i, X i} {r : ι → ℝ} : + z ∈ polydisc c r ↔ ∀ i, dist (z i) (c i) < r i := by + simp [polydisc, mem_ball] + +/-- Membership in a closed polydisc is a coordinatewise non-strict distance bound. -/ +@[simp] lemma mem_closedPolydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + {c z : ∀ i, X i} {r : ι → ℝ} : + z ∈ closedPolydisc c r ↔ ∀ i, dist (z i) (c i) ≤ r i := by + simp [closedPolydisc, mem_closedBall] + +/-- Every origin-centred open polydisc is complete Reinhardt, even with nonpositive radii. -/ +theorem isCompleteReinhardt_polydisc {ι : Type*} (r : ι → ℝ) : + IsCompleteReinhardt (polydisc (0 : ι → ℂ) r) := by + intro z hz w hw + simp only [mem_polydisc, Pi.zero_apply, dist_zero_right] at hz ⊢ + exact fun i => (hw i).trans_lt (hz i) + +/-- Every origin-centred closed polydisc is complete Reinhardt, including degenerate ones. -/ +theorem isCompleteReinhardt_closedPolydisc {ι : Type*} (r : ι → ℝ) : + IsCompleteReinhardt (closedPolydisc (0 : ι → ℂ) r) := by + intro z hz w hw + simp only [mem_closedPolydisc, Pi.zero_apply, dist_zero_right] at hz ⊢ + exact fun i => (hw i).trans (hz i) + +/-- Completeness means containing the closed polydisc determined by each point's moduli. -/ +theorem isCompleteReinhardt_iff_closedPolydisc_subset {ι : Type*} + {U : Set (ι → ℂ)} : + IsCompleteReinhardt U ↔ + ∀ z ∈ U, closedPolydisc 0 (fun i => ‖z i‖) ⊆ U := by + simp only [IsCompleteReinhardt, Set.subset_def, mem_closedPolydisc, + Pi.zero_apply, dist_zero_right] + +/-- An origin-centred open polydisc has independent coordinate rotation symmetry. -/ +theorem isReinhardt_polydisc {ι : Type*} (r : ι → ℝ) : + IsReinhardt (polydisc (0 : ι → ℂ) r) := + (isCompleteReinhardt_polydisc r).isReinhardt + +/-- An origin-centred closed polydisc has independent coordinate rotation symmetry. -/ +theorem isReinhardt_closedPolydisc {ι : Type*} (r : ι → ℝ) : + IsReinhardt (closedPolydisc (0 : ι → ℂ) r) := + (isCompleteReinhardt_closedPolydisc r).isReinhardt + +/-- Open origin-centred polydiscs are logarithmically convex, with arbitrary real radii. -/ +theorem isLogarithmicallyConvex_polydisc {ι : Type*} (r : ι → ℝ) : + IsLogarithmicallyConvex (polydisc (0 : ι → ℂ) r) := by + intro x hx y hy a b ha hb hab + simp only [logarithmicImage, Set.mem_ofPred_eq, mem_polydisc, + Pi.zero_apply, dist_zero_right] at hx hy ⊢ + intro i + have h := (convexOn_exp.convex_lt (r i)) + ⟨Set.mem_univ _, by simpa using hx i⟩ ⟨Set.mem_univ _, by simpa using hy i⟩ ha hb hab + simpa only [Pi.add_apply, Pi.smul_apply, smul_eq_mul, + Complex.norm_of_nonneg (Real.exp_nonneg _)] using h.2 + +/-- Closed origin-centred polydiscs are logarithmically convex, including degenerate ones. -/ +theorem isLogarithmicallyConvex_closedPolydisc {ι : Type*} (r : ι → ℝ) : + IsLogarithmicallyConvex (closedPolydisc (0 : ι → ℂ) r) := by + intro x hx y hy a b ha hb hab + simp only [logarithmicImage, Set.mem_ofPred_eq, mem_closedPolydisc, + Pi.zero_apply, dist_zero_right] at hx hy ⊢ + intro i + have h := (convexOn_exp.convex_le (r i)) + ⟨Set.mem_univ _, by simpa using hx i⟩ ⟨Set.mem_univ _, by simpa using hy i⟩ ha hb hab + simpa only [Pi.add_apply, Pi.smul_apply, smul_eq_mul, + Complex.norm_of_nonneg (Real.exp_nonneg _)] using h.2 + +/-- A finite-dimensional polydisc is open. -/ +theorem isOpen_polydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + [Finite ι] (c : ∀ i, X i) (r : ι → ℝ) : + IsOpen (polydisc c r) := by + change IsOpen (Set.pi univ fun i => ball (c i) (r i)) + exact isOpen_set_pi finite_univ (fun _ _ => isOpen_ball) + +/-- A closed polydisc in a product of proper spaces is compact, by the product compactness +theorem. -/ +theorem isCompact_closedPolydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + [∀ i, ProperSpace (X i)] (c : ∀ i, X i) (r : ι → ℝ) : + IsCompact (closedPolydisc c r) := + isCompact_univ_pi fun i => isCompact_closedBall (c i) (r i) + +/-- The closure of a positive-radius polydisc is the corresponding closed polydisc. -/ +theorem closure_polydisc {ι : Type*} (c : ι → ℂ) {r : ι → ℝ} + (hr : ∀ i, 0 < r i) : + closure (polydisc c r) = closedPolydisc c r := by + simp only [polydisc, closedPolydisc, closure_pi_set, + closure_ball _ (ne_of_gt (hr _))] + +/-- In finite coordinates, equal positive radii give the open ball for the supremum norm. -/ +theorem polydisc_const_eq_ball {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + [Fintype ι] (c : ∀ i, X i) {R : ℝ} (hR : 0 < R) : polydisc c (fun _ => R) = ball c R := + (ball_pi c hR).symm + +/-- Enlarging every radius enlarges the polydisc. -/ +theorem polydisc_mono {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + (c : ∀ i, X i) {r s : ι → ℝ} (hrs : ∀ i, r i ≤ s i) : polydisc c r ⊆ polydisc c s := by + intro z hz + exact mem_polydisc.mpr fun i => (mem_polydisc.mp hz i).trans_le (hrs i) + +/-- Strictly smaller closed coordinate discs lie in the larger open polydisc. -/ +theorem closedPolydisc_subset_polydisc {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + (c : ∀ i, X i) {r s : ι → ℝ} (hrs : ∀ i, r i < s i) : + closedPolydisc c r ⊆ polydisc c s := by + intro z hz + exact mem_polydisc.mpr fun i => (mem_closedPolydisc.mp hz i).trans_lt (hrs i) + +/-- The torus parametrization with separate coordinate radii is continuous. -/ +theorem continuous_torusMap {n : ℕ} (c : Fin n → ℂ) (r : Fin n → ℝ) : + Continuous (torusMap c r) := by + apply continuous_pi + intro i + simp only [torusMap] + fun_prop + +/-- Each torus coordinate has the prescribed nonnegative radius. -/ +theorem norm_torusMap_sub {n : ℕ} {c : Fin n → ℂ} {r : Fin n → ℝ} + (hr : ∀ i, 0 ≤ r i) (θ : Fin n → ℝ) (i : Fin n) : + ‖torusMap c r θ i - c i‖ = r i := by + simp [torusMap, abs_of_nonneg (hr i)] + +/-- A torus with nonnegative radii belongs to its closed polydisc. -/ +theorem torusMap_mem_closedPolydisc {n : ℕ} {c : Fin n → ℂ} {r : Fin n → ℝ} + (hr : ∀ i, 0 ≤ r i) (θ : Fin n → ℝ) : + torusMap c r θ ∈ closedPolydisc c r := by + exact mem_closedPolydisc.mpr fun i => by + rw [dist_eq_norm, norm_torusMap_sub hr] + +/-- A Cauchy kernel has no pole on a coordinate circle when evaluated inside the polydisc. -/ +theorem torusMap_apply_ne_of_norm_sub_lt {n : ℕ} {c w : Fin n → ℂ} + {r : Fin n → ℝ} {θ : Fin n → ℝ} {i : Fin n} + (hr : ∀ i, 0 < r i) (hw : ‖w i - c i‖ < r i) : torusMap c r θ i ≠ w i := by + intro h + have H := norm_torusMap_sub (c := c) (fun j => (hr j).le) θ i + rw [h] at H + exact hw.ne H + +/-- Membership of a coordinate and the tail gives membership of the full polydisc. -/ +theorem cons_mem_closedPolydisc {n : ℕ} {c : Fin (n + 1) → ℂ} + {r : Fin (n + 1) → ℝ} {x : ℂ} {y : Fin n → ℂ} + (hx : x ∈ closedBall (c 0) (r 0)) + (hy : y ∈ closedPolydisc (c ∘ Fin.succ) (r ∘ Fin.succ)) : + Fin.cons x y ∈ closedPolydisc c r := by + intro i _ + refine Fin.cases ?_ ?_ i + · simpa using hx + · intro j + simpa using hy j (mem_univ _) + +/-- An equal-radius closed polydisc is the closed ball for the supremum norm. -/ +theorem closedPolydisc_eq_closedBall {ι : Type*} {X : ι → Type*} [∀ i, PseudoMetricSpace (X i)] + [Fintype ι] {c : ∀ i, X i} {R : ℝ} (hR : 0 ≤ R) : + closedPolydisc c (fun _ => R) = closedBall c R := + (closedBall_pi c hR).symm + +/-- The standard equal-radius torus parametrization is continuous. -/ +theorem continuous_torusMap_const {n : ℕ} (c : Fin n → ℂ) (R : ℝ) : + Continuous (torusMap c (fun _ => R)) := + continuous_pi fun i => by + simp only [torusMap] + fun_prop + +/-- No natural-number power of `2 * π * I` vanishes. -/ +theorem _root_.Complex.two_pi_I_pow_ne_zero (n : ℕ) : ((2 * π * I : ℂ) ^ n) ≠ 0 := + pow_ne_zero _ two_pi_I_ne_zero + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscMeanValue.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscMeanValue.lean new file mode 100644 index 0000000000..a866b0a28e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscMeanValue.lean @@ -0,0 +1,186 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.MeanValue +public import Mathlib.MeasureTheory.Constructions.Pi +public import Mathlib.MeasureTheory.Integral.Prod +public import Mathlib.MeasureTheory.Measure.Haar.InnerProductSpace +public import Mathlib.MeasureTheory.Measure.Lebesgue.Complex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral + +/-! +# Torus and volume mean values on polydiscs + +The fixed-radius torus average of a holomorphic function equals its value at the center, for +every valid radius. This is the plain Bochner-integral average, with no residual Jacobian +factor: the complex contour normalization in `torusIntegral` cancels exactly at the center. +Averaging common complex rotations and applying Fubini also gives the volume mean-value formula +on equal-radius polydiscs. This formula supports the local `Lp` estimate on holomorphic function +spaces. Arbitrary finite coordinate types, including the empty type, are allowed in the volume +formula. + +## Main results + +* `torusAverage_eq_center`: At the center of a polydisc, the fixed-radius torus average is a plain + Bochner-integral average of the function over the angle cube, with no Jacobian residue. +* `integral_closedBall_zero_eq_volume_smul`: Averaging a holomorphic function over an equal-radius + polydisc centered at zero returns its center value times the volume. +* `integral_closedBall_eq_volume_smul`: The volume mean-value formula on an equal-radius polydisc + with arbitrary center. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped ENNReal NNReal Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-- At the center of a polydisc, the fixed-radius torus average is a plain Bochner-integral average +of the function over the angle cube, with no Jacobian residue. -/ +theorem torusAverage_eq_center {d : ℕ} {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R : Fin d → ℝ} + (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + ∫ θ in Set.Icc (0 : Fin d → ℝ) (fun _ => 2 * π), f (torusMap c R θ) = + (2 * π : ℂ) ^ d • f c := by + have hw : ∀ i, ‖c i - c i‖ < R i := fun i => by simpa using hR i + have hkey := two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul hR hw hfc hfa + rw [torusIntegral] at hkey + have hkernel : Set.EqOn + (fun θ : Fin d → ℝ => (∏ i, (R i : ℂ) * Complex.exp ((θ i : ℂ) * I) * I) • + ((∏ i, (torusMap c R θ i - c i)⁻¹) • f (torusMap c R θ))) + (fun θ : Fin d → ℝ => (I : ℂ) ^ d • f (torusMap c R θ)) + (Set.Icc (0 : Fin d → ℝ) fun _ => 2 * π) := by + intro θ _ + simp only + rw [smul_smul] + congr 1 + rw [← Finset.prod_mul_distrib] + rw [show (I : ℂ) ^ d = ∏ _i : Fin d, I by simp] + apply Finset.prod_congr rfl + intro i _ + have hRi : (R i : ℂ) ≠ 0 := Complex.ofReal_ne_zero.mpr (hR i).ne' + have hzc : torusMap c R θ i - c i = R i * Complex.exp ((θ i : ℂ) * I) := by + simp [torusMap] + rw [hzc] + have hexp : Complex.exp ((θ i : ℂ) * I) ≠ 0 := Complex.exp_ne_zero _ + field_simp + rw [MeasureTheory.setIntegral_congr_fun measurableSet_Icc hkernel, + MeasureTheory.integral_smul] at hkey + have hI : ((2 * π * I : ℂ) ^ d)⁻¹ • ((I : ℂ) ^ d • + ∫ θ in Set.Icc (0 : Fin d → ℝ) fun _ => 2 * π, f (torusMap c R θ)) = f c := hkey + have hIpow : ((2 * π * I : ℂ) ^ d)⁻¹ * (I : ℂ) ^ d = ((2 * π : ℂ) ^ d)⁻¹ := by + rw [mul_pow] + field_simp + rw [smul_smul, hIpow] at hI + have h2π : ((2 * π : ℂ) ^ d) ≠ 0 := by + apply pow_ne_zero + exact_mod_cast (by positivity : (2 * π : ℝ) ≠ 0) + have := congrArg (fun x => (2 * π : ℂ) ^ d • x) hI + simpa [smul_smul, h2π] using this + +omit [CompleteSpace E] in +/-- A common unit complex rotation preserves integration over a centered polydisc. -/ +private theorem integral_closedBall_smul {ι : Type*} [Fintype ι] + (f : (ι → ℂ) → E) (r : ℝ) {w : ℂ} (hw : ‖w‖ = 1) : + ∫ z in closedBall (0 : ι → ℂ) r, f (w • z) = + ∫ z in closedBall (0 : ι → ℂ) r, f z := by + have hw0 : w ≠ 0 := by intro h; simp [h] at hw + let e : ℂ ≃ₗᵢ[ℝ] ℂ := + { (LinearEquiv.smulOfNeZero ℂ ℂ w hw0).restrictScalars ℝ with + norm_map' := fun z => by simp [LinearEquiv.smulOfNeZero_apply, hw] } + let ePi := MeasurableEquiv.piCongrRight (fun _ : ι => e.toMeasurableEquiv) + have hm : MeasurePreserving (fun z : ι → ℂ => w • z) volume volume := + volume_preserving_pi (fun _ : ι => e.measurePreserving) + have hpre : (fun z : ι → ℂ => w • z) ⁻¹' closedBall 0 r = closedBall 0 r := by + ext z + simp [mem_closedBall, dist_zero_right, norm_smul, hw] + simpa only [hpre] using + hm.setIntegral_preimage_emb ePi.measurableEmbedding f (closedBall 0 r) + +/-- Averaging a holomorphic function over an equal-radius polydisc centered at zero returns its +center value times the volume. The proof averages common complex rotations and uses Fubini; it +also applies when the coordinate type is empty. -/ +theorem integral_closedBall_zero_eq_volume_smul {ι : Type*} [Fintype ι] + {f : (ι → ℂ) → E} {r : ℝ} + (hf : AnalyticOnNhd ℂ f (closedBall 0 r)) : + ∫ z in closedBall (0 : ι → ℂ) r, f z = + volume.real (closedBall (0 : ι → ℂ) r) • f 0 := by + let B := closedBall (0 : ι → ℂ) r + let T := Icc (0 : ℝ) (2 * π) + let H := fun (z : ι → ℂ) (θ : ℝ) => f (circleMap 0 1 θ • z) + have hrot (θ : ℝ) : ‖circleMap 0 1 θ‖ = 1 := by simp + have hmap : MapsTo (fun p : (ι → ℂ) × ℝ => circleMap 0 1 p.2 • p.1) (B ×ˢ T) B := by + intro p hp + simpa only [B, mem_closedBall, dist_zero_right, norm_smul, hrot, one_mul] using hp.1 + have hcont : ContinuousOn (Function.uncurry H) (B ×ˢ T) := + hf.continuousOn.comp (by fun_prop) hmap + have hint : Integrable (Function.uncurry H) + ((volume.restrict B).prod (volume.restrict T)) := by + rw [Measure.prod_restrict, ← Measure.volume_eq_prod] + exact hcont.integrableOn_compact ((isCompact_closedBall _ _).prod isCompact_Icc) + have hmean (z : ι → ℂ) (hz : z ∈ B) : + ∫ θ in T, H z θ = (2 * π) • f 0 := by + have hline : DifferentiableOn ℂ (fun w : ℂ => f (w • z)) (closedBall 0 1) := by + intro w hw + have hwz : w • z ∈ closedBall (0 : ι → ℂ) r := by + rw [mem_closedBall, dist_zero_right, norm_smul] + exact (mul_le_mul_of_nonneg_right (mem_closedBall_zero_iff.mp hw) (norm_nonneg z)).trans + (by simpa [B] using hz) + have hmap : AnalyticAt ℂ (fun t : ℂ => t • z) w := + analyticAt_id.smul analyticAt_const + exact ((hf _ hwz).comp_of_eq hmap rfl).differentiableWithinAt + have hline' : DifferentiableOn ℂ (fun w : ℂ => f (w • z)) + (closure (ball 0 |(1 : ℝ)|)) := by + simpa only [abs_one, closure_ball _ one_ne_zero] using hline + have h := hline'.diffContOnCl.circleAverage + simp only [Real.circleAverage, zero_smul] at h + rw [intervalIntegral.integral_of_le Real.two_pi_pos.le, ← integral_Icc_eq_integral_Ioc] at h + have he := congrArg (fun v : E => (2 * π) • v) h + simpa only [smul_smul, mul_inv_cancel₀ Real.two_pi_pos.ne', one_smul] using he + have hswap := integral_integral_swap hint + have hleft : (∫ z in B, ∫ θ in T, H z θ) = + (2 * π) • (volume.real B • f 0) := by + rw [setIntegral_congr_fun measurableSet_closedBall hmean, integral_const] + simp only [Measure.real, Measure.restrict_apply_univ] + exact smul_comm _ _ _ + have hright : (∫ θ in T, ∫ z in B, H z θ) = + (2 * π) • (∫ z in B, f z) := by + simp_rw [H, B, integral_closedBall_smul f r (hrot _)] + simp [T, integral_const, Real.volume_Icc, Measure.real, ENNReal.toReal_ofReal Real.pi_pos.le] + rw [hleft, hright] at hswap + exact (smul_right_injective E Real.two_pi_pos.ne' hswap).symm + +/-- The volume mean-value formula on an equal-radius polydisc with arbitrary center. The norm on the +finite coordinate space is the supremum norm. -/ +theorem integral_closedBall_eq_volume_smul {ι : Type*} [Fintype ι] + {f : (ι → ℂ) → E} {c : ι → ℂ} {r : ℝ} + (hf : AnalyticOnNhd ℂ f (closedBall c r)) : + ∫ z in closedBall c r, f z = volume.real (closedBall c r) • f c := by + have hpre : (fun z : ι → ℂ => c + z) ⁻¹' closedBall c r = closedBall 0 r := by + ext z + simp [mem_closedBall, dist_eq_norm] + have hvol : volume (closedBall (0 : ι → ℂ) r) = volume (closedBall c r) := by + rw [← hpre] + exact measure_preimage_add volume c _ + have hm := (measurePreserving_add_left (volume : Measure (ι → ℂ)) c).setIntegral_preimage_emb + (Homeomorph.addLeft c).isClosedEmbedding.measurableEmbedding f (closedBall c r) + rw [hpre] at hm + have htrans : AnalyticOnNhd ℂ (fun z => f (c + z)) (closedBall (0 : ι → ℂ) r) := by + intro z hz + have hcz : c + z ∈ closedBall c r := by simpa [mem_closedBall, dist_eq_norm] using hz + exact (hf _ hcz).comp (analyticAt_const.add analyticAt_id) + rw [← hm, integral_closedBall_zero_eq_volume_smul htrans, Measure.real, hvol, add_zero] + rfl + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscTaylor.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscTaylor.lean new file mode 100644 index 0000000000..62c7df94b9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolydiscTaylor.lean @@ -0,0 +1,334 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.RingTheory.MvPowerSeries.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform + +/-! +# Taylor expansions on polydiscs with separate radii + +The multi-index Cauchy series converges throughout its open polydisc, not merely on the largest +inscribed equal-radius ball. Convergence is uniform on smaller closed polydiscs and locally +uniform on the full open polydisc, also after mixed differentiation. Explicit geometric-tail +estimates control the remainder after any finite set of multi-indices. Scalar Taylor +coefficients also define an element of Mathlib's `MvPowerSeries`. + +## Main definitions + +* `holomorphicTaylorSeries`: The Taylor series of a Banach-valued function as a Mathlib multivariate + formal power series: the normalized mixed derivatives at the center. + +## Main results + +* `hasSum_polydiscTaylor`: The full multi-index Taylor expansion on a polydisc with separate radii. +* `hasSumLocallyUniformlyOn_polydiscTaylor`: The multi-index Taylor expansion converges locally + uniformly throughout its polydisc. +* `norm_polydiscTaylor_remainder_le`: A uniform remainder bound for any finite Taylor polynomial. +* `hasSumLocallyUniformlyOn_iteratedPartialDeriv_polydiscTaylor`: Any mixed derivative of the + separate-radius Taylor expansion is obtained by termwise differentiation, with locally uniform + convergence on the full open polydisc. +-/ + +public noncomputable section + +open Complex Filter Function MeasureTheory Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {d : ℕ} {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [CompleteSpace E] + +/-- The Taylor series of a Banach-valued function as a Mathlib multivariate formal power series: the +normalized mixed derivatives at the center. -/ +@[expose] def holomorphicTaylorSeries (f : (Fin d → ℂ) → E) (c : Fin d → ℂ) : MvPowerSeries + (Fin d) E := + fun m => (∏ i, (m i).factorial : ℂ)⁻¹ • multiIndexDeriv m f c + +/-- Formal Taylor coefficients coincide with the integral Cauchy coefficients. -/ +theorem coeff_holomorphicTaylorSeries {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} + {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) (m : Fin d →₀ ℕ) : + holomorphicTaylorSeries f c m = polydiscCauchyCoeffWithRadii f c R m := by + exact (polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hR hfc hfa m).symm + +/-- The ungrouped multi-index geometric expansion of the Cauchy kernel. -/ +theorem hasSum_multiIndex_cauchyKernel {z c h : Fin d → ℂ} + (hz : ∀ i, z i ≠ c i) (hh : ∀ i, ‖h i‖ < ‖z i - c i‖) : + HasSum (fun m : Fin d → ℕ => (∏ i, h i ^ m i) * cauchyKernel m c z) + (∏ i, (z i - (c + h) i)⁻¹) := by + have hx : ∀ i, ‖h i / (z i - c i)‖ < 1 := by + intro i + rw [norm_div, div_lt_one (norm_pos_iff.mpr (sub_ne_zero.mpr (hz i)))] + exact hh i + have hs := (hasSum_pi_geometric (fun i => h i / (z i - c i)) hx).mul_right + (∏ i, (z i - c i)⁻¹) + have hterm (m : Fin d → ℕ) : (∏ i, h i ^ m i) * cauchyKernel m c z = + (∏ i, (h i / (z i - c i)) ^ m i) * ∏ i, (z i - c i)⁻¹ := by + rw [cauchyKernel, ← Finset.prod_mul_distrib, ← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i hi + rw [pow_succ, div_pow, inv_pow] + field_simp [sub_ne_zero.mpr (hz i)] + have hconst : (∏ i, (z i - (c + h) i)⁻¹) = + (∏ i, (1 - h i / (z i - c i))⁻¹) * ∏ i, (z i - c i)⁻¹ := by + rw [← Finset.prod_mul_distrib] + apply Finset.prod_congr rfl + intro i hi + have hzi : z i - c i ≠ 0 := sub_ne_zero.mpr (hz i) + have hzih : z i - (c + h) i ≠ 0 := by + intro heq + have he : z i - c i = h i := by + have H := sub_eq_zero.mp heq + simp only [Pi.add_apply] at H + linear_combination H + exact (hh i).ne (congrArg norm he.symm) + simp only [Pi.add_apply] + field_simp [hzi, hzih] + ring + simpa only [hterm, hconst] using hs + +omit [CompleteSpace E] in +/-- Every higher Cauchy kernel times a continuous function is integrable on its contour. -/ +theorem torusIntegrable_cauchyKernel_multi {f : (Fin d → ℂ) → E} + {c w : Fin d → ℂ} {R : Fin d → ℝ} (hR : ∀ i, 0 < R i) + (hw : w ∈ polydisc c R) + (hfc : ContinuousOn f (closedPolydisc c R)) (m : Fin d → ℕ) : + TorusIntegrable (fun z => cauchyKernel m w z • f z) c R := by + have hfθ : ContinuousOn (fun θ => f (torusMap c R θ)) + (Icc (0 : Fin d → ℝ) (fun _ => 2 * π)) := + hfc.comp (continuous_torusMap c R).continuousOn + (fun θ _ => torusMap_mem_closedPolydisc (fun i => (hR i).le) θ) + have hk : ContinuousOn (fun θ => cauchyKernel m w (torusMap c R θ)) + (Icc (0 : Fin d → ℝ) (fun _ => 2 * π)) := by + apply continuousOn_finsetProd + intro i hi + apply ContinuousOn.pow + refine (((continuous_apply i).comp (continuous_torusMap c R)).continuousOn.sub + continuousOn_const).inv₀ (fun θ hθ => ?_) + exact sub_ne_zero.mpr (torusMap_apply_ne_of_norm_sub_lt hR + (by simpa [dist_eq_norm] using mem_polydisc.mp hw i)) + exact (hk.smul hfθ).integrableOn_compact isCompact_Icc + +omit [CompleteSpace E] in +/-- Bound for the Cauchy–Taylor integrand on the distinguished boundary. -/ +private theorem norm_cauchyTaylor_integrand_le {f : (Fin d → ℂ) → E} + {c h : Fin d → ℂ} {R : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) + (m : Fin d → ℕ) (θ : Fin d → ℝ) : + ‖(∏ i, h i ^ m i) • cauchyKernel m c (torusMap c R θ) • f (torusMap c R θ)‖ ≤ + (M * ∏ i, (R i)⁻¹) * ∏ i, (‖h i‖ / R i) ^ m i := by + calc + _ = (∏ i, ‖h i‖ ^ m i) * (∏ i, (R i)⁻¹ ^ (m i + 1)) * ‖f (torusMap c R θ)‖ := by + simp only [norm_smul, cauchyKernel, norm_prod, norm_pow, norm_inv, + norm_torusMap_sub (fun i => (hR i).le), mul_assoc] + _ ≤ (∏ i, ‖h i‖ ^ m i) * (∏ i, (R i)⁻¹ ^ (m i + 1)) * M := + mul_le_mul_of_nonneg_left + (hM _ (torusMap_mem_closedPolydisc (fun i => (hR i).le) θ)) + (mul_nonneg (Finset.prod_nonneg fun i _ => pow_nonneg (norm_nonneg _) _) + (Finset.prod_nonneg fun i _ => pow_nonneg (inv_nonneg.mpr (hR i).le) _)) + _ = _ := by + simp only [div_eq_mul_inv, mul_pow, pow_succ, Finset.prod_mul_distrib] + ring + +/-- The full multi-index Taylor expansion on a polydisc with separate radii. The sum is indexed by +all multi-indices, and therefore does not depend on a summation order. -/ +theorem hasSum_polydiscTaylor {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} + {R : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) (hh : ∀ i, ‖h i‖ < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) : + HasSum (fun m : Fin d → ℕ => (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m) + (f (c + h)) := by + let T (m : Fin d → ℕ) (z : Fin d → ℂ) := (∏ i, h i ^ m i) • cauchyKernel m c z • f z + let a (m : Fin d → ℕ) := (M * ∏ i, (R i)⁻¹) * ∏ i, (‖h i‖ / R i) ^ m i + have hq : ∀ i, ‖‖h i‖ / R i‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (norm_nonneg _) (hR i).le), div_lt_one (hR i)] + exact hh i + have ha : Summable a := (hasSum_pi_geometric (fun i => ‖h i‖ / R i) hq).summable.mul_left _ + have hc : c ∈ polydisc c R := mem_polydisc.mpr (by simpa using hR) + have hTi (m : Fin d → ℕ) : TorusIntegrable (T m) c R := + (torusIntegrable_cauchyKernel_multi hR hc hfc m).smul (∏ i, h i ^ m i) + have hs := hasSum_torusIntegral_of_uniform (g := fun z => (∏ i, (z i - (c + h) i)⁻¹) • f z) + ha hTi (fun m θ => norm_cauchyTaylor_integrand_le hR hM m θ) (fun θ => by + have hz : ∀ i, torusMap c R θ i ≠ c i := by + intro i hi + have H := norm_torusMap_sub (c := c) (fun i => (hR i).le) θ i + rw [hi, sub_self, norm_zero] at H + exact (hR i).ne' H.symm + have H := hasSum_multiIndex_cauchyKernel (h := h) hz (fun i => by + rw [norm_torusMap_sub (fun i => (hR i).le)]; exact hh i) + simpa only [T, smul_smul, smul_eq_mul] using H.smul_const (f (torusMap c R θ))) + have hn := hs.const_smul (((2 * π * I : ℂ) ^ d)⁻¹) + have hterm (m : Fin d → ℕ) : (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m = + (((2 * π * I : ℂ) ^ d)⁻¹) • torusIntegral (T m) c R := by + dsimp only [polydiscCauchyCoeffWithRadii, polydiscCauchyTransform, T] + rw [torusIntegral_smul] + exact smul_comm _ _ _ + rw [two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul hR (fun i => by simpa using hh i) hfc + hfa] at hn + simpa only [hterm] using hn + +omit [CompleteSpace E] in +/-- A summable geometric majorant for individual Taylor terms on a smaller closed polydisc. -/ +theorem norm_polydiscTaylor_term_le {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} + {R s : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) (hM0 : 0 ≤ M) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) + (hh : ∀ i, ‖h i‖ ≤ s i) (m : Fin d → ℕ) : + ‖(∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m‖ ≤ + M * ∏ i, (s i / R i) ^ m i := by + calc + _ ≤ (∏ i, ‖h i‖ ^ m i) * (M * ∏ i, (R i)⁻¹ ^ m i) := by + rw [norm_smul, norm_prod] + simp only [norm_pow] + exact mul_le_mul_of_nonneg_left (norm_polydiscCauchyCoeffWithRadii_le hR hM m) + (Finset.prod_nonneg fun i _ => pow_nonneg (norm_nonneg _) _) + _ = M * ∏ i, (‖h i‖ / R i) ^ m i := by + simp only [div_eq_mul_inv, mul_pow, Finset.prod_mul_distrib] + ring + _ ≤ _ := by + apply mul_le_mul_of_nonneg_left _ hM0 + apply Finset.prod_le_prod₀ + · intro i hi + exact pow_nonneg (div_nonneg (norm_nonneg _) (hR i).le) _ + · intro i hi + exact pow_le_pow_left₀ (div_nonneg (norm_nonneg _) (hR i).le) + (div_le_div_of_nonneg_right (hh i) (hR i).le) _ + +/-- Uniform convergence of the Taylor series on every strictly smaller closed polydisc. -/ +theorem hasSumUniformlyOn_polydiscTaylor {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} + {R s : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hs : ∀ i, 0 ≤ s i) (hsR : ∀ i, s i < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) : + HasSumUniformlyOn + (fun (m : Fin d → ℕ) h => (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m) + (fun h => f (c + h)) (closedPolydisc 0 s) := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans + (hM c (mem_closedPolydisc.mpr (by simpa using fun i => (hR i).le))) + have hq : ∀ i, ‖s i / R i‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (hs i) (hR i).le), div_lt_one (hR i)] + exact hsR i + have ha := (hasSum_pi_geometric (fun i => s i / R i) hq).summable.mul_left M + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + refine (tendstoUniformlyOn_tsum ha (fun m h hh => + norm_polydiscTaylor_term_le hR hM0 hM + (fun i => by simpa using mem_closedPolydisc.mp hh i) m)).congr_right ?_ + intro h hh + exact (hasSum_polydiscTaylor hR (fun i => + (show ‖h i‖ ≤ s i by simpa using mem_closedPolydisc.mp hh i).trans_lt (hsR i)) + hfc hfa hM).tsum_eq + +/-- The multi-index Taylor expansion converges locally uniformly throughout its polydisc. -/ +theorem hasSumLocallyUniformlyOn_polydiscTaylor {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} + {R : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) : + HasSumLocallyUniformlyOn + (fun (m : Fin d → ℕ) h => (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m) + (fun h => f (c + h)) (polydisc 0 R) := by + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro h hh + let s (i : Fin d) := (‖h i‖ + R i) / 2 + have hhR (i) : ‖h i‖ < R i := by simpa using mem_polydisc.mp hh i + have hs (i) : 0 ≤ s i := by dsimp [s]; linarith [norm_nonneg (h i), hR i] + have hsR (i) : s i < R i := by dsimp [s]; linarith [hhR i] + have hhs : h ∈ polydisc 0 s := mem_polydisc.mpr (by + intro i; simp only [Pi.zero_apply, dist_zero_right]; dsimp [s]; linarith [hhR i]) + refine ⟨closedPolydisc 0 s, ?_, + hasSumUniformlyOn_polydiscTaylor hR hs hsR hfc hfa hM⟩ + apply mem_nhdsWithin_of_mem_nhds + exact Filter.mem_of_superset ((isOpen_polydisc 0 s).mem_nhds hhs) + (fun z hz => mem_closedPolydisc.mpr (fun i => + (mem_polydisc.mp hz i).le)) + +/-- A uniform remainder bound for any finite Taylor polynomial. The right-hand side is the tail of +an explicitly summable product of geometric series. -/ +theorem norm_polydiscTaylor_remainder_le {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} + {R s : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hs : ∀ i, 0 ≤ s i) (hsR : ∀ i, s i < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) + (hh : ∀ i, ‖h i‖ ≤ s i) (t : Finset (Fin d → ℕ)) : + ‖f (c + h) - ∑ m ∈ t, (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m‖ ≤ + ∑' m : {m : Fin d → ℕ // m ∉ t}, M * ∏ i, (s i / R i) ^ m.val i := by + have hM0 : 0 ≤ M := (norm_nonneg (f c)).trans + (hM c (mem_closedPolydisc.mpr (by simpa using fun i => (hR i).le))) + have hq : ∀ i, ‖s i / R i‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (hs i) (hR i).le), div_lt_one (hR i)] + exact hsR i + have ha := (hasSum_pi_geometric (fun i => s i / R i) hq).summable.mul_left M + have hn := Summable.of_nonneg_of_le + (fun m => norm_nonneg ((∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m)) + (norm_polydiscTaylor_term_le hR hM0 hM hh) ha + rw [← (hasSum_polydiscTaylor hR (fun i => (hh i).trans_lt (hsR i)) hfc hfa hM).tsum_eq, + ← hn.of_norm.sum_add_tsum_subtype_compl t, add_sub_cancel_left] + exact (norm_tsum_le_tsum_norm (hn.subtype _)).trans + ((hn.subtype _).tsum_le_tsum (fun m => norm_polydiscTaylor_term_le hR hM0 hM hh m.val) + (ha.subtype _)) + +/-- The geometric-tail bound written without an infinite sum: a finite polynomial is subtracted from +the product of the geometric sums. -/ +theorem norm_polydiscTaylor_remainder_le_prod {f : (Fin d → ℂ) → E} {c h : Fin d → ℂ} + {R s : Fin d → ℝ} {M : ℝ} (hR : ∀ i, 0 < R i) + (hs : ∀ i, 0 ≤ s i) (hsR : ∀ i, s i < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) + (hh : ∀ i, ‖h i‖ ≤ s i) (t : Finset (Fin d → ℕ)) : + ‖f (c + h) - ∑ m ∈ t, (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m‖ ≤ + M * ((∏ i, (1 - s i / R i)⁻¹) - ∑ m ∈ t, ∏ i, (s i / R i) ^ m i) := by + have hq : ∀ i, ‖s i / R i‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (hs i) (hR i).le), div_lt_one (hR i)] + exact hsR i + have ha := (hasSum_pi_geometric (fun i => s i / R i) hq).mul_left M + have ht := ha.summable.sum_add_tsum_subtype_compl t + rw [ha.tsum_eq, ← Finset.mul_sum] at ht + have heq : (∑' m : {m : Fin d → ℕ // m ∉ t}, M * ∏ i, (s i / R i) ^ m.val i) = + M * ((∏ i, (1 - s i / R i)⁻¹) - ∑ m ∈ t, ∏ i, (s i / R i) ^ m i) := by + linarith + exact (norm_polydiscTaylor_remainder_le hR hs hsR hfc hfa hM hh t).trans_eq heq + +/-- Any mixed derivative of the separate-radius Taylor expansion is obtained by termwise +differentiation, with locally uniform convergence on the full open polydisc. -/ +theorem hasSumLocallyUniformlyOn_iteratedPartialDeriv_polydiscTaylor + {f : (Fin d → ℂ) → E} {c : Fin d → ℂ} {R : Fin d → ℝ} {M : ℝ} + (hR : ∀ i, 0 < R i) (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun v => f (update z i v)) (z i)) + (hM : ∀ z ∈ closedPolydisc c R, ‖f z‖ ≤ M) (is : List (Fin d)) : + HasSumLocallyUniformlyOn + (fun m : Fin d → ℕ => iteratedPartialDeriv is + (fun h => (∏ i, h i ^ m i) • polydiscCauchyCoeffWithRadii f c R m)) + (iteratedPartialDeriv is (fun h => f (c + h))) (polydisc 0 R) := by + apply (hasSumLocallyUniformlyOn_polydiscTaylor hR hfc hfa hM).iteratedPartialDeriv + _ (isOpen_polydisc 0 R) is + intro m z hz + apply AnalyticAt.smul + · exact Finset.analyticAt_fun_prod Finset.univ (fun i _ => + ((ContinuousLinearMap.proj i : (Fin d → ℂ) →L[ℂ] ℂ).analyticAt z).pow (m i)) + · exact analyticAt_const + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean new file mode 100644 index 0000000000..939b2e2f7c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean @@ -0,0 +1,9 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial/OfFn.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial/OfFn.lean new file mode 100644 index 0000000000..43014ef0bc --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial/OfFn.lean @@ -0,0 +1,72 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.Polynomial.Monic +public import Mathlib.Algebra.Polynomial.OfFn + +/-! +# Reconstruction of polynomials from finite coefficient vectors + +The notation `R[X]` denotes `Polynomial R`. Mathlib's linear map `Polynomial.ofFn n` builds +an `R[X]` from `n` coefficients. Adding `X ^ n` gives a monic polynomial; its monicity follows +from `Polynomial.monic_X_pow_add` and `Polynomial.ofFn_degree_lt`. + +## Main results + +* `Polynomial.ofFn_toFn_eq_of_degree_lt`: Reconstruction below a degree bound, including the + zero polynomial and the empty coefficient vector. +* `Polynomial.Monic.eq_X_pow_add_ofFn`: Reconstruction of a monic polynomial from its leading + term and its lower coefficients. +* `Polynomial.coeff_X_pow_add_ofFn_of_lt`: The lower coefficients of the monic construction. +* `Polynomial.natDegree_X_pow_add_ofFn`: Its natural degree over a nontrivial semiring. + +These algebraic facts require no topology and apply to arbitrary semirings. +-/ + +public section + +namespace Polynomial + +variable {R : Type*} [Semiring R] [DecidableEq R] + +/-- A polynomial of degree below `n` is recovered from its first `n` coefficients, including +when `n = 0` and the polynomial is zero. -/ +theorem ofFn_toFn_eq_of_degree_lt {n : ℕ} {p : R[X]} (hp : p.degree < (n : WithBot ℕ)) : + ofFn n (toFn n p) = p := by + ext i + by_cases hi : i < n + · simp [hi, toFn] + · rw [ofFn_coeff_eq_zero_of_ge _ (Nat.le_of_not_gt hi)] + exact (coeff_eq_zero_of_degree_lt (hp.trans_le (by exact_mod_cast Nat.le_of_not_gt hi))).symm + +/-- A monic polynomial is its leading power of `X` plus the polynomial of its lower +coefficient vector. -/ +theorem Monic.eq_X_pow_add_ofFn {p : R[X]} (hp : p.Monic) : + p = X ^ p.natDegree + ofFn p.natDegree (toFn p.natDegree p) := by + rw [ofFn_eq_sum_monomial] + simp only [toFn, LinearMap.pi_apply, lcoeff_apply, ← C_mul_X_pow_eq_monomial] + rw [Fin.sum_univ_eq_sum_range (fun i => C (p.coeff i) * X ^ i) p.natDegree] + exact hp.as_sum + +/-- Adding the leading monomial leaves every prescribed lower coefficient unchanged. -/ +theorem coeff_X_pow_add_ofFn_of_lt {n i : ℕ} (v : Fin n → R) (hi : i < n) : + (X ^ n + ofFn n v).coeff i = v ⟨i, hi⟩ := by + simp [coeff_add, coeff_X_pow, hi.ne, ofFn_coeff_eq_val_of_lt v hi] + +/-- Over a nontrivial semiring, adding `X ^ n` to a polynomial with `n` prescribed lower +coefficients gives natural degree `n`. -/ +theorem natDegree_X_pow_add_ofFn [Nontrivial R] {n : ℕ} (v : Fin n → R) : + (X ^ n + ofFn n v).natDegree = n := by + apply natDegree_eq_of_degree_eq_some + have hlt : (ofFn n v).degree < (X ^ n : R[X]).degree := by + rw [degree_X_pow] + exact ofFn_degree_lt v + rw [degree_add_eq_left_of_degree_lt hlt, degree_X_pow] + +end Polynomial + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean new file mode 100644 index 0000000000..d9797e7e16 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean @@ -0,0 +1,51 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.MvPolynomial.PDeriv +public import Mathlib.Analysis.Analytic.Polynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Formal and analytic coordinate derivatives of complex polynomials + +The formal partial derivatives of a multivariate polynomial agree with the analytic coordinate +derivatives of its evaluation. No finiteness assumption on the variable type is needed for the +one-variable slice identity. + +## Main results + +`hasDerivAt_eval_update` identifies `pderiv i p` with the derivative of the `i`-th coordinate +slice of `eval`. `partialDeriv_eval` is the corresponding statement for the several-variable +coordinate derivative `partialDeriv`. +-/ + +public noncomputable section +namespace MvPolynomial +variable {ι : Type*} + +/-- Formal partial differentiation agrees with differentiating a coordinate slice. No finiteness +assumption on the variable type is needed. -/ +theorem hasDerivAt_eval_update [DecidableEq ι] (p : MvPolynomial ι ℂ) (z : ι → ℂ) (i : ι) (x : ℂ) : + HasDerivAt (fun w => p.eval (Function.update z i w)) + ((pderiv i p).eval (Function.update z i x)) x := by + induction p using MvPolynomial.induction_on with + | C c => simpa using hasDerivAt_const x c + | add p q hp hq => simpa using! hp.add hq + | mul_X p j hp => + by_cases h : j = i + · subst j + simpa [pderiv_mul, mul_comm, add_comm] using! hp.mul (hasDerivAt_id x) + · simpa [pderiv_mul, h, Ne.symm h, mul_comm] using! hp.mul (hasDerivAt_const x (z j)) + +/-- Coordinate differentiation of a polynomial is evaluation of its formal derivative. -/ +theorem partialDeriv_eval [Fintype ι] [DecidableEq ι] (p : MvPolynomial ι ℂ) (z : ι → ℂ) (i : ι) : + SeveralComplexVariables.partialDeriv i (fun w => p.eval w) z = (pderiv i p).eval z := by + simpa [SeveralComplexVariables.partialDeriv] using (p.hasDerivAt_eval_update z i (z i)).deriv + +end MvPolynomial + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence.lean new file mode 100644 index 0000000000..1a8a219abc --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence.lean @@ -0,0 +1,127 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity + +/-! +# Characterization of power-series convergence domains + +An open complete logarithmically convex Reinhardt domain is holomorphically convex, by monomial +separation. Cartan–Thullen supplies a function with precisely that domain of existence. Its +Taylor series at zero has the prescribed convergence domain. + +## Main results + +`exists_powerSeriesConvergenceDomain_eq` realizes every nonempty open complete logarithmically +convex Reinhardt set as a scalar power-series convergence domain. +`isLogarithmicallyConvex_iff_exists_powerSeriesConvergenceDomain` is the corresponding +characterization among open complete Reinhardt sets. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +-/ + +public noncomputable section + +open Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} [Fintype ι] + +/-- Changing coordinate labels transports the convergence domain of a coefficient family. -/ +theorem powerSeriesConvergenceDomain_domCongr {κ : Type*} [Fintype κ] + (e : ι ≃ κ) (c : MvPowerSeries κ ℂ) : + powerSeriesConvergenceDomain (fun m => c (Finsupp.domCongr e m)) = + (Homeomorph.piCongrLeft (Y := fun _ : κ => ℂ) e) ⁻¹' powerSeriesConvergenceDomain c := by + let H := Homeomorph.piCongrLeft (Y := fun _ : κ => ℂ) e + have he : powerSeriesAbsConvergenceSet (fun m => c (Finsupp.domCongr e m)) = + H ⁻¹' powerSeriesAbsConvergenceSet c := by + ext z + change Summable (fun m : ι →₀ ℕ => ‖c (Finsupp.domCongr e m)‖ * ∏ i, ‖z i‖ ^ m i) ↔ + Summable (fun m : κ →₀ ℕ => ‖c m‖ * ∏ i, ‖H z i‖ ^ m i) + rw [← (Finsupp.domCongr e).toEquiv.summable_iff] + apply summable_congr + intro m + congr 1 + rw [← e.prod_comp] + simp [H, Homeomorph.piCongrLeft, Equiv.piCongrLeft, Finsupp.domCongr_apply, + Finsupp.equivMapDomain_apply] + change interior (powerSeriesAbsConvergenceSet _) = H ⁻¹' interior (powerSeriesAbsConvergenceSet c) + rw [he, H.preimage_interior] + +/-- On finite ordered coordinates, the Taylor series of a nonextendable function realizes an open +complete logarithmically convex Reinhardt domain. -/ +private theorem exists_powerSeriesConvergenceDomain_eq_fin {n : ℕ} {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hne : U.Nonempty) (hc : IsCompleteReinhardt U) + (hl : IsLogarithmicallyConvex U) : + ∃ c : MvPowerSeries (Fin n) ℂ, powerSeriesConvergenceDomain c = U := by + obtain ⟨f, hf⟩ := (isHolomorphicallyConvex_of_completeReinhardt ho hc + hl).exists_domainOfExistence ho + obtain ⟨hUD, he⟩ + := IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum ho hc hf.1 + refine ⟨taylorCoefficientsAtZero f, Subset.antisymm ?_ hUD⟩ + exact hf.2 _ U (isOpen_powerSeriesConvergenceDomain _) + ((isCompleteReinhardt_powerSeriesConvergenceDomain _).isConnected (hne.mono hUD)) + ho hne Subset.rfl hUD ⟨_, analyticOnNhd_powerSeriesSum _, he⟩ + +/-- **Hartogs' characterization, existence direction** ([Boas][Boas2013] §2.2, Theorem 1). +Every nonempty open complete logarithmically convex Reinhardt set is exactly the convergence +domain of a scalar power series. Monomial separation and Cartan–Thullen give a +nonextendable function whose Taylor series realizes the domain. -/ +theorem exists_powerSeriesConvergenceDomain_eq {U : Set (ι → ℂ)} (hU : IsOpen U) + (hne : U.Nonempty) (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) : + ∃ c : MvPowerSeries ι ℂ, powerSeriesConvergenceDomain c = U := by + let e := Fintype.equivFin ι + let H : (Fin (Fintype.card ι) → ℂ) ≃ₜ (ι → ℂ) := + { toFun := fun z i => z (e i) + invFun := fun z j => z (e.symm j) + left_inv := fun z => by ext j; simp + right_inv := fun z => by ext i; simp + continuous_toFun := continuous_pi fun i => continuous_apply (e i) + continuous_invFun := continuous_pi fun j => continuous_apply (e.symm j) } + let V := H ⁻¹' U + have hoV : IsOpen V := hU.preimage H.continuous + have hnV : V.Nonempty := by + obtain ⟨z, hz⟩ := hne + exact ⟨H.symm z, by simpa only [V, mem_preimage, H.apply_symm_apply] using hz⟩ + have hcV : IsCompleteReinhardt V := by + intro z hz w hw + change (fun i => w (e i)) ∈ U + exact hc (show (fun i => z (e i)) ∈ U from hz) (fun i => hw (e i)) + have hlV : IsLogarithmicallyConvex V := by + intro x hx y hy a b ha hb hab + exact hl (x := fun i => x (e i)) hx (y := fun i => y (e i)) hy ha hb hab + obtain ⟨c, hD⟩ := exists_powerSeriesConvergenceDomain_eq_fin hoV hnV hcV hlV + refine ⟨fun m => c (Finsupp.domCongr e m), ?_⟩ + rw [powerSeriesConvergenceDomain_domCongr, hD] + ext z + change H ((Homeomorph.piCongrLeft (Y := fun _ : Fin (Fintype.card ι) => ℂ) e) z) ∈ U ↔ z ∈ U + have he : H ((Homeomorph.piCongrLeft (Y := fun _ : Fin (Fintype.card ι) => ℂ) e) z) = z := by + ext i + exact Equiv.piCongrLeft_apply_apply (fun _ : Fin (Fintype.card ι) => ℂ) e z i + rw [he] + +/-- **Hartogs' characterization of power-series convergence domains.** For a nonempty +open complete Reinhardt set, logarithmic convexity is exactly the existence condition. -/ +theorem isLogarithmicallyConvex_iff_exists_powerSeriesConvergenceDomain + {U : Set (ι → ℂ)} (hU : IsOpen U) (hne : U.Nonempty) (hc : IsCompleteReinhardt U) : + IsLogarithmicallyConvex U ↔ + ∃ c : MvPowerSeries ι ℂ, powerSeriesConvergenceDomain c = U := by + constructor + · exact exists_powerSeriesConvergenceDomain_eq hU hne hc + · rintro ⟨c, rfl⟩ + exact isLogarithmicallyConvex_powerSeriesConvergenceDomain c + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Analytic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Analytic.lean new file mode 100644 index 0000000000..aba1f1f98c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Analytic.lean @@ -0,0 +1,148 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull + +/-! +# Analytic sums on power-series convergence domains + +Arbitrary Banach-valued coefficient families converge locally uniformly on the interior of their +absolute-convergence set, and their sum is analytic there. Absolute-convergence sets are +geometrically convex in moduli even at zero coordinates and boundary points. Reference: +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Theorem 2.4.2. + +## Main results + +`powerSeriesSum` is the sum of a Banach-valued power series on its convergence domain. +`hasSumLocallyUniformlyOn_powerSeries` is locally uniform convergence there. +`analyticOnNhd_powerSeriesSum` is analyticity of the sum. +`hasGeometricallyConvexModuli_powerSeriesConvergenceDomain` is geometric convexity of the moduli, +including zero coordinates. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Set Filter +open scoped NNReal Topology BigOperators + +namespace SeveralComplexVariables + +variable {ι F : Type*} [Fintype ι] [NormedAddCommGroup F] + +/-- Nonnegative monomials commute with weighted geometric interpolation, including zeros. -/ +theorem prod_geometricCombination_pow (r s : ι → ℝ≥0) (m : ι →₀ ℕ) (a b : ℝ) : + (∏ i, geometricCombination a b r s i ^ m i) = + (∏ i, r i ^ m i) ^ a * (∏ i, s i ^ m i) ^ b := by + simp only [geometricCombination, mul_pow, Finset.prod_mul_distrib] + congr 1 + · rw [← NNReal.finsetProd_rpow] + apply Finset.prod_congr rfl + intro i _ + rw [← NNReal.rpow_mul_natCast, mul_comm, NNReal.rpow_natCast_mul] + · rw [← NNReal.finsetProd_rpow] + apply Finset.prod_congr rfl + intro i _ + rw [← NNReal.rpow_mul_natCast, mul_comm, NNReal.rpow_natCast_mul] + +/-- Weighted arithmetic–geometric mean bounds a coefficient times an interpolated monomial. -/ +theorem geometric_monomial_le (k : ℝ≥0) (r s : ι → ℝ≥0) (m : ι →₀ ℕ) + {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1) : + (k : ℝ) * (∏ i, (geometricCombination a b r s i : ℝ) ^ m i) ≤ + a * ((k : ℝ) * ∏ i, (r i : ℝ) ^ m i) + + b * ((k : ℝ) * ∏ i, (s i : ℝ) ^ m i) := by + have he : k * (∏ i, geometricCombination a b r s i ^ m i) = + (k * ∏ i, r i ^ m i) ^ a * (k * ∏ i, s i ^ m i) ^ b := by + rw [prod_geometricCombination_pow, NNReal.mul_rpow, NNReal.mul_rpow] + have hk : k ^ a * k ^ b = k := by + rw [← NNReal.rpow_add_of_nonneg k ha hb, hab, NNReal.rpow_one] + calc + _ = (k ^ a * k ^ b) * ((∏ i, r i ^ m i) ^ a * (∏ i, s i ^ m i) ^ b) := by rw [hk] + _ = _ := by ring + have h := NNReal.geom_mean_le_arith_mean2_weighted ⟨a, ha⟩ ⟨b, hb⟩ + (k * ∏ i, r i ^ m i) (k * ∏ i, s i ^ m i) (by ext; exact hab) + change (k * ∏ i, r i ^ m i) ^ a * (k * ∏ i, s i ^ m i) ^ b ≤ _ at h + rw [← he] at h + exact_mod_cast h + +/-- The absolute-convergence set has geometrically convex moduli, including boundary points and +points on coordinate hyperplanes. No completeness of the coefficient space is needed. -/ +theorem hasGeometricallyConvexModuli_powerSeriesAbsConvergenceSet (c : MvPowerSeries ι F) : + HasGeometricallyConvexModuli (powerSeriesAbsConvergenceSet c) := by + rintro r ⟨z, hz, rfl⟩ s ⟨w, hw, rfl⟩ a b ha hb hab + apply (isCompleteReinhardt_powerSeriesAbsConvergenceSet c).isReinhardt.mem_modulusTrace_iff.mpr + change Summable (fun m : ι →₀ ℕ => ‖c m‖ * + ∏ i, ‖(geometricCombination a b (fun i => ‖z i‖₊) (fun i => ‖w i‖₊) i : ℂ)‖ ^ m i) + apply ((hz.mul_left a).add (hw.mul_left b)).of_nonneg_of_le (fun _ => by positivity) + intro m + simpa only [Complex.norm_of_nonneg (NNReal.coe_nonneg _), coe_nnnorm] using + geometric_monomial_le ‖c m‖₊ (fun i => ‖z i‖₊) (fun i => ‖w i‖₊) m ha hb hab + +/-- The convergence domain satisfies the zero-inclusive logarithmic convexity property. -/ +theorem hasGeometricallyConvexModuli_powerSeriesConvergenceDomain (c : MvPowerSeries ι F) : + HasGeometricallyConvexModuli (powerSeriesConvergenceDomain c) := + (isLogarithmicallyConvex_powerSeriesConvergenceDomain c).hasGeometricallyConvexModuli + (isOpen_powerSeriesConvergenceDomain c) (isCompleteReinhardt_powerSeriesConvergenceDomain c) + +variable [NormedSpace ℂ F] [CompleteSpace F] + +/-- The sum of a coefficient power series; its analytic domain is treated separately. -/ +@[expose] def powerSeriesSum (c : MvPowerSeries ι F) (z : ι → ℂ) : F := + ∑' m : ι →₀ ℕ, (∏ i, z i ^ m i) • c m + +/-- An arbitrary coefficient series converges locally uniformly on its convergence domain. -/ +theorem hasSumLocallyUniformlyOn_powerSeries (c : MvPowerSeries ι F) : + HasSumLocallyUniformlyOn (fun (m : ι →₀ ℕ) z => (∏ i, z i ^ m i) • c m) + (powerSeriesSum c) (powerSeriesConvergenceDomain c) := by + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro z hz + obtain ⟨r, hr, hzr⟩ := (isReinhardt_powerSeriesConvergenceDomain c).exists_strict_modulus_majorant + (isOpen_powerSeriesConvergenceDomain c) hz + let W : Set (ι → ℂ) := {w | ∀ i, ‖w i‖ < (r i : ℝ)} + have hW : IsOpen W := by + simpa only [W, ofPred_forall] using + (isOpen_iInter_of_finite fun i => isOpen_lt (continuous_apply i).norm + (continuous_const (y := (r i : ℝ)))) + refine ⟨W, nhdsWithin_le_nhds (hW.mem_nhds (fun i => hzr i)), ?_⟩ + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + apply tendstoUniformlyOn_tsum (powerSeriesConvergenceDomain_subset c hr) + intro m w hw + simp only [norm_smul, norm_prod, norm_pow] + rw [mul_comm] + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + apply Finset.prod_le_prod₀ (fun _ _ => by positivity) + intro i _ + apply pow_le_pow_left₀ (norm_nonneg _) _ + simpa only [Complex.norm_of_nonneg (NNReal.coe_nonneg _)] using (hw i).le + +/-- Compact subsets of the convergence domain have uniform convergence of finite subsums. -/ +theorem hasSumUniformlyOn_powerSeries (c : MvPowerSeries ι F) + {K : Set (ι → ℂ)} (hK : IsCompact K) (hKD : K ⊆ powerSeriesConvergenceDomain c) : + HasSumUniformlyOn (fun (m : ι →₀ ℕ) z => (∏ i, z i ^ m i) • c m) + (powerSeriesSum c) K := + hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + ((tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK).mp + ((hasSumLocallyUniformlyOn_powerSeries c).mono hKD)) + +/-- The sum of an arbitrary Banach-valued power series is analytic on its convergence domain. -/ +theorem analyticOnNhd_powerSeriesSum (c : MvPowerSeries ι F) : + AnalyticOnNhd ℂ (powerSeriesSum c) (powerSeriesConvergenceDomain c) := by + classical + apply (hasSumLocallyUniformlyOn_powerSeries c).analyticOnNhd_pi _ + (isOpen_powerSeriesConvergenceDomain c) + intro m z _ + exact (Finset.analyticAt_fun_prod Finset.univ (fun i _ => + ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt z).pow (m i))).smul analyticAt_const + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Basic.lean new file mode 100644 index 0000000000..0ecefe7e49 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PowerSeriesConvergence/Basic.lean @@ -0,0 +1,192 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Normed.Group.InfiniteSum +public import Mathlib.RingTheory.MvPowerSeries.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt + +/-! +# Domains of absolute convergence of multivariable power series + +For coefficients indexed by Mathlib's finitely supported multi-indices, the absolute convergence +set records summability of the norms of the individual monomial terms. Its interior is the +convergence domain, following [Boas][Boas2013] (2013), Sections 2.1--2.2. Boundary convergence +is deliberately not included in the definition of the domain. + +The absolute-convergence set and its interior are complete Reinhardt and logarithmically convex. +The proofs apply to normed-group-valued coefficients; a complex Banach target is needed only to +deduce summability of the actual vector-valued terms. Convexity follows by comparing terms at +logarithmic interpolates with arithmetic averages, using convexity of exp. + +The existence converse is proved in `SeveralComplexVariables.PowerSeriesConvergence`. Empty +coordinate index types are included; nonemptiness is required of a prescribed domain, but a +general series may have empty convergence domain. + +## Main definitions + +* `powerSeriesAbsConvergenceSet`: The absolute-convergence set of a power series centred at zero. +* `powerSeriesConvergenceDomain`: The convergence domain is the interior of the absolute-convergence + set. + +## Main results + +* `isOpen_powerSeriesConvergenceDomain`: A power-series convergence domain is open by definition, + and may be empty. +* `isCompleteReinhardt_powerSeriesConvergenceDomain`: The convergence domain is complete Reinhardt, + including at coordinate hyperplanes. +* `isLogarithmicallyConvex_powerSeriesConvergenceDomain`: The interior of the absolute-convergence + set is logarithmically convex. +* `isPathConnected_powerSeriesConvergenceDomain`: A nonempty convergence domain is path connected. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +-/ + +public noncomputable section + +open Set +open scoped BigOperators + +namespace SeveralComplexVariables + +variable {ι E : Type*} [Fintype ι] [NormedAddCommGroup E] + +/-- The absolute-convergence set of a power series centred at zero. The product records the norm of +the monomial, so no scalar action or completeness of the coefficient space is needed. -/ +@[expose] def powerSeriesAbsConvergenceSet (c : MvPowerSeries ι E) : Set (ι → ℂ) := + {z | Summable (fun m : ι →₀ ℕ => ‖c m‖ * ∏ i, ‖z i‖ ^ m i)} + +/-- The convergence domain is the interior of the absolute-convergence set. -/ +@[expose] def powerSeriesConvergenceDomain (c : MvPowerSeries ι E) : Set (ι → ℂ) := + interior (powerSeriesAbsConvergenceSet c) + +/-- For complex normed coefficients the defining summability condition is exactly absolute +convergence of the vector-valued monomial terms. -/ +theorem mem_powerSeriesAbsConvergenceSet_iff [NormedSpace ℂ E] + {c : MvPowerSeries ι E} {z : ι → ℂ} : + z ∈ powerSeriesAbsConvergenceSet c ↔ + Summable (fun m : ι →₀ ℕ => ‖(∏ i, z i ^ m i) • c m‖) := by + simp [powerSeriesAbsConvergenceSet, norm_smul, norm_prod, norm_pow, mul_comm] + +/-- Every formal series converges absolutely at zero, since only its constant term survives. This +does not assert that its convergence domain is nonempty. -/ +theorem zero_mem_powerSeriesAbsConvergenceSet (c : MvPowerSeries ι E) : + 0 ∈ powerSeriesAbsConvergenceSet c := by + classical + apply summable_of_ne_finset_zero (s := {0}) + intro m hm + have hm0 : m ≠ 0 := by simpa using hm + obtain ⟨i, hi⟩ := Finsupp.ne_iff.mp hm0 + have hterm : ‖(0 : ι → ℂ) i‖ ^ m i = 0 := by + simpa using (zero_pow hi : (0 : ℝ) ^ m i = 0) + rw [Finset.prod_eq_zero (Finset.mem_univ i) hterm, mul_zero] + +/-- A power-series convergence domain is open by definition, and may be empty. -/ +theorem isOpen_powerSeriesConvergenceDomain (c : MvPowerSeries ι E) : + IsOpen (powerSeriesConvergenceDomain c) := isOpen_interior + +/-- Membership of the convergence domain implies absolute convergence. -/ +theorem powerSeriesConvergenceDomain_subset (c : MvPowerSeries ι E) : + powerSeriesConvergenceDomain c ⊆ powerSeriesAbsConvergenceSet c := interior_subset + +/-- Decreasing coordinate moduli preserves absolute convergence. -/ +theorem isCompleteReinhardt_powerSeriesAbsConvergenceSet (c : MvPowerSeries ι E) : + IsCompleteReinhardt (powerSeriesAbsConvergenceSet c) := by + intro z hz w hw + apply hz.of_nonneg_of_le + · intro m + positivity + · intro m + apply mul_le_mul_of_nonneg_left _ (norm_nonneg _) + exact Finset.prod_le_prod₀ (fun i _ => by positivity) + (fun i _ => pow_le_pow_left₀ (norm_nonneg _) (hw i) _) + +/-- The convergence domain is complete Reinhardt, including at coordinate hyperplanes. -/ +theorem isCompleteReinhardt_powerSeriesConvergenceDomain (c : MvPowerSeries ι E) : + IsCompleteReinhardt (powerSeriesConvergenceDomain c) := + (isCompleteReinhardt_powerSeriesAbsConvergenceSet c).interior + +/-- A power-series convergence domain has independent coordinate rotation symmetry. -/ +theorem isReinhardt_powerSeriesConvergenceDomain (c : MvPowerSeries ι E) : + IsReinhardt (powerSeriesConvergenceDomain c) := + (isCompleteReinhardt_powerSeriesConvergenceDomain c).isReinhardt + +/-- A nonempty convergence domain is path connected. -/ +theorem isPathConnected_powerSeriesConvergenceDomain (c : MvPowerSeries ι E) + (hne : (powerSeriesConvergenceDomain c).Nonempty) : + IsPathConnected (powerSeriesConvergenceDomain c) := + (isCompleteReinhardt_powerSeriesConvergenceDomain c).isPathConnected hne + +/-- In logarithmic coordinates the modulus of a monomial is an exponential of a linear form. -/ +theorem prod_norm_exp_pow (x : ι → ℝ) (m : ι →₀ ℕ) : + (∏ i, ‖(Real.exp (x i) : ℂ)‖ ^ m i) = Real.exp (∑ i, (m i : ℝ) * x i) := by + simp [Real.exp_sum, Real.exp_nat_mul] + +/-- Absolute convergence has a convex logarithmic image, by termwise convexity of exp and comparison +of nonnegative series. -/ +theorem isLogarithmicallyConvex_powerSeriesAbsConvergenceSet (c : MvPowerSeries ι E) : + IsLogarithmicallyConvex (powerSeriesAbsConvergenceSet c) := by + intro x hx y hy a b ha hb hab + change Summable (fun m : ι →₀ ℕ => + ‖c m‖ * ∏ i, ‖(Real.exp ((a • x + b • y) i) : ℂ)‖ ^ m i) + have hx' : Summable (fun m : ι →₀ ℕ => ‖c m‖ * Real.exp (∑ i, (m i : ℝ) * x i)) := by + simpa only [logarithmicImage, mem_ofPred_eq, powerSeriesAbsConvergenceSet, + prod_norm_exp_pow] using hx + have hy' : Summable (fun m : ι →₀ ℕ => ‖c m‖ * Real.exp (∑ i, (m i : ℝ) * y i)) := by + simpa only [logarithmicImage, mem_ofPred_eq, powerSeriesAbsConvergenceSet, + prod_norm_exp_pow] using hy + apply ((hx'.mul_left a).add (hy'.mul_left b)).of_nonneg_of_le + · intro m + positivity + · intro m + rw [prod_norm_exp_pow] + have heq : (∑ i, (m i : ℝ) * (a • x + b • y) i) = + a * (∑ i, (m i : ℝ) * x i) + b * (∑ i, (m i : ℝ) * y i) := by + simp only [Pi.add_apply, Pi.smul_apply, smul_eq_mul, mul_add, + Finset.sum_add_distrib, Finset.mul_sum] + congr 1 <;> apply Finset.sum_congr rfl <;> intros <;> ring + rw [heq] + have h := mul_le_mul_of_nonneg_left + (convexOn_exp.2 (mem_univ (∑ i, (m i : ℝ) * x i)) + (mem_univ (∑ i, (m i : ℝ) * y i)) ha hb hab) (norm_nonneg (c m)) + simpa only [smul_eq_mul, mul_add, mul_left_comm] using h + +/-- The interior of the absolute-convergence set is logarithmically convex. -/ +theorem isLogarithmicallyConvex_powerSeriesConvergenceDomain (c : MvPowerSeries ι E) : + IsLogarithmicallyConvex (powerSeriesConvergenceDomain c) := + (isLogarithmicallyConvex_powerSeriesAbsConvergenceSet c).interior + (isCompleteReinhardt_powerSeriesAbsConvergenceSet c) + +/-- Absolute convergence implies summability of the vector-valued monomial terms in a complex Banach +space. -/ +theorem summable_powerSeriesTerms [NormedSpace ℂ E] [CompleteSpace E] + {c : MvPowerSeries ι E} {z : ι → ℂ} (hz : z ∈ powerSeriesAbsConvergenceSet c) : + Summable (fun m : ι →₀ ℕ => (∏ i, z i ^ m i) • c m) := by + apply hz.of_norm_bounded + intro m + simp [norm_smul, norm_prod, norm_pow, mul_comm] + +/-- The zero series has the whole coordinate space as its convergence domain. -/ +@[simp] theorem powerSeriesConvergenceDomain_zero : + powerSeriesConvergenceDomain (0 : MvPowerSeries ι E) = univ := by + have hz (m : ι →₀ ℕ) : (0 : MvPowerSeries ι E) m = 0 := rfl + simp [powerSeriesConvergenceDomain, powerSeriesAbsConvergenceSet, hz] + +/-- With no coordinates, every series has the whole singleton coordinate space as its convergence +domain. -/ +theorem powerSeriesConvergenceDomain_of_isEmpty [IsEmpty ι] (c : MvPowerSeries ι E) : + powerSeriesConvergenceDomain c = univ := by + have h : powerSeriesAbsConvergenceSet c = univ := by + apply Set.eq_univ_of_forall + intro z + exact Summable.of_finite + simp [powerSeriesConvergenceDomain, h] + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean new file mode 100644 index 0000000000..5ba74f4226 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean @@ -0,0 +1,656 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.AbsMax +public import Mathlib.Topology.Connected.LocallyPathConnected +public import Mathlib.Topology.Order.ProjIcc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant + +/-! +# Pseudoconvexity + +This file relates domains of holomorphy to plurisubharmonic functions and to two geometric +convexity notions. + +* **Boundary distance.** On a domain of holomorphy in `Fin n → ℂ`, the negative logarithm of +the supremum-norm distance to the complement is plurisubharmonic. The proof is +[Hörmander][Hormander1973]'s: a +harmonic polynomial majorant of `-log δ` on a circle in a complex line gives, through the +weighted hull-radius bound of Thullen's lemma, the same bound at the center. +* **Pseudoconvexity.** An open set is pseudoconvex if it carries a continuous + plurisubharmonic exhaustion function. Domains of holomorphy are pseudoconvex. +* **Continuity principle.** Along a continuous family of affine analytic discs whose boundary + circles stay in a pseudoconvex set and whose initial disc lies in the set, every disc lies in + the set. This is the Kontinuitätssatz for affine discs, proved by the maximum principle for + plurisubharmonic functions on discs. +* **Hartogs convexity.** In a product `E × ℂ`, a set satisfying the continuity principle + contains the filled cylinder of every Hartogs cylinder it contains. +* **Kontinuitätssatz.** On a domain of holomorphy in a finite-dimensional complex normed space, the +continuity principle +holds for continuous families of holomorphic discs, not only affine ones: every point of a +holomorphic disc lies in the holomorphic hull of the boundary circle, and Thullen's radius +bound keeps the discs at a fixed distance from the complement. + +The boundary-distance result uses the supremum norm on `Fin n → ℂ`. For the whole space, +`Metric.infDist` of the empty complement and `Real.log 0` are both zero, so the function in +that theorem is identically zero. This is a real-valued convention; `boundaryEDistance` instead +takes the value `∞` for an empty complement. Pseudoconvexity and the holomorphic continuity +principle are transported to arbitrary finite-dimensional complex normed spaces; this transport +does not identify their boundary-distance functions. + +The converse implications, from pseudoconvexity back to the domain-of-holomorphy property, form +the Levi problem and are outside the present scope. + +References: [Hörmander][Hormander1973] (1973), Theorems 2.5.4, 2.6.5 and 2.6.7; +[Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Sections 1 and 3; +[Range][Range1986] (1986), Chapter II, Sections 2 and 5. + +## Main definitions + +* `IsPseudoconvex`: An open set is pseudoconvex if it carries a continuous plurisubharmonic + exhaustion function: one whose sublevel sets inside the set are compact. +* `SatisfiesContinuityPrinciple`: **Continuity principle for affine analytic discs.** Along a + continuous family of affine analytic discs whose boundary circles stay in the set and whose + initial disc lies in the set, every disc of the family lies in the set. +* `SatisfiesHolomorphicContinuityPrinciple`: **Continuity principle for holomorphic discs + (Kontinuitätssatz).** Along a continuous family of holomorphic discs whose boundary circles stay + in the set and whose initial disc lies in the set, every disc of the family lies in the set. +* `IsHartogsConvex`: **Hartogs convexity** for cylinder figures: whenever a Hartogs cylinder over an + open preconnected base, with disc fibers over a nonempty open part of the base, lies in the set, + so does the filled cylinder. + +## Main results + +* `IsDomainOfHolomorphy.plurisubharmonicOn_neg_log_infDist`: **Plurisubharmonicity of the boundary + distance ([Hörmander][Hormander1973] 2.6.5).** On a domain of holomorphy in `Fin n → ℂ`, the + negative logarithm of the distance to the complement is plurisubharmonic. +* `IsDomainOfHolomorphy.isPseudoconvex_fin`: **Domains of holomorphy in coordinates are + pseudoconvex.** The exhaustion is the maximum of the negative logarithm of the boundary distance + and the norm. +* `IsPseudoconvex.satisfiesContinuityPrinciple`: **Pseudoconvex sets satisfy the continuity + principle ([Fritzsche–Grauert][FritzscheGrauert2002] II.3.1).** +* `IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple_fin`: **Domains of holomorphy in + coordinates satisfy the continuity principle for holomorphic discs.** The coordinate-free version + is `IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple`. +* `IsDomainOfHolomorphy.isPseudoconvex`: **Domains of holomorphy are pseudoconvex.** The exhaustion + is transported from the coordinate version `IsDomainOfHolomorphy.isPseudoconvex_fin`. +* `IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple`: **Domains of holomorphy satisfy + the continuity principle for holomorphic discs.** +* `SatisfiesContinuityPrinciple.isHartogsConvex`: **The continuity principle implies Hartogs + convexity ([Fritzsche–Grauert][FritzscheGrauert2002] II.1.5).** The disc fibers are slid along a + path in the base from the part carrying full discs. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +-/ + +public section + +open Complex Filter Metric Set Real +open scoped Topology + +namespace SeveralComplexVariables + +/-- Clamp a real parameter to the unit interval. -/ +private noncomputable def clampIcc01 (t : ℝ) : ℝ := Set.projIcc 0 1 zero_le_one t + +/-- Clamping to `[0, 1]` is continuous. -/ +private theorem continuous_clampIcc01 : Continuous clampIcc01 := continuous_subtype_val.comp + continuous_projIcc + +/-- The clamp of any real lies in `[0, 1]`. -/ +private theorem clampIcc01_mem_Icc (t : ℝ) : clampIcc01 t ∈ Icc (0 : ℝ) 1 := + (Set.projIcc 0 1 zero_le_one t).property + +/-- Clamping is the identity on `[0, 1]`. -/ +private theorem clampIcc01_eq_of_mem_Icc {t : ℝ} (ht : t ∈ Icc (0 : ℝ) 1) : clampIcc01 t = t + := congrArg + Subtype.val (Set.projIcc_of_mem zero_le_one ht) + +/-- Clamping is idempotent. -/ +private theorem clampIcc01_idem (t : ℝ) : clampIcc01 (clampIcc01 t) = clampIcc01 t := + clampIcc01_eq_of_mem_Icc (clampIcc01_mem_Icc t) + +section BoundaryDistance + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Points of a closed disc in a complex line lie in the holomorphic hull of its boundary circle, by +the maximum modulus principle. -/ +theorem mem_holomorphicHull_of_mem_disc {U : Set E} {a w : E} {r : ℝ} (hr : 0 < r) + (hdisc : ∀ t ∈ closedBall (0 : ℂ) r, a + t • w ∈ U) {t : ℂ} (ht : t ∈ closedBall (0 : ℂ) r) : + a + t • w ∈ holomorphicHull U ((fun t : ℂ => a + t • w) '' sphere 0 r) := by + refine ⟨hdisc t ht, fun f hf M hM => ?_⟩ + have hg : DiffContOnCl ℂ (fun t : ℂ => f (a + t • w)) (ball 0 r) := by + apply DifferentiableOn.diffContOnCl + rw [closure_ball 0 hr.ne'] + exact fun s hs => ((hf _ (hdisc s hs)).comp_of_eq + (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) + rfl).differentiableAt.differentiableWithinAt + have hbd : ∀ s ∈ frontier (ball (0 : ℂ) r), ‖f (a + s • w)‖ ≤ M := by + intro s hs + rw [frontier_ball 0 hr.ne'] at hs + exact hM _ ⟨s, hs, rfl⟩ + have := Complex.norm_le_of_forall_mem_frontier_norm_le isBounded_ball hg hbd + (z := t) (by rw [closure_ball 0 hr.ne']; exact ht) + exact this + +/-- Every point of a closed holomorphic disc lies in the holomorphic hull of the boundary circle, by +the maximum modulus principle. -/ +theorem mem_holomorphicHull_of_analytic_disc {U : Set E} {φ : ℂ → E} {r : ℝ} (hr : 0 < r) + (hφ : AnalyticOnNhd ℂ φ (closedBall 0 r)) (hdisc : ∀ t ∈ closedBall (0 : ℂ) r, φ t ∈ U) + {t : ℂ} (ht : t ∈ closedBall (0 : ℂ) r) : φ t ∈ holomorphicHull U (φ '' sphere 0 r) := by + refine ⟨hdisc t ht, fun f hf M hM => ?_⟩ + have hg : DiffContOnCl ℂ (fun t : ℂ => f (φ t)) (ball 0 r) := by + apply DifferentiableOn.diffContOnCl + rw [closure_ball 0 hr.ne'] + exact fun s hs => ((hf _ (hdisc s hs)).comp_of_eq (hφ s hs) + rfl).differentiableAt.differentiableWithinAt + have hbd : ∀ s ∈ frontier (ball (0 : ℂ) r), ‖f (φ s)‖ ≤ M := by + intro s hs + rw [frontier_ball 0 hr.ne'] at hs + exact hM _ ⟨s, hs, rfl⟩ + exact Complex.norm_le_of_forall_mem_frontier_norm_le isBounded_ball hg hbd + (z := t) (by rw [closure_ball 0 hr.ne']; exact ht) + +variable {n : ℕ} + +/-- **Plurisubharmonicity of the boundary distance ([Hörmander][Hormander1973] 2.6.5).** On a domain +of holomorphy in `Fin n → ℂ`, the negative logarithm of the supremum-norm distance to the +complement is plurisubharmonic. When the complement is empty, this function is zero by the +conventions `Metric.infDist_empty` and `Real.log_zero`. -/ +theorem IsDomainOfHolomorphy.plurisubharmonicOn_neg_log_infDist {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : + PlurisubharmonicOn (fun z => -Real.log (infDist z Uᶜ)) U := by + rcases eq_empty_or_nonempty Uᶜ with hc | hc + · simp only [hc, infDist_empty, Real.log_zero, neg_zero] + exact plurisubharmonicOn_const 0 U + have hpos : ∀ z ∈ U, 0 < infDist z Uᶜ := fun z hz => + (infDist_pos_iff_notMem_closure hc).mp (by rwa [ho.isClosed_compl.closure_eq, notMem_compl_iff]) + have hcont : ContinuousOn (fun z => -Real.log (infDist z Uᶜ)) U := + ((continuous_infDist_pt Uᶜ).continuousOn.log fun z hz => (hpos z hz).ne').neg + refine plurisubharmonicOn_of_hasSubmeanAt hcont.upperSemicontinuousOn fun a ha w => ?_ + -- the constant slice + by_cases hw : w = 0 + · simp only [hw, smul_zero, add_zero] + exact hasSubmeanAt_const _ 0 + obtain ⟨i, hi⟩ := Function.ne_iff.mp hw + have hline : Continuous fun t : ℂ => a + t • w := by fun_prop + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hline.continuousAt.preimage_mem_nhds (by + show U ∈ 𝓝 ((fun t : ℂ => a + t • w) 0) + simp only [zero_smul, add_zero] + exact ho.mem_nhds ha)) + refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ + have hdisc : ∀ t ∈ closedBall (0 : ℂ) r, a + t • w ∈ U := fun t ht => + hball (closedBall_subset_ball hrρ ht) + have hslice_cont : ContinuousOn (fun t : ℂ => -Real.log (infDist (a + t • w) Uᶜ)) (sphere 0 r) := + hcont.comp hline.continuousOn fun t ht => hdisc t (sphere_subset_closedBall ht) + refine ⟨hslice_cont.circleIntegrable hr.le, ?_⟩ + refine le_circleAverage_of_forall_polynomial_majorant hr hslice_cont fun Q hQ => ?_ + simp only [zero_smul, add_zero] + -- the entire function realizing the polynomial majorant along the line + set F : (Fin n → ℂ) → ℂ := fun z => Q.eval ((z i - a i) / w i / r) with hF + have hFline : ∀ t : ℂ, F (a + t • w) = Q.eval ((t - 0) / r) := fun t => by + simp only [hF, Pi.add_apply, Pi.smul_apply, smul_eq_mul, add_sub_cancel_left, sub_zero] + rw [mul_div_cancel_right₀ _ hi] + set q : (Fin n → ℂ) → ℂ := fun z => Complex.exp (-F z) with hq + have hqan : AnalyticOnNhd ℂ q U := by + have hd : Differentiable ℂ q := by + apply Complex.differentiable_exp.comp + apply Differentiable.neg + exact Q.differentiable.comp (by fun_prop) + exact hd.analyticOnNhd_of_finiteDimensional.mono (subset_univ U) + have hqnorm : ∀ z, ‖q z‖ = Real.exp (-(F z).re) := fun z => by + simp [hq, Complex.norm_exp] + set K := (fun t : ℂ => a + t • w) '' sphere 0 r with hK + have hKc : IsCompact K := (isCompact_sphere 0 r).image hline + have hKU : K ⊆ U := by + rintro _ ⟨t, ht, rfl⟩ + exact hdisc t (sphere_subset_closedBall ht) + have hrad : ∀ z ∈ K, ball z ‖q z‖ ⊆ U := by + rintro _ ⟨t, ht, rfl⟩ + have h1 := hQ t ht + rw [← hFline t] at h1 + show ball (a + t • w) ‖q (a + t • w)‖ ⊆ U + rw [hqnorm] + have hδ : 0 < infDist (a + t • w) Uᶜ := hpos _ (hdisc t (sphere_subset_closedBall ht)) + have h2 : Real.exp (-(F (a + t • w)).re) ≤ infDist (a + t • w) Uᶜ := by + rw [← Real.le_log_iff_exp_le hδ] + linarith + apply (ball_subset_ball h2).trans + simpa using (ball_infDist_subset_compl (x := a + t • w) (s := Uᶜ)) + have hhull := hU.holomorphic_radius_bound ho hKc hKU hqan hrad a + (by simpa using mem_holomorphicHull_of_mem_disc hr hdisc (mem_closedBall_self hr.le)) + -- the radius bound at the center gives the distance bound + have hδa : 0 < infDist a Uᶜ := hpos a ha + have hle : ‖q a‖ ≤ infDist a Uᶜ := by + by_contra hlt + push Not at hlt + obtain ⟨y, hy, hdy⟩ := (infDist_lt_iff hc).mp hlt + exact hy (hhull (by rwa [mem_ball, dist_comm])) + rw [hqnorm, ← Real.le_log_iff_exp_le hδa] at hle + have hFa : F a = Q.eval 0 := by + have := hFline 0 + simpa using this + rw [hFa] at hle + linarith + +end BoundaryDistance + +section Pseudoconvex + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- An open set is pseudoconvex if it carries a continuous plurisubharmonic exhaustion function: one +whose sublevel sets inside the set are compact. -/ +@[expose] def IsPseudoconvex (U : Set E) : Prop := + IsOpen U ∧ ∃ φ : E → ℝ, ContinuousOn φ U ∧ PlurisubharmonicOn φ U ∧ + ∀ c : ℝ, IsCompact {z ∈ U | φ z ≤ c} + +/-- A pseudoconvex set is open. -/ +theorem IsPseudoconvex.isOpen {U : Set E} (h : IsPseudoconvex U) : IsOpen U := h.1 + +variable {n : ℕ} + +/-- **Domains of holomorphy in coordinates are pseudoconvex.** The exhaustion is the maximum +of the negative logarithm of the boundary distance and the norm. The coordinate-free version +is `IsDomainOfHolomorphy.isPseudoconvex`. -/ +theorem IsDomainOfHolomorphy.isPseudoconvex_fin {U : Set (Fin n → ℂ)} (hU : IsDomainOfHolomorphy U) + (ho : IsOpen U) : IsPseudoconvex U := by + refine ⟨ho, ?_⟩ + rcases eq_empty_or_nonempty Uᶜ with hc | hc + · have hU' : U = univ := compl_empty_iff.mp hc + refine ⟨fun z => ‖z‖, continuous_norm.continuousOn, plurisubharmonicOn_norm.mono (subset_univ + U), + fun c => ?_⟩ + convert isCompact_closedBall (0 : Fin n → ℂ) c using 1 + ext z + simp [hU'] + have hpos : ∀ z ∈ U, 0 < infDist z Uᶜ := fun z hz => + (infDist_pos_iff_notMem_closure hc).mp (by rwa [ho.isClosed_compl.closure_eq, notMem_compl_iff]) + refine ⟨fun z => max (-Real.log (infDist z Uᶜ)) ‖z‖, ?_, ?_, fun c => ?_⟩ + · exact (((continuous_infDist_pt Uᶜ).continuousOn.log fun z hz => (hpos z hz).ne').neg).sup + continuous_norm.continuousOn + · exact (hU.plurisubharmonicOn_neg_log_infDist ho).sup (plurisubharmonicOn_norm.mono + (subset_univ U)) + · have heq : {z ∈ U | max (-Real.log (infDist z Uᶜ)) ‖z‖ ≤ c} = + {z | Real.exp (-c) ≤ infDist z Uᶜ} ∩ closedBall 0 c := by + ext z + simp only [mem_ofPred_eq, mem_inter_iff, mem_closedBall, dist_zero_right, max_le_iff] + constructor + · rintro ⟨hz, h1, h2⟩ + refine ⟨?_, h2⟩ + rw [← Real.le_log_iff_exp_le (hpos z hz)] + linarith + · rintro ⟨h1, h2⟩ + have hδ : 0 < infDist z Uᶜ := (Real.exp_pos _).trans_le h1 + have hz : z ∈ U := by + by_contra hz + rw [infDist_zero_of_mem hz] at hδ + exact lt_irrefl _ hδ + refine ⟨hz, ?_, h2⟩ + rw [← Real.le_log_iff_exp_le hδ] at h1 + linarith + rw [heq] + refine isCompact_of_isClosed_isBounded ((isClosed_le continuous_const + (continuous_infDist_pt Uᶜ)).inter isClosed_closedBall) ?_ + exact isBounded_closedBall.subset inter_subset_right + +/-- **Continuity principle for affine analytic discs.** Along a continuous family of affine +analytic discs whose boundary circles stay in the set and whose initial disc lies in the set, +every disc of the family lies in the set. -/ +@[expose] def SatisfiesContinuityPrinciple (U : Set E) : Prop := + ∀ a b : ℝ → E, Continuous a → Continuous b → + (∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ sphere (0 : ℂ) 1, a t + ζ • b t ∈ U) → + (∀ ζ ∈ closedBall (0 : ℂ) 1, a 0 + ζ • b 0 ∈ U) → + ∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ closedBall (0 : ℂ) 1, a t + ζ • b t ∈ U + +/-- **Pseudoconvex sets satisfy the continuity principle ([Fritzsche–Grauert][FritzscheGrauert2002] +II.3.1).** -/ +theorem IsPseudoconvex.satisfiesContinuityPrinciple {U : Set E} (h : IsPseudoconvex U) : + SatisfiesContinuityPrinciple U := by + obtain ⟨hU, φ, hφc, hφpsh, hφex⟩ := h + intro a b ha hb hbd h0 + set p := clampIcc01 + have hpc : Continuous p := continuous_clampIcc01 + have hpI : ∀ t, p t ∈ Icc (0 : ℝ) 1 := clampIcc01_mem_Icc + have hpid : ∀ t ∈ Icc (0 : ℝ) 1, p t = t := fun t ht => clampIcc01_eq_of_mem_Icc ht + have hpp : ∀ t, p (p t) = p t := clampIcc01_idem + set Φ : ℝ × ℂ → E := fun q => a (p q.1) + q.2 • b (p q.1) with hΦ + have hΦc : Continuous Φ := by fun_prop + -- the compact set of boundary points and initial disc points + set K₀ := Φ '' (Icc (0 : ℝ) 1 ×ˢ sphere (0 : ℂ) 1) ∪ Φ '' ({0} ×ˢ closedBall (0 : ℂ) 1) with hK₀ + have hK₀c : IsCompact K₀ := + ((isCompact_Icc.prod (isCompact_sphere _ _)).image hΦc).union + ((isCompact_singleton.prod (isCompact_closedBall _ _)).image hΦc) + have hK₀U : K₀ ⊆ U := by + rintro _ (⟨⟨t, ζ⟩, ⟨ht, hζ⟩, rfl⟩ | ⟨⟨t, ζ⟩, ⟨ht, hζ⟩, rfl⟩) + · simp only [hΦ, hpid t ht] + exact hbd t ht ζ hζ + · simp only [mem_singleton_iff] at ht + simp only [hΦ, ht, hpid 0 (left_mem_Icc.mpr zero_le_one)] + exact h0 ζ hζ + obtain ⟨C, hC⟩ := hK₀c.exists_bound_of_continuousOn (hφc.mono hK₀U) + have hCle : ∀ z ∈ K₀, φ z ≤ C := fun z hz => (le_abs_self _).trans (by simpa using hC z hz) + set L := {z ∈ U | φ z ≤ C} with hL + have hLc : IsCompact L := hφex C + have hLU : L ⊆ U := fun z hz => hz.1 + -- the parameters whose disc lies in `U` + set W := {t : ℝ | ∀ ζ ∈ closedBall (0 : ℂ) 1, Φ (t, ζ) ∈ U} with hW + have hdisc : ∀ t ∈ W, ∀ ζ ∈ closedBall (0 : ℂ) 1, Φ (t, ζ) ∈ L := by + intro t ht ζ hζ + have hat : a (p t) ∈ U := by simpa [hΦ] using ht 0 (mem_closedBall_self zero_le_one) + have hsl : SubharmonicOn (fun ζ : ℂ => φ (a (p t) + ζ • b (p t))) (ball 0 1) := + (hφpsh.slice hat (b (p t))).mono fun ζ hζ => ht ζ (ball_subset_closedBall hζ) + have husc : UpperSemicontinuousOn (fun ζ : ℂ => φ (a (p t) + ζ • b (p t))) (closedBall 0 1) := + (hφc.comp (by fun_prop : Continuous fun ζ : ℂ => a (p t) + ζ • b (p t)).continuousOn + fun ζ hζ => ht ζ hζ).upperSemicontinuousOn + have hbdy : ∀ ζ ∈ sphere (0 : ℂ) 1, φ (a (p t) + ζ • b (p t)) ≤ C := by + intro ζ hζ + apply hCle + refine Or.inl ⟨(p t, ζ), ⟨hpI t, hζ⟩, ?_⟩ + simp only [hΦ, hpp] + exact ⟨ht ζ hζ, hsl.le_of_le_sphere zero_lt_one husc hbdy ζ hζ⟩ + have hWo : IsOpen W := by + rw [isOpen_iff_mem_nhds] + intro t ht + have := (isCompact_closedBall (0 : ℂ) 1).eventually_forall_of_forall_eventually + (x₀ := t) (P := fun t ζ => Φ (t, ζ) ∈ U) fun ζ hζ => + hΦc.continuousAt.preimage_mem_nhds (hU.mem_nhds (ht ζ hζ)) + exact this + have hWcl : IsClosed W := by + rw [← closure_subset_iff_isClosed] + intro t ht ζ hζ + have hne : NeBot (𝓝[W] t) := mem_closure_iff_nhdsWithin_neBot.mp ht + have htend : Tendsto (fun t' => Φ (t', ζ)) (𝓝[W] t) (𝓝 (Φ (t, ζ))) := + ((hΦc.comp (continuous_id.prodMk continuous_const)).tendsto t).mono_left nhdsWithin_le_nhds + have hmem : Φ (t, ζ) ∈ closure L := + mem_closure_of_tendsto htend (eventually_nhdsWithin_of_forall fun t' ht' => hdisc t' ht' ζ hζ) + rw [hLc.isClosed.closure_eq] at hmem + exact hLU hmem + have hW0 : (0 : ℝ) ∈ W := by + intro ζ hζ + simp only [hΦ, hpid 0 (left_mem_Icc.mpr zero_le_one)] + exact h0 ζ hζ + have hWuniv : W = univ := IsClopen.eq_univ (⟨hWcl, hWo⟩ : IsClopen W) ⟨0, hW0⟩ + intro t ht ζ hζ + have := (hWuniv ▸ mem_univ t : t ∈ W) ζ hζ + simpa [hΦ, hpid t ht] using this + +end Pseudoconvex + + +section HolomorphicContinuity + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- **Continuity principle for holomorphic discs (Kontinuitätssatz).** Along a continuous +family of holomorphic discs whose boundary circles stay in the set and whose initial disc lies +in the set, every disc of the family lies in the set. -/ +@[expose] def SatisfiesHolomorphicContinuityPrinciple (U : Set E) : Prop := + ∀ φ : ℝ → ℂ → E, Continuous (fun q : ℝ × ℂ => φ q.1 q.2) → + (∀ t ∈ Icc (0 : ℝ) 1, AnalyticOnNhd ℂ (φ t) (closedBall 0 1)) → + (∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ sphere (0 : ℂ) 1, φ t ζ ∈ U) → + (∀ ζ ∈ closedBall (0 : ℂ) 1, φ 0 ζ ∈ U) → + ∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ closedBall (0 : ℂ) 1, φ t ζ ∈ U + +/-- The holomorphic continuity principle contains the affine one. -/ +theorem SatisfiesHolomorphicContinuityPrinciple.satisfiesContinuityPrinciple {U : Set E} + (h : SatisfiesHolomorphicContinuityPrinciple U) : SatisfiesContinuityPrinciple U := by + intro a b ha hb hbd h0 + exact h (fun t ζ => a t + ζ • b t) (by fun_prop) + (fun t _ ζ _ => analyticAt_const.add (analyticAt_id.smul analyticAt_const)) hbd h0 + +variable {n : ℕ} + +/-- **Domains of holomorphy in coordinates satisfy the continuity principle for holomorphic +discs.** The coordinate-free version is +`IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple`. -/ +theorem IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple_fin {U : Set (Fin n → ℂ)} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : SatisfiesHolomorphicContinuityPrinciple U := by + intro φ hφc hφan hbd h0 + rcases eq_empty_or_nonempty Uᶜ with hc | hc + · have hU' : U = univ := compl_empty_iff.mp hc + intro t _ ζ _ + rw [hU'] + exact mem_univ _ + set p := clampIcc01 + have hpc : Continuous p := continuous_clampIcc01 + have hpI : ∀ t, p t ∈ Icc (0 : ℝ) 1 := clampIcc01_mem_Icc + have hpid : ∀ t ∈ Icc (0 : ℝ) 1, p t = t := fun t ht => clampIcc01_eq_of_mem_Icc ht + have hpp : ∀ t, p (p t) = p t := clampIcc01_idem + set Φ : ℝ × ℂ → Fin n → ℂ := fun q => φ (p q.1) q.2 with hΦ + have hΦc : Continuous Φ := hφc.comp ((hpc.comp continuous_fst).prodMk continuous_snd) + -- the compact set of boundary points and initial disc points + set K₀ := Φ '' (Icc (0 : ℝ) 1 ×ˢ sphere (0 : ℂ) 1) ∪ Φ '' ({0} ×ˢ closedBall (0 : ℂ) 1) with hK₀ + have hK₀c : IsCompact K₀ := + ((isCompact_Icc.prod (isCompact_sphere _ _)).image hΦc).union + ((isCompact_singleton.prod (isCompact_closedBall _ _)).image hΦc) + have hK₀U : K₀ ⊆ U := by + rintro _ (⟨⟨t, ζ⟩, ⟨ht, hζ⟩, rfl⟩ | ⟨⟨t, ζ⟩, ⟨ht, hζ⟩, rfl⟩) + · simp only [hΦ, hpid t ht] + exact hbd t ht ζ hζ + · simp only [mem_singleton_iff] at ht + simp only [hΦ, ht, hpid 0 (left_mem_Icc.mpr zero_le_one)] + exact h0 ζ hζ + have hK₀ne : K₀.Nonempty := + ⟨Φ (0, 1), Or.inl ⟨(0, 1), ⟨left_mem_Icc.mpr zero_le_one, by simp⟩, rfl⟩⟩ + -- the minimal boundary distance over that compact set + obtain ⟨z₀, hz₀K, hz₀min⟩ := + hK₀c.exists_isMinOn hK₀ne (continuous_infDist_pt Uᶜ).continuousOn + set m := infDist z₀ Uᶜ with hm + have hm0 : 0 < m := (infDist_pos_iff_notMem_closure hc).mp (by + rw [ho.isClosed_compl.closure_eq] + exact notMem_compl_iff.mpr (hK₀U hz₀K)) + have hmK : ∀ z ∈ K₀, m ≤ infDist z Uᶜ := fun z hz => hz₀min hz + have hmC : ‖(m : ℂ)‖ = m := by rw [Complex.norm_real, Real.norm_eq_abs, abs_of_pos hm0] + set L := {z : Fin n → ℂ | m ≤ infDist z Uᶜ} with hL + have hLc : IsClosed L := isClosed_le continuous_const (continuous_infDist_pt _) + have hLU : L ⊆ U := fun z hz => by + by_contra hzU + have : infDist z Uᶜ = 0 := infDist_zero_of_mem hzU + have hz' : m ≤ infDist z Uᶜ := hz + linarith + -- the parameters whose disc lies in `U` + set W := {t : ℝ | ∀ ζ ∈ closedBall (0 : ℂ) 1, Φ (t, ζ) ∈ U} with hW + have hdisc : ∀ t ∈ W, ∀ ζ ∈ closedBall (0 : ℂ) 1, Φ (t, ζ) ∈ L := by + intro t ht ζ hζ + have han : AnalyticOnNhd ℂ (φ (p t)) (closedBall 0 1) := hφan (p t) (hpI t) + have hdU : ∀ ζ ∈ closedBall (0 : ℂ) 1, φ (p t) ζ ∈ U := fun ζ hζ => ht ζ hζ + have hhull := mem_holomorphicHull_of_analytic_disc zero_lt_one han hdU hζ + have hKt : (φ (p t)) '' sphere 0 1 ⊆ K₀ := by + rintro _ ⟨ζ', hζ', rfl⟩ + exact Or.inl ⟨(p t, ζ'), ⟨hpI t, hζ'⟩, by simp only [hΦ, hpp]⟩ + have hKtc : IsCompact ((φ (p t)) '' sphere 0 1) := + (isCompact_sphere _ _).image_of_continuousOn (han.continuousOn.mono sphere_subset_closedBall) + have hrad := hU.holomorphic_radius_bound ho hKtc (hKt.trans hK₀U) (q := fun _ => (m : ℂ)) + analyticOnNhd_const (fun z hz => by + rw [hmC] + exact (ball_subset_ball (hmK z (hKt hz))).trans + (by simpa using ball_infDist_subset_compl (x := z) (s := Uᶜ))) _ hhull + rw [hmC] at hrad + show m ≤ infDist (φ (p t) ζ) Uᶜ + by_contra hlt + push Not at hlt + obtain ⟨y, hy, hdy⟩ := (infDist_lt_iff hc).mp hlt + exact hy (hrad (by rwa [mem_ball, dist_comm])) + have hWo : IsOpen W := by + rw [isOpen_iff_mem_nhds] + intro t ht + have := (isCompact_closedBall (0 : ℂ) 1).eventually_forall_of_forall_eventually + (x₀ := t) (P := fun t ζ => Φ (t, ζ) ∈ U) fun ζ hζ => + hΦc.continuousAt.preimage_mem_nhds (ho.mem_nhds (ht ζ hζ)) + exact this + have hWcl : IsClosed W := by + rw [← closure_subset_iff_isClosed] + intro t ht ζ hζ + have hne : NeBot (𝓝[W] t) := mem_closure_iff_nhdsWithin_neBot.mp ht + have htend : Tendsto (fun t' => Φ (t', ζ)) (𝓝[W] t) (𝓝 (Φ (t, ζ))) := + ((hΦc.comp (continuous_id.prodMk continuous_const)).tendsto t).mono_left nhdsWithin_le_nhds + have hmem : Φ (t, ζ) ∈ closure L := + mem_closure_of_tendsto htend (eventually_nhdsWithin_of_forall fun t' ht' => hdisc t' ht' ζ hζ) + rw [hLc.closure_eq] at hmem + exact hLU hmem + have hW0 : (0 : ℝ) ∈ W := by + intro ζ hζ + simp only [hΦ, hpid 0 (left_mem_Icc.mpr zero_le_one)] + exact h0 ζ hζ + have hWuniv : W = univ := IsClopen.eq_univ (⟨hWcl, hWo⟩ : IsClopen W) ⟨0, hW0⟩ + intro t ht ζ hζ + have := (hWuniv ▸ mem_univ t : t ∈ W) ζ hζ + simpa [hΦ, hpid t ht] using this + +end HolomorphicContinuity + +section Transport + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- Pseudoconvexity pulls back along a continuous linear equivalence. -/ +theorem IsPseudoconvex.of_image_equiv {U : Set E} (L : E ≃L[ℂ] F) + (h : IsPseudoconvex (L '' U)) : IsPseudoconvex U := by + obtain ⟨ho, φ, hφc, hφp, hφk⟩ := h + have hU : IsOpen U := by + have : U = L ⁻¹' (L '' U) := (L.injective.preimage_image U).symm + rw [this] + exact ho.preimage L.continuous + refine ⟨hU, fun z => φ (L z), hφc.comp L.continuous.continuousOn (mapsTo_image L U), ?_, + fun c => ?_⟩ + · have := hφp.comp_affine (L : E →L[ℂ] F) 0 + simp only [zero_add, ContinuousLinearEquiv.coe_coe] at this + exact this.mono fun z hz => mem_image_of_mem L hz + · have heq : {z ∈ U | φ (L z) ≤ c} = L.symm '' {w ∈ L '' U | φ w ≤ c} := by + ext z + constructor + · rintro ⟨hz, hc⟩ + exact ⟨L z, ⟨mem_image_of_mem L hz, hc⟩, L.symm_apply_apply z⟩ + · rintro ⟨w, ⟨hw, hc⟩, rfl⟩ + refine ⟨?_, by simpa using hc⟩ + obtain ⟨z, hz, rfl⟩ := hw + simpa using hz + rw [heq] + exact (hφk c).image L.symm.continuous + +/-- The holomorphic continuity principle pulls back along a continuous linear equivalence. -/ +theorem SatisfiesHolomorphicContinuityPrinciple.of_image_equiv {U : Set E} (L : E ≃L[ℂ] F) + (h : SatisfiesHolomorphicContinuityPrinciple (L '' U)) : + SatisfiesHolomorphicContinuityPrinciple U := by + intro φ hφc hφa hbd h0 t ht ζ hζ + have := h (fun t ζ => L (φ t ζ)) (L.continuous.comp hφc) + (fun t ht => (L.toContinuousLinearMap.analyticOnNhd univ).comp (hφa t ht) (mapsTo_univ _ _)) + (fun t ht ζ hζ => mem_image_of_mem L (hbd t ht ζ hζ)) + (fun ζ hζ => mem_image_of_mem L (h0 ζ hζ)) t ht ζ hζ + exact L.injective.mem_set_image.mp this + +variable [FiniteDimensional ℂ E] + +/-- **Domains of holomorphy are pseudoconvex.** The exhaustion is transported from the +coordinate version `IsDomainOfHolomorphy.isPseudoconvex_fin`. -/ +theorem IsDomainOfHolomorphy.isPseudoconvex {U : Set E} (hU : IsDomainOfHolomorphy U) + (ho : IsOpen U) : IsPseudoconvex U := by + let L := (Module.finBasis ℂ E).equivFunL + exact IsPseudoconvex.of_image_equiv L ((hU.image_equiv L).isPseudoconvex_fin (L.isOpenMap U ho)) + +/-- **Domains of holomorphy satisfy the continuity principle for holomorphic discs.** -/ +theorem IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple {U : Set E} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : SatisfiesHolomorphicContinuityPrinciple U := by + let L := (Module.finBasis ℂ E).equivFunL + exact SatisfiesHolomorphicContinuityPrinciple.of_image_equiv L + ((hU.image_equiv L).satisfiesHolomorphicContinuityPrinciple_fin (L.isOpenMap U ho)) + +/-- Domains of holomorphy satisfy the affine continuity principle. -/ +theorem IsDomainOfHolomorphy.satisfiesContinuityPrinciple {U : Set E} + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) : SatisfiesContinuityPrinciple U := + (hU.satisfiesHolomorphicContinuityPrinciple ho).satisfiesContinuityPrinciple + +end Transport + +section Hartogs + +variable {E' : Type*} [NormedAddCommGroup E'] [NormedSpace ℂ E'] + +/-- **Hartogs convexity** for cylinder figures: whenever a Hartogs cylinder over an open +preconnected base, with disc fibers over a nonempty open part of the base, lies in the set, so +does the filled cylinder. -/ +@[expose] def IsHartogsConvex (U : Set (E' × ℂ)) : Prop := + ∀ (D D₀ : Set E') (ρ R : ℝ), IsOpen D → IsPreconnected D → IsOpen D₀ → D₀.Nonempty → + D₀ ⊆ D → 0 ≤ ρ → ρ < R → hartogsCylinder D D₀ ρ R ⊆ U → D ×ˢ ball 0 R ⊆ U + +/-- **The continuity principle implies Hartogs convexity ([Fritzsche–Grauert][FritzscheGrauert2002] +II.1.5).** The disc +fibers are slid along a path in the base from the part carrying full discs. -/ +theorem SatisfiesContinuityPrinciple.isHartogsConvex {U : Set (E' × ℂ)} + (h : SatisfiesContinuityPrinciple U) : IsHartogsConvex U := by + intro D D₀ ρ R hD hDc hD₀ hne hsub hρ hρR hcyl + rintro ⟨w, ζ₀⟩ ⟨hw, hζ₀⟩ + obtain ⟨w₀, hw₀⟩ := hne + have hζ₀' : ‖ζ₀‖ < R := mem_ball_zero_iff.mp hζ₀ + obtain ⟨R', hR'₁, hR'₂⟩ := exists_between (max_lt hρR hζ₀') + have hρR' : ρ < R' := (le_max_left _ _).trans_lt hR'₁ + have hζR' : ‖ζ₀‖ < R' := (le_max_right _ _).trans_lt hR'₁ + have hR'pos : 0 < R' := hρ.trans_lt hρR' + have hpath : JoinedIn D w₀ w := + (hD.isConnected_iff_isPathConnected.mp ⟨⟨w, hw⟩, hDc⟩).joinedIn w₀ (hsub hw₀) w hw + set γ := hpath.somePath with hγ + have hγD : ∀ t, γ.extend t ∈ D := fun t => by + have : γ.extend t ∈ range γ := by + rw [← Path.extend_range] + exact mem_range_self t + obtain ⟨s, hs⟩ := this + rw [← hs] + exact hpath.somePath_mem s + set a : ℝ → E' × ℂ := fun t => (γ.extend t, (0 : ℂ)) with ha + set b : ℝ → E' × ℂ := fun _ => ((0 : E'), (R' : ℂ)) with hb + have hpt : ∀ (t : ℝ) (ζ : ℂ), a t + ζ • b t = (γ.extend t, ζ * R') := fun t ζ => by + simp [ha, hb] + have hac : Continuous a := (γ.continuous_extend).prodMk continuous_const + have hbc : Continuous b := continuous_const + have hbd : ∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ sphere (0 : ℂ) 1, a t + ζ • b t ∈ U := by + intro t _ ζ hζ + rw [hpt] + apply hcyl + have hζn : ‖ζ * R'‖ = R' := by + rw [norm_mul, mem_sphere_zero_iff_norm.mp hζ, one_mul, Complex.norm_real, + Real.norm_eq_abs, abs_of_pos hR'pos] + refine Or.inl ⟨hγD t, ?_, ?_⟩ + · rw [mem_ball_zero_iff, hζn]; exact hR'₂ + · rw [mem_closedBall_zero_iff, hζn]; exact not_le.mpr hρR' + have h0 : ∀ ζ ∈ closedBall (0 : ℂ) 1, a 0 + ζ • b 0 ∈ U := by + intro ζ hζ + rw [hpt] + apply hcyl + refine Or.inr ⟨by rw [Path.extend_zero]; exact hw₀, ?_⟩ + rw [mem_ball_zero_iff, norm_mul, Complex.norm_real, Real.norm_eq_abs, abs_of_pos hR'pos] + calc ‖ζ‖ * R' ≤ 1 * R' := + mul_le_mul_of_nonneg_right (mem_closedBall_zero_iff.mp hζ) hR'pos.le + _ < R := by linarith + have hfin := h a b hac hbc hbd h0 1 (right_mem_Icc.mpr zero_le_one) (ζ₀ / R') (by + rw [mem_closedBall_zero_iff, norm_div, Complex.norm_real, Real.norm_eq_abs, + abs_of_pos hR'pos, div_le_one hR'pos] + exact hζR'.le) + rw [hpt, Path.extend_one, div_mul_cancel₀ _ (by exact_mod_cast hR'pos.ne')] at hfin + exact hfin + +/-- Pseudoconvex sets in a product with `ℂ` are Hartogs convex. -/ +theorem IsPseudoconvex.isHartogsConvex {U : Set (E' × ℂ)} (h : IsPseudoconvex U) : + IsHartogsConvex U := + h.satisfiesContinuityPrinciple.isHartogsConvex + +end Hartogs + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RealUniqueness.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RealUniqueness.lean new file mode 100644 index 0000000000..61ec4d15c9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RealUniqueness.lean @@ -0,0 +1,129 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.IsolatedZeros +public import Mathlib.Analysis.Complex.CauchyIntegral + +import Mathlib.Analysis.SpecificLimits.Basic + +/-! +# Analytic uniqueness from positive real parameters + +This file records uniqueness principles for holomorphic functions whose values are known only on +the positive real locus. They are useful for transporting certain identities proved using real +probability measures to their complex analytic continuations. + +## Main results + +`AnalyticOnNhd.eqOn_of_eventuallyEq_ofReal` is one-variable uniqueness from agreement on a real +germ, on a connected continuation domain. `AnalyticOnNhd.eq_of_eqOn_posReal` is uniqueness of +entire functions of one variable from the positive reals. `AnalyticOnNhd.eq_of_eqOn_posReal_pi` +is the corresponding statement for entire functions of finitely many variables. All three +results allow values in any complex normed space; completeness of the target is not needed. +-/ + +open Complex Set Filter +open scoped Topology + +public noncomputable section RealUniqueness + +variable {H : Type*} [NormedAddCommGroup H] [NormedSpace ℂ H] + +/-- Local one-variable uniqueness from agreement on a real germ. This is the form useful when the +functions are only analytic on a connected continuation domain rather than entire. -/ +theorem AnalyticOnNhd.eqOn_of_eventuallyEq_ofReal {U : Set ℂ} {F G : ℂ → H} + {x₀ : ℝ} (hF : AnalyticOnNhd ℂ F U) (hG : AnalyticOnNhd ℂ G U) + (hU : IsPreconnected U) (hx₀ : (x₀ : ℂ) ∈ U) + (hEq : ∀ᶠ x : ℝ in 𝓝 x₀, F (x : ℂ) = G (x : ℂ)) : Set.EqOn F G U := by + let wR : ℕ → ℝ := fun n ↦ x₀ + (n + 1 : ℝ)⁻¹ + let w : ℕ → ℂ := fun n ↦ (wR n : ℂ) + have hwR : Tendsto wR atTop (𝓝 x₀) := by + simpa [wR] using tendsto_const_nhds.add + (tendsto_one_div_add_atTop_nhds_zero_nat (𝕜 := ℝ)) + have hw : Tendsto w atTop (𝓝 (x₀ : ℂ)) := by + exact Complex.continuous_ofReal.continuousAt.tendsto.comp hwR + have hwne : ∀ n, w n ≠ (x₀ : ℂ) := by + intro n h + have hr : x₀ + (n + 1 : ℝ)⁻¹ = x₀ := Complex.ofReal_injective h + have : (0 : ℝ) < (n + 1 : ℝ)⁻¹ := by positivity + linarith + have hwithin : Tendsto w atTop (𝓝[≠] (x₀ : ℂ)) := + tendsto_nhdsWithin_iff.mpr ⟨hw, Eventually.of_forall hwne⟩ + have hagree : ∀ᶠ n : ℕ in atTop, F (w n) = G (w n) := by + filter_upwards [hwR.eventually hEq] with n hn + exact hn + exact hF.eqOn_of_preconnected_of_frequently_eq hG hU hx₀ + (hwithin.frequently hagree.frequently) + +/-- Two entire functions of one complex variable which agree at every positive real number agree +everywhere. -/ +theorem AnalyticOnNhd.eq_of_eqOn_posReal {F G : ℂ → H} + (hF : AnalyticOnNhd ℂ F univ) (hG : AnalyticOnNhd ℂ G univ) + (hEq : ∀ x : ℝ, 0 < x → F (x : ℂ) = G (x : ℂ)) : F = G := by + have hEq' : ∀ᶠ x : ℝ in 𝓝 1, F (x : ℂ) = G (x : ℂ) := by + filter_upwards [eventually_gt_nhds (show (0 : ℝ) < 1 by norm_num)] with x hx + exact hEq x hx + have h := hF.eqOn_of_eventuallyEq_ofReal hG isPreconnected_univ (Set.mem_univ _) hEq' + exact funext fun z => h (Set.mem_univ z) + +/-- Two entire functions of finitely many complex variables which agree on all vectors of strictly +positive real parameters agree everywhere. No complex-open agreement hypothesis is needed. -/ +theorem AnalyticOnNhd.eq_of_eqOn_posReal_pi {ι : Type*} [Fintype ι] + {F G : (ι → ℂ) → H} (hF : AnalyticOnNhd ℂ F univ) + (hG : AnalyticOnNhd ℂ G univ) + (hEq : ∀ b : ι → ℝ, (∀ i, 0 < b i) → + F (fun i ↦ (b i : ℂ)) = G (fun i ↦ (b i : ℂ))) : F = G := by + classical + have hstep : ∀ s : Finset ι, ∀ b : ι → ℂ, + (∀ i, i ∉ s → ∃ x : ℝ, 0 < x ∧ b i = (x : ℂ)) → F b = G b := by + intro s + induction s using Finset.induction with + | empty => + intro b hb + choose r hr hbr using fun i ↦ hb i (by simp) + have hb_eq : b = fun i ↦ (r i : ℂ) := by + funext i + exact hbr i + rw [hb_eq] + exact hEq r hr + | @insert a s ha ih => + intro b hb + let L : ℂ → (ι → ℂ) := fun w ↦ Function.update b a w + have hL : AnalyticOnNhd ℂ L univ := by + intro w _ + apply AnalyticAt.pi + intro i + by_cases hia : i = a + · subst i + have heq : (fun x : ℂ ↦ L x a) = id := by + funext x + simp [L] + rw [heq] + exact analyticAt_id + · simpa [L, hia] using + (analyticAt_const : AnalyticAt ℂ (fun _ : ℂ ↦ b i) w) + have hslices : (fun w ↦ F (L w)) = (fun w ↦ G (L w)) := by + apply AnalyticOnNhd.eq_of_eqOn_posReal + · intro w _ + exact (hF (L w) (mem_univ _)).comp_of_eq (hL w (mem_univ _)) rfl + · intro w _ + exact (hG (L w) (mem_univ _)).comp_of_eq (hL w (mem_univ _)) rfl + · intro x hx + apply ih + intro i his + by_cases hia : i = a + · subst i + exact ⟨x, hx, by simp [L]⟩ + · simpa [L, hia] using hb i (by simp [his, hia]) + have := congrFun hslices (b a) + simpa [L] using this + funext b + exact hstep Finset.univ b (by simp) + +end RealUniqueness + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reindex.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reindex.lean new file mode 100644 index 0000000000..c9974ed3da --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reindex.lean @@ -0,0 +1,90 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives + +/-! +# Reindexing finite complex coordinate spaces + +Coordinate derivatives commute with renaming coordinates. The polydisc Cauchy formula is +transported along any enumeration of a finite index type; its value is independent of that +enumeration whenever the Cauchy hypotheses hold. + +## Main results + +`partialDeriv_reindex` and `iteratedPartialDeriv_reindex` transport coordinate derivatives along a +renaming of coordinates. `two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul_reindex` transports +the polydisc Cauchy formula along any enumeration of a finite index type. +-/ + +public section + +open Complex Function MeasureTheory Set +open scoped Real + +namespace SeveralComplexVariables + +variable {ι κ F : Type*} [Fintype ι] [DecidableEq ι] [Fintype κ] [DecidableEq κ] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +omit [Fintype ι] [Fintype κ] in +/-- Renaming coordinates renames a coordinate derivative by the inverse equivalence. -/ +theorem partialDeriv_reindex (e : κ ≃ ι) (f : (κ → ℂ) → F) (z : ι → ℂ) (i : ι) : + partialDeriv i (fun w => f (w ∘ e)) z = partialDeriv (e.symm i) f (z ∘ e) := by + change deriv (fun w => f (update z i w ∘ e)) (z i) = + deriv (fun w => f (update (z ∘ e) (e.symm i) w)) ((z ∘ e) (e.symm i)) + simp only [update_comp_equiv, comp_apply, e.apply_symm_apply] + +omit [Fintype ι] [Fintype κ] in +/-- All iterated coordinate derivatives are natural under coordinate reindexing. -/ +theorem iteratedPartialDeriv_reindex (e : κ ≃ ι) (f : (κ → ℂ) → F) (is : List ι) + (z : ι → ℂ) : + iteratedPartialDeriv is (fun w => f (w ∘ e)) z = + iteratedPartialDeriv (is.map e.symm) f (z ∘ e) := by + induction is generalizing z with + | nil => rfl + | cons i is ih => + simp only [iteratedPartialDeriv, List.map_cons] + rw [show iteratedPartialDeriv is (fun w => f (w ∘ e)) = + fun w => iteratedPartialDeriv (is.map e.symm) f (w ∘ e) by funext w; exact ih w] + exact partialDeriv_reindex e _ z i + +variable [CompleteSpace F] + +omit [Fintype ι] in +/-- Cauchy's polydisc formula for an arbitrary finite index type, integrated using any enumeration +by `Fin n`. No nonemptiness or positive-dimension hypothesis is needed. -/ +theorem two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul_reindex {n : ℕ} (e : Fin n ≃ ι) + {f : (ι → ℂ) → F} {c w : ι → ℂ} {R : ι → ℝ} + (hR : ∀ i, 0 < R i) (hw : ∀ i, ‖w i - c i‖ < R i) + (hfc : ContinuousOn f (closedPolydisc c R)) + (hfa : ∀ z ∈ closedPolydisc c R, ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + ((2 * π * I : ℂ) ^ n)⁻¹ • torusIntegral + (fun z => (∏ i, (z i - w (e i))⁻¹) • f (z ∘ e.symm)) (c ∘ e) (R ∘ e) = f w := by + have hm : MapsTo (fun z => z ∘ e.symm) + (closedPolydisc (c ∘ e) (R ∘ e)) (closedPolydisc c R) := by + intro z hz j hj + simpa only [comp_apply, e.apply_symm_apply] using hz (e.symm j) (mem_univ _) + have hc := hfc.comp (continuous_pi (fun j => continuous_apply (e.symm j))).continuousOn hm + have ha : ∀ z ∈ closedPolydisc (c ∘ e) (R ∘ e), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x ∘ e.symm)) (z i) := by + intro z hz i + simpa only [update_comp_equiv, Equiv.symm_symm, comp_apply, e.symm_apply_apply] using + hfa (z ∘ e.symm) (hm hz) (e i) + have hew : (w ∘ e) ∘ e.symm = w := by funext j; simp + simpa only [comp_apply, hew] using + two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul (f := fun z => f (z ∘ e.symm)) + (c := c ∘ e) (w := w ∘ e) (R := R ∘ e) (fun i => hR (e i)) + (fun i => hw (e i)) hc ha + +end SeveralComplexVariables + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt.lean new file mode 100644 index 0000000000..633d852e55 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt.lean @@ -0,0 +1,295 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.Convex.PathConnected +public import Mathlib.Analysis.Convex.SpecificFunctions.Basic +public import Mathlib.Analysis.Convex.Topology + +/-! +# Reinhardt sets + +`IsReinhardt` expresses invariance under independent rotations of the complex coordinates. +`IsCompleteReinhardt` additionally permits independent shrinking of their moduli. Both are +properties of sets: openness, connectedness and nonemptiness are separate hypotheses. +Completeness here is unrelated to metric completeness. A nonempty complete Reinhardt set +contains the origin and is path connected, without an openness assumption. + +`logarithmicImage` is the inverse image of a set under coordinatewise real exponentiation, +viewed in complex coordinates. `IsLogarithmicallyConvex` asks for this real set to be convex. +For complete Reinhardt sets, logarithmic image commutes with taking the interior; both +completeness and logarithmic convexity are preserved by taking interiors. + +The centre is the origin in the specified coordinates. To express the property about `a`, apply +the predicate to `{z | a + z ∈ U}`. Arbitrary complex linear changes of coordinates need not +preserve either property. These definitions and results also allow empty coordinate types; no +finiteness assumption is needed for the basic geometry in the product topology. + +References: [Korevaar–Wiegerinck][KorevaarWiegerinck2017], Definitions 2.3.2 and 2.3.4; +[Lebl][Lebl2026], Section 1.2; [Boas][Boas2013] (2013), Sections 2.1--2.2. Polydisc examples are +provided in `SeveralComplexVariables.Polydisc`. + +## Main definitions + +* `IsReinhardt`: A set is Reinhardt if membership is preserved by independent coordinate rotations. +* `IsCompleteReinhardt`: A set is complete Reinhardt if membership is preserved by decreasing + coordinate moduli. +* `logarithmicImage`: The logarithmic image uses the positive real slice, avoiding logarithms at + zero. +* `IsLogarithmicallyConvex`: Logarithmic convexity means convexity of the logarithmic image. + +## Main results + +* `IsCompleteReinhardt.isReinhardt`: Every complete Reinhardt set is Reinhardt. +* `IsCompleteReinhardt.isPathConnected`: Every nonempty complete Reinhardt set is path connected in + the product topology. +* `IsCompleteReinhardt.interior`: The interior of a complete Reinhardt set is complete Reinhardt. +* `IsCompleteReinhardt.logarithmicImage_interior`: For complete Reinhardt sets, logarithmic image + commutes with taking the interior. +* `IsLogarithmicallyConvex.interior`: The interior of a complete logarithmically convex Reinhardt + set is logarithmically convex. +* `isOpen_logarithmicImage`: The logarithmic image of an open set is open. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +* [J. Lebl, *Tasty Bits of Several Complex Variables: A Whirlwind Tour of the Subject*][Lebl2026] +-/ + +public noncomputable section + +open Filter Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} {U V : Set (ι → ℂ)} + +/-- A set is Reinhardt if membership is preserved by independent coordinate rotations. The centre is +zero; openness, connectedness and nonemptiness are not required. -/ +@[expose] def IsReinhardt (U : Set (ι → ℂ)) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃w⦄, (∀ i, ‖w i‖ = ‖z i‖) → w ∈ U + +/-- A set is complete Reinhardt if membership is preserved by decreasing coordinate moduli. This +includes rotations and allows zero coordinates; no topological hypotheses are imposed. -/ +@[expose] def IsCompleteReinhardt (U : Set (ι → ℂ)) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃w⦄, (∀ i, ‖w i‖ ≤ ‖z i‖) → w ∈ U + +/-- The empty set is Reinhardt. -/ +@[simp] theorem isReinhardt_empty : IsReinhardt (∅ : Set (ι → ℂ)) := + fun _ hz => hz.elim + +/-- The whole coordinate space is Reinhardt. -/ +@[simp] theorem isReinhardt_univ : IsReinhardt (univ : Set (ι → ℂ)) := + fun _ _ _ _ => mem_univ _ + +/-- The empty set is complete Reinhardt. -/ +@[simp] theorem isCompleteReinhardt_empty : IsCompleteReinhardt (∅ : Set (ι → ℂ)) := + fun _ hz => hz.elim + +/-- The whole coordinate space is complete Reinhardt. -/ +@[simp] theorem isCompleteReinhardt_univ : IsCompleteReinhardt (univ : Set (ι → ℂ)) := + fun _ _ _ _ => mem_univ _ + +/-- Every complete Reinhardt set is Reinhardt. -/ +theorem IsCompleteReinhardt.isReinhardt (hU : IsCompleteReinhardt U) : IsReinhardt U := + fun _ hz _ hw => hU hz (fun i => (hw i).le) + +/-- With no coordinates, every set is complete Reinhardt. -/ +theorem isCompleteReinhardt_of_isEmpty [IsEmpty ι] (U : Set (ι → ℂ)) : + IsCompleteReinhardt U := by + intro z hz w _ + simpa only [Subsingleton.elim w z] using hz + +/-- Intersections preserve Reinhardt symmetry. -/ +theorem IsReinhardt.inter (hU : IsReinhardt U) (hV : IsReinhardt V) : + IsReinhardt (U ∩ V) := + fun _ hz _ hw => ⟨hU hz.1 hw, hV hz.2 hw⟩ + +/-- Unions preserve Reinhardt symmetry, without any connectedness requirement. -/ +theorem IsReinhardt.union (hU : IsReinhardt U) (hV : IsReinhardt V) : + IsReinhardt (U ∪ V) := + fun _ hz _ hw => hz.elim (fun h => Or.inl (hU h hw)) (fun h => Or.inr (hV h hw)) + +/-- Arbitrary unions of Reinhardt sets are Reinhardt. -/ +theorem isReinhardt_iUnion {κ : Sort*} {S : κ → Set (ι → ℂ)} + (hS : ∀ k, IsReinhardt (S k)) : IsReinhardt (⋃ k, S k) := by + intro z hz w hw + obtain ⟨k, hk⟩ := mem_iUnion.mp hz + exact mem_iUnion.mpr ⟨k, hS k hk hw⟩ + +/-- Intersections preserve the complete Reinhardt property. -/ +theorem IsCompleteReinhardt.inter (hU : IsCompleteReinhardt U) + (hV : IsCompleteReinhardt V) : IsCompleteReinhardt (U ∩ V) := + fun _ hz _ hw => ⟨hU hz.1 hw, hV hz.2 hw⟩ + +/-- Unions preserve the complete Reinhardt property. -/ +theorem IsCompleteReinhardt.union (hU : IsCompleteReinhardt U) + (hV : IsCompleteReinhardt V) : IsCompleteReinhardt (U ∪ V) := + fun _ hz _ hw => hz.elim (fun h => Or.inl (hU h hw)) (fun h => Or.inr (hV h hw)) + +/-- Arbitrary unions of complete Reinhardt sets are complete Reinhardt. -/ +theorem isCompleteReinhardt_iUnion {κ : Sort*} {S : κ → Set (ι → ℂ)} + (hS : ∀ k, IsCompleteReinhardt (S k)) : IsCompleteReinhardt (⋃ k, S k) := by + intro z hz w hw + obtain ⟨k, hk⟩ := mem_iUnion.mp hz + exact mem_iUnion.mpr ⟨k, hS k hk hw⟩ + +/-- Multiplying each coordinate by a complex number of modulus one preserves a Reinhardt set. -/ +theorem IsReinhardt.mul_mem (hU : IsReinhardt U) {z : ι → ℂ} (hz : z ∈ U) + {a : ι → ℂ} (ha : ∀ i, ‖a i‖ = 1) : (fun i => a i * z i) ∈ U := + hU hz (fun i => by simp [ha i]) + +/-- Independent complex contractions preserve a complete Reinhardt set. -/ +theorem IsCompleteReinhardt.mul_mem (hU : IsCompleteReinhardt U) {z : ι → ℂ} + (hz : z ∈ U) {a : ι → ℂ} (ha : ∀ i, ‖a i‖ ≤ 1) : (fun i => a i * z i) ∈ U := by + apply hU hz + intro i + rw [norm_mul] + exact mul_le_of_le_one_left (norm_nonneg _) (ha i) + +/-- A nonempty complete Reinhardt set contains the origin. -/ +theorem IsCompleteReinhardt.zero_mem (hU : IsCompleteReinhardt U) (hne : U.Nonempty) : + 0 ∈ U := by + obtain ⟨z, hz⟩ := hne + exact hU hz (fun i => by simp) + +/-- A complete Reinhardt set is star-convex about the origin, including when it is empty. -/ +theorem IsCompleteReinhardt.starConvex (hU : IsCompleteReinhardt U) : + StarConvex ℝ (0 : ι → ℂ) U := by + intro z hz a b ha hb hab + simp only [smul_zero, zero_add] + apply hU hz + intro i + change ‖b • z i‖ ≤ ‖z i‖ + rw [norm_smul, Real.norm_eq_abs, abs_of_nonneg hb] + exact mul_le_of_le_one_left (norm_nonneg _) (by linarith) + +/-- Every nonempty complete Reinhardt set is path connected in the product topology. -/ +theorem IsCompleteReinhardt.isPathConnected (hU : IsCompleteReinhardt U) + (hne : U.Nonempty) : IsPathConnected U := + hU.starConvex.isPathConnected (hU.zero_mem hne) + +/-- Every nonempty complete Reinhardt set is connected. -/ +theorem IsCompleteReinhardt.isConnected (hU : IsCompleteReinhardt U) + (hne : U.Nonempty) : IsConnected U := + (hU.isPathConnected hne).isConnected + +/-- Complete Reinhardt sets are preconnected; this statement also covers the empty set. -/ +theorem IsCompleteReinhardt.isPreconnected (hU : IsCompleteReinhardt U) : + IsPreconnected U := by + rcases U.eq_empty_or_nonempty with rfl | hne + · exact isPreconnected_empty + · exact (hU.isConnected hne).isPreconnected + +/-- The logarithmic image uses the positive real slice, avoiding logarithms at zero. For a Reinhardt +set this is its usual image under coordinatewise log modulus. -/ +@[expose] def logarithmicImage (U : Set (ι → ℂ)) : Set (ι → ℝ) := + {x | (fun i => (Real.exp (x i) : ℂ)) ∈ U} + +/-- Logarithmic convexity means convexity of the logarithmic image. Reinhardt symmetry, +completeness, openness and nonemptiness remain separate hypotheses. -/ +@[expose] def IsLogarithmicallyConvex (U : Set (ι → ℂ)) : Prop := + Convex ℝ (logarithmicImage U) + +/-- Membership of the logarithmic image is membership of the exponential coordinate vector. -/ +@[simp] theorem mem_logarithmicImage {x : ι → ℝ} : + x ∈ logarithmicImage U ↔ (fun i => (Real.exp (x i) : ℂ)) ∈ U := Iff.rfl + +/-- The empty set is logarithmically convex. -/ +@[simp] theorem isLogarithmicallyConvex_empty : + IsLogarithmicallyConvex (∅ : Set (ι → ℂ)) := convex_empty + +/-- The whole coordinate space is logarithmically convex. -/ +@[simp] theorem isLogarithmicallyConvex_univ : + IsLogarithmicallyConvex (univ : Set (ι → ℂ)) := convex_univ + +/-- Intersections preserve logarithmic convexity. -/ +theorem IsLogarithmicallyConvex.inter (hU : IsLogarithmicallyConvex U) + (hV : IsLogarithmicallyConvex V) : IsLogarithmicallyConvex (U ∩ V) := + Convex.inter hU hV + +/-- The logarithmic image of an open set is open. -/ +theorem isOpen_logarithmicImage (hU : IsOpen U) : IsOpen (logarithmicImage U) := + hU.preimage (continuous_pi fun i => Complex.continuous_ofReal.comp + (Real.continuous_exp.comp (continuous_apply i))) + +/-- The interior of a complete Reinhardt set is complete Reinhardt. The proof also handles points on +coordinate hyperplanes, where coordinate contractions need not be open maps. -/ +theorem IsCompleteReinhardt.interior (hU : IsCompleteReinhardt U) : + IsCompleteReinhardt (_root_.interior U) := by + classical + intro z hz w hw + let f : (ι → ℂ) → (ι → ℂ) := fun v i => + if z i = 0 then v i else (max ‖z i‖ ‖v i‖ / ‖z i‖) • z i + have hf : Continuous f := by + apply continuous_pi + intro i + dsimp [f] + split_ifs + · exact continuous_apply i + · exact ((continuous_const.max (continuous_apply i).norm).div_const _).smul continuous_const + have hfw : f w = z := by + ext i + dsimp [f] + split_ifs with hi + · have hwi : w i = 0 := norm_eq_zero.mp (le_antisymm + (by simpa [hi] using hw i) (norm_nonneg _)) + simp [hi, hwi] + · simp [max_eq_left (hw i), norm_ne_zero_iff.mpr hi] + have hnorm (v : ι → ℂ) (i : ι) : ‖v i‖ ≤ ‖f v i‖ := by + dsimp [f] + split_ifs with hi + · exact le_rfl + · rw [norm_mul, Complex.norm_real, Real.norm_eq_abs, abs_of_nonneg + (div_nonneg (le_max_of_le_left (norm_nonneg _)) (norm_nonneg _)), + div_mul_cancel₀ _ (norm_ne_zero_iff.mpr hi)] + exact le_max_right _ _ + apply mem_interior_iff_mem_nhds.mpr + have hn : ∀ᶠ v in 𝓝 w, f v ∈ _root_.interior U := + (hf.continuousAt : ContinuousAt f w) (by simpa [hfw] using isOpen_interior.mem_nhds hz) + filter_upwards [hn] with v hv + exact hU (interior_subset hv) (hnorm v) + +/-- For complete Reinhardt sets, logarithmic image commutes with taking the interior. -/ +theorem IsCompleteReinhardt.logarithmicImage_interior (hU : IsCompleteReinhardt U) : + logarithmicImage (_root_.interior U) = _root_.interior (logarithmicImage U) := by + apply Subset.antisymm + · exact (isOpen_logarithmicImage isOpen_interior).subset_interior_iff.mpr + (fun x hx => (interior_subset hx : (fun i => (Real.exp (x i) : ℂ)) ∈ U)) + · intro x hx + change (fun i => (Real.exp (x i) : ℂ)) ∈ _root_.interior U + let z : ι → ℂ := fun i => Real.exp (x i) + have hc : ContinuousAt (fun w : ι → ℂ => fun i => Real.log ‖w i‖) z := by + apply continuousAt_pi.mpr + intro i + apply (continuousAt_apply i z).norm.log + simp [z, Real.exp_ne_zero] + have heq : (fun i => Real.log ‖z i‖) = x := by + ext i + simp [z] + have hn : ∀ᶠ w in 𝓝 z, (fun i => Real.log ‖w i‖) ∈ logarithmicImage U := + hc (by simpa [heq] using mem_interior_iff_mem_nhds.mp hx) + apply mem_interior_iff_mem_nhds.mpr + filter_upwards [hn] with w hw + apply hU hw + intro i + by_cases hi : ‖w i‖ = 0 + · simp [hi] + · simp [Real.exp_log (lt_of_le_of_ne (norm_nonneg _) (Ne.symm hi))] + +/-- The interior of a complete logarithmically convex Reinhardt set is logarithmically convex. -/ +theorem IsLogarithmicallyConvex.interior (hU : IsLogarithmicallyConvex U) + (hc : IsCompleteReinhardt U) : IsLogarithmicallyConvex (_root_.interior U) := by + unfold IsLogarithmicallyConvex + rw [hc.logarithmicImage_interior] + exact (show Convex ℝ (logarithmicImage U) from hU).interior + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean new file mode 100644 index 0000000000..276174fcf5 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean @@ -0,0 +1,250 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic + +/-! +# Extension to Reinhardt hulls + +Power series extend analytic functions from complete Reinhardt domains. More generally, a +connected Reinhardt domain meeting every coordinate hyperplane has a power-series extension to +its geometric logarithmic hull, even if it does not contain the origin. The hull here includes +zero coordinates. This is extension between subsets of ℂⁿ; no abstract envelope or Riemann +domain is constructed. + +Laurent expansion gives power-series extension to logarithmic and complete Reinhardt hulls. The +geometric inclusion of the complete hull in the logarithmic hull for open Reinhardt sets +containing zero is proved independently of Laurent expansion. Analyticity of the extended sums +follows from the proved arbitrary-coefficient convergence theorem. References: +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Corollary 2.4.3, Theorem 2.5.1, Corollary +2.5.2, and Theorem 2.8.2. + +## Main results + +`IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum` is the Taylor series of a +holomorphic function on a complete Reinhardt domain. +`exists_extension_logarithmicReinhardtHull_of_zero_mem` and `exists_extension_completeReinhardtHull` +extend to the logarithmic and complete hulls. +`completeReinhardtHull_subset_logarithmicReinhardtHull` is the geometric inclusion when the set is +open and contains the origin. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology NNReal + +namespace SeveralComplexVariables + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Banach-valued normalized multivariate Taylor coefficients at the origin. -/ +@[expose] def taylorCoefficientsAtZero (f : (Fin n → ℂ) → F) : MvPowerSeries (Fin n) F := + fun m => (∏ i, (m i).factorial : ℂ)⁻¹ • multiIndexDeriv m f 0 + +/-- On a complete Reinhardt open set, the Taylor series at zero represents the function, and the +entire set lies inside its absolute-convergence domain. The proof applies the existing polydisc +Taylor theorem and coefficient estimates. -/ +theorem IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsCompleteReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) : + U ⊆ powerSeriesConvergenceDomain (taylorCoefficientsAtZero f) ∧ + EqOn (powerSeriesSum (taylorCoefficientsAtZero f)) f U := by + classical + have hpoint : ∀ z ∈ U, + Summable (fun m : Fin n →₀ ℕ => ‖(∏ i, z i ^ m i) • taylorCoefficientsAtZero f m‖) ∧ + HasSum (fun m : Fin n →₀ ℕ => (∏ i, z i ^ m i) • taylorCoefficientsAtZero f m) (f z) := by + intro z hz + obtain ⟨r, hrU, hzr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho hz + have hr : ∀ i, (0 : ℝ) < r i := fun i => lt_of_le_of_lt (norm_nonneg _) (hzr i) + have hBU : closedPolydisc 0 (fun i => (r i : ℝ)) ⊆ U := by + intro y hy + apply hc hrU + intro i + simpa only [Complex.norm_of_nonneg (NNReal.coe_nonneg _), Pi.zero_apply, dist_zero_right] + using + (mem_closedPolydisc.mp hy i) + have hfc := hf.continuousOn.mono hBU + have hfa : ∀ y ∈ closedPolydisc 0 (fun i => (r i : ℝ)), ∀ i, + AnalyticAt ℂ (fun v => f (Function.update y i v)) (y i) := by + intro y hy i + have hd : Differentiable ℂ (fun v => Function.update y i v) := + fun v => (hasDerivAt_update y i v).differentiableAt + exact (hf y (hBU hy)).comp_of_eq (hd.analyticAt (y i)) (by simp) + obtain ⟨M, hM⟩ := (isCompact_closedPolydisc 0 (fun i => (r i : ℝ))).bddAbove_image + hfc.norm + have hMb : ∀ y ∈ closedPolydisc 0 (fun i => (r i : ℝ)), ‖f y‖ ≤ M := + fun y hy => hM ⟨y, hy, rfl⟩ + have hM0 : 0 ≤ M := (norm_nonneg (f 0)).trans + (hMb 0 (mem_closedPolydisc.mpr (fun i => by simpa only [Pi.zero_apply, dist_self] + using (hr i).le))) + have he : ∀ m : Fin n →₀ ℕ, taylorCoefficientsAtZero f m = + polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m := + fun m => (polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hr hfc hfa m).symm + have hq : ∀ i, ‖‖z i‖ / (r i : ℝ)‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (norm_nonneg _) (hr i).le), div_lt_one (hr i)] + exact hzr i + have hnorm : Summable (fun m : Fin n → ℕ => + ‖(∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m‖) := + ((hasSum_pi_geometric (fun i => ‖z i‖ / (r i : ℝ)) hq).summable.mul_left M).of_nonneg_of_le + (fun _ => norm_nonneg _) (fun m => norm_polydiscTaylor_term_le hr hM0 hMb (fun _ => + le_rfl) m) + have hsum := hasSum_polydiscTaylor (f := f) (c := 0) (h := z) hr (fun i => hzr i) hfc hfa hMb + let e : (Fin n →₀ ℕ) ≃ (Fin n → ℕ) := Finsupp.equivFunOnFinite + constructor + · simp_rw [he] + exact e.summable_iff.mpr hnorm + · simp_rw [he] + have hs : HasSum (fun m : Fin n → ℕ => + (∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m) (f z) := by + simpa only [zero_add] using hsum + exact e.hasSum_iff.mpr hs + refine ⟨ho.subset_interior_iff.mpr (fun z hz => ?_), fun z hz => (hpoint z hz).2.tsum_eq⟩ + exact mem_powerSeriesAbsConvergenceSet_iff.mpr (hpoint z hz).1 + +/-- **Extension from a complete Reinhardt domain to its logarithmic hull.** The explicit +extension is its Taylor sum. -/ +theorem analyticOnNhd_taylorSum_logarithmicReinhardtHull {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsCompleteReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) : + AnalyticOnNhd ℂ (powerSeriesSum (taylorCoefficientsAtZero f)) (logarithmicReinhardtHull U) ∧ + EqOn (powerSeriesSum (taylorCoefficientsAtZero f)) f U := by + obtain ⟨hD, he⟩ := IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum ho hc hf + exact ⟨(analyticOnNhd_powerSeriesSum _).mono + (logarithmicReinhardtHull_min hD (isReinhardt_powerSeriesConvergenceDomain _) + (hasGeometricallyConvexModuli_powerSeriesConvergenceDomain _)), he⟩ + +/-- **Power-series extension from a Reinhardt domain meeting each coordinate hyperplane.** +The points on different hyperplanes need not coincide. The proof eliminates negative +Laurent coefficients and uses geometric convexity of the convergence domain; it depends +on the Laurent expansion theorem. -/ +theorem exists_powerSeries_extension_of_meets_coordinateHyperplanes + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + (hmeet : ∀ i, ∃ z ∈ U, z i = 0) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ c : MvPowerSeries (Fin n) F, + logarithmicReinhardtHull U ⊆ powerSeriesConvergenceDomain c ∧ EqOn (powerSeriesSum c) f U := + by + classical + obtain ⟨z₀, hz₀⟩ := hc.nonempty + obtain ⟨r, hrU, hrz⟩ := hR.exists_strict_modulus_majorant ho hz₀ + have hr : ∀ i, (0 : ℝ) < r i := fun i => lt_of_le_of_lt (norm_nonneg _) (hrz i) + obtain ⟨hsum, hnorm, hneg, _, _⟩ := multivariableLaurent_expansion ho hc.isPreconnected hR hf hr + hrU + let e : (Fin n →₀ ℕ) → (Fin n → ℤ) := fun m i => (m i : ℤ) + have hinj : Function.Injective e := by + intro m k he + ext i + exact_mod_cast (show (m i : ℤ) = (k i : ℤ) from congrFun he i) + let c : MvPowerSeries (Fin n) F := fun m => multivariableLaurentCoeff f (fun i => (r i : ℝ)) (e m) + have hterm : ∀ m z, multivariableLaurentTerm (multivariableLaurentCoeff f (fun i => (r i : ℝ))) + (e m) z = (∏ i, z i ^ m i) • c m := by + intro m z + simp only [multivariableLaurentTerm, e, c, zpow_natCast] + have hzero : ∀ k, k ∉ Set.range e → multivariableLaurentCoeff f (fun i => (r i : ℝ)) k = 0 := by + intro k hk + by_cases hp : ∀ i, 0 ≤ k i + · exfalso + apply hk + refine ⟨Finsupp.equivFunOnFinite.symm (fun i => (k i).toNat), ?_⟩ + ext i + simp [e, Int.toNat_of_nonneg (hp i)] + · push Not at hp + obtain ⟨i, hi⟩ := hp + exact hneg k i (hmeet i) hi + have hA : U ⊆ powerSeriesAbsConvergenceSet c := by + intro z hz + apply mem_powerSeriesAbsConvergenceSet_iff.mpr + exact ((hnorm z hz).comp_injective hinj).congr (fun m => congrArg norm (hterm m z)) + refine ⟨c, logarithmicReinhardtHull_min (ho.subset_interior_iff.mpr hA) + (isReinhardt_powerSeriesConvergenceDomain c) + (hasGeometricallyConvexModuli_powerSeriesConvergenceDomain c), ?_⟩ + intro z hz + have hs := (hinj.hasSum_iff (fun k hk => by + simp only [multivariableLaurentTerm, hzero k hk, smul_zero])).mpr (hsum.hasSum hz) + exact (hs.congr_fun (fun m => (hterm m z).symm)).tsum_eq + +/-- Theorem 2.8.2: extension to the logarithmic hull when every coordinate hyperplane is met. +Depends on the Laurent expansion, and allows Banach-valued functions. -/ +theorem exists_extension_logarithmicReinhardtHull_of_meets_coordinateHyperplanes + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + (hmeet : ∀ i, ∃ z ∈ U, z i = 0) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g (logarithmicReinhardtHull U) ∧ EqOn g f U := by + obtain ⟨c, hD, he⟩ := exists_powerSeries_extension_of_meets_coordinateHyperplanes ho hc hR hmeet + hf + exact ⟨powerSeriesSum c, (analyticOnNhd_powerSeriesSum c).mono hD, he⟩ + +/-- Corollary 2.5.2: a connected Reinhardt domain containing zero admits extension to its +logarithmic hull. Depends on the Laurent expansion. -/ +theorem exists_extension_logarithmicReinhardtHull_of_zero_mem + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + (hzero : 0 ∈ U) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g (logarithmicReinhardtHull U) ∧ EqOn g f U := + exists_extension_logarithmicReinhardtHull_of_meets_coordinateHyperplanes ho hc hR + (fun _ => ⟨0, hzero, rfl⟩) hf + +/-- The geometric logarithmic hull of an open Reinhardt set containing zero contains its complete +Reinhardt hull. Interpolate a strict modulus majorant with radius vectors converging to zero; +the calculation also includes vanishing coordinates. -/ +theorem completeReinhardtHull_subset_logarithmicReinhardtHull + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hR : IsReinhardt U) (hzero : 0 ∈ U) : + completeReinhardtHull U ⊆ logarithmicReinhardtHull U := by + rintro w ⟨z, hz, hw⟩ + obtain ⟨r, hrU, hzr⟩ := hR.exists_strict_modulus_majorant ho hz + have hwr (i : Fin n) : ‖w i‖₊ < r i := (show ‖w i‖₊ ≤ ‖z i‖₊ from hw i).trans_lt (hzr i) + have hr (i : Fin n) : 0 < r i := (show 0 ≤ ‖w i‖₊ from zero_le).trans_lt (hwr i) + let v (k : ℕ) : Fin n → ℝ≥0 := fun i => r i * (‖w i‖₊ / r i) ^ k + have hv : Tendsto (fun k i => (v k i : ℂ)) atTop (𝓝 0) := by + apply tendsto_pi_nhds.mpr + intro i + have hratio : ‖w i‖₊ / r i < 1 := (div_lt_one (hr i)).mpr (hwr i) + have h := (NNReal.tendsto_pow_atTop_nhds_zero_of_lt_one hratio).const_mul (r i) + have hreal := NNReal.tendsto_coe.mpr h + simpa only [mul_zero, NNReal.coe_zero, Complex.ofReal_zero, Function.comp_def, + v, Pi.zero_apply] using + Complex.continuous_ofReal.continuousAt.tendsto.comp hreal + obtain ⟨k, hk, hvU⟩ := ((eventually_ge_atTop 1).and (hv.eventually (ho.mem_nhds hzero))).exists + have hkpos : 0 < (k : ℝ) := by exact_mod_cast (show 0 < k by omega) + have hkle : 1 ≤ (k : ℝ) := by exact_mod_cast hk + have ha : 0 ≤ (k : ℝ)⁻¹ := (inv_pos.mpr hkpos).le + have hb : 0 ≤ 1 - (k : ℝ)⁻¹ := sub_nonneg.mpr (inv_le_one_of_one_le₀ hkle) + have hm := isGeometricallyConvex_geometricConvexHull (modulusTrace U) + (subset_geometricConvexHull _ (hR.mem_modulusTrace_iff.mpr hvU)) + (subset_geometricConvexHull _ (hR.mem_modulusTrace_iff.mpr hrU)) + ha hb (add_sub_cancel _ _) + have he : geometricCombination (k : ℝ)⁻¹ (1 - (k : ℝ)⁻¹) (v k) r = + fun i => ‖w i‖₊ := by + funext i + dsimp [geometricCombination, v] + rw [NNReal.mul_rpow, NNReal.pow_rpow_inv_natCast _ (by omega : k ≠ 0)] + calc + r i ^ (k : ℝ)⁻¹ * (‖w i‖₊ / r i) * r i ^ (1 - (k : ℝ)⁻¹) = + (r i ^ (k : ℝ)⁻¹ * r i ^ (1 - (k : ℝ)⁻¹)) * (‖w i‖₊ / r i) := by ring + _ = r i * (‖w i‖₊ / r i) := by + rw [← NNReal.rpow_add_of_nonneg _ ha hb, add_sub_cancel, NNReal.rpow_one] + _ = ‖w i‖₊ := mul_div_cancel₀ _ (hr i).ne' + change (fun i => ‖w i‖₊) ∈ geometricConvexHull (modulusTrace U) + exact he ▸ hm + +/-- Theorem 2.5.1: extension to the complete Reinhardt hull, obtained by restricting the +logarithmic-hull extension. Depends on the Laurent expansion. -/ +theorem exists_extension_completeReinhardtHull + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + (hzero : 0 ∈ U) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g (completeReinhardtHull U) ∧ EqOn g f U := by + obtain ⟨g, hg, he⟩ := exists_extension_logarithmicReinhardtHull_of_zero_mem ho hc hR hzero hf + exact ⟨g, hg.mono (completeReinhardtHull_subset_logarithmicReinhardtHull ho hR hzero), he⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/GeometricConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/GeometricConvexity.lean new file mode 100644 index 0000000000..6597692b43 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/GeometricConvexity.lean @@ -0,0 +1,270 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.MeanInequalities +public import Mathlib.Analysis.Real.Sqrt +public import Mathlib.Topology.Homeomorph.Lemmas +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt + +/-! +# Geometric convexity including zero coordinates + +Geometric combinations of nonnegative radius vectors include coordinate hyperplanes. Weights are +nonnegative and sum to one, as in `Convex`. Mathlib's convention `0 ^ 0 = 1` gives the expected +endpoints. The old logarithmic-image predicate remains unchanged. Reinhardt symmetry, openness, +and completeness are separate assumptions. Positive geometric interpolation is an open map, +including on coordinate hyperplanes. Consequently, interiors preserve geometric convexity and +geometric convex hulls preserve openness. + +Reference: [Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), §2.2, Definition 2.2.3. + +## Main definitions + +* `geometricCombination`: Coordinatewise weighted geometric combination of nonnegative radii. +* `IsGeometricallyConvex`: Closure under geometric combinations, including zero coordinates and + endpoint weights. +* `geometricConvexHull`: The geometric convex hull, with zero coordinates included. +* `modulusTrace`: The modulus trace of a complex coordinate set, with values in nonnegative radii. +* `HasGeometricallyConvexModuli`: Logarithmic convexity including zero coordinates is geometric + convexity of the trace. + +## Main results + +* `isGeometricallyConvex_geometricConvexHull`: The geometric convex hull is geometrically convex. +* `geometricConvexHull_min`: Minimality of the geometric convex hull. +* `isOpenMap_geometricCombination`: Positive weighted geometric interpolation is an open map on + pairs of radius vectors. +* `IsGeometricallyConvex.interior`: The interior of a geometrically convex set of radii is + geometrically convex. +* `isOpen_geometricConvexHull`: The geometric convex hull of an open set of nonnegative radii is + open. +* `HasGeometricallyConvexModuli.isLogarithmicallyConvex`: Strong logarithmic convexity implies + convexity of the positive logarithmic image. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Set Filter +open scoped NNReal Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} + +/-- Coordinatewise weighted geometric combination of nonnegative radii. -/ +@[expose] def geometricCombination (a b : ℝ) (r s : ι → ℝ≥0) : ι → ℝ≥0 := + fun i => r i ^ a * s i ^ b + +/-- Closure under geometric combinations, including zero coordinates and endpoint weights. -/ +@[expose] def IsGeometricallyConvex (S : Set (ι → ℝ≥0)) : Prop := + ∀ ⦃r⦄, r ∈ S → ∀ ⦃s⦄, s ∈ S → ∀ ⦃a b : ℝ⦄, + 0 ≤ a → 0 ≤ b → a + b = 1 → geometricCombination a b r s ∈ S + +/-- The left endpoint of geometric interpolation. -/ +@[simp] theorem geometricCombination_one_zero (r s : ι → ℝ≥0) : + geometricCombination 1 0 r s = r := by ext i; simp [geometricCombination] + +/-- The right endpoint of geometric interpolation. -/ +@[simp] theorem geometricCombination_zero_one (r s : ι → ℝ≥0) : + geometricCombination 0 1 r s = s := by ext i; simp [geometricCombination] + +/-- Interpolating a radius vector with itself fixes it, including its zero coordinates. -/ +theorem geometricCombination_self (r : ι → ℝ≥0) {a b : ℝ} + (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1) : geometricCombination a b r r = r := by + ext i + simp only [geometricCombination, ← NNReal.rpow_add_of_nonneg (r i) ha hb, hab, NNReal.rpow_one] + +/-- Positive interpolation weights preserve a zero from either input coordinate. -/ +theorem geometricCombination_eq_zero {r s : ι → ℝ≥0} {a b : ℝ} + (ha : 0 < a) (hb : 0 < b) {i : ι} (h : r i = 0 ∨ s i = 0) : + geometricCombination a b r s i = 0 := by + rcases h with h | h <;> simp [geometricCombination, h, ha.ne', hb.ne'] + +/-- A singleton of radii is geometrically convex, including when some radii are zero. -/ +theorem isGeometricallyConvex_singleton (r : ι → ℝ≥0) : IsGeometricallyConvex {r} := by + intro x hx y hy a b ha hb hab + rw [mem_singleton_iff] at hx hy ⊢ + rw [hx, hy] + exact geometricCombination_self r ha hb hab + +/-- The empty set is geometrically convex. -/ +@[simp] theorem isGeometricallyConvex_empty : IsGeometricallyConvex (∅ : Set (ι → ℝ≥0)) := + fun _ h => h.elim + +/-- The whole space of nonnegative radii is geometrically convex. -/ +@[simp] theorem isGeometricallyConvex_univ : IsGeometricallyConvex (univ : Set (ι → ℝ≥0)) := + fun _ _ _ _ _ _ _ _ _ => mem_univ _ + +/-- Arbitrary intersections preserve geometric convexity. -/ +theorem isGeometricallyConvex_sInter {A : Set (Set (ι → ℝ≥0))} + (hA : ∀ S ∈ A, IsGeometricallyConvex S) : IsGeometricallyConvex (⋂₀ A) := by + intro r hr s hs a b ha hb hab + exact mem_sInter.mpr fun S hS => hA S hS (mem_sInter.mp hr S hS) + (mem_sInter.mp hs S hS) ha hb hab + +/-- The geometric convex hull, with zero coordinates included. -/ +@[expose] def geometricConvexHull (S : Set (ι → ℝ≥0)) : Set (ι → ℝ≥0) := + ⋂₀ {T | S ⊆ T ∧ IsGeometricallyConvex T} + +/-- Every set is contained in its geometric convex hull. -/ +theorem subset_geometricConvexHull (S : Set (ι → ℝ≥0)) : S ⊆ geometricConvexHull S := + fun _ hr => mem_sInter.mpr fun _ hT => hT.1 hr + +/-- The geometric convex hull is geometrically convex. -/ +theorem isGeometricallyConvex_geometricConvexHull (S : Set (ι → ℝ≥0)) : + IsGeometricallyConvex (geometricConvexHull S) := + isGeometricallyConvex_sInter fun _ h => h.2 + +/-- Minimality of the geometric convex hull. -/ +theorem geometricConvexHull_min {S T : Set (ι → ℝ≥0)} (hST : S ⊆ T) + (hT : IsGeometricallyConvex T) : geometricConvexHull S ⊆ T := + fun _ h => mem_sInter.mp h T ⟨hST, hT⟩ + +/-- Taking the geometric convex hull is monotone. -/ +theorem geometricConvexHull_mono {S T : Set (ι → ℝ≥0)} (h : S ⊆ T) : + geometricConvexHull S ⊆ geometricConvexHull T := + geometricConvexHull_min (h.trans (subset_geometricConvexHull T)) + (isGeometricallyConvex_geometricConvexHull T) + +/-- A geometrically convex set equals its hull. -/ +theorem IsGeometricallyConvex.geometricConvexHull_eq {S : Set (ι → ℝ≥0)} + (h : IsGeometricallyConvex S) : geometricConvexHull S = S := + Subset.antisymm (geometricConvexHull_min Subset.rfl h) (subset_geometricConvexHull S) + +/-- Multiplication of nonnegative radii is open, including at the pair of zero radii. -/ +private theorem isOpenMap_nnreal_mul : IsOpenMap (fun p : ℝ≥0 × ℝ≥0 => p.1 * p.2) := by + intro S hS + rw [isOpen_iff_mem_nhds] + rintro _ ⟨⟨r, s⟩, hrs, rfl⟩ + by_cases hr : r = 0 + · subst r + by_cases hs : s = 0 + · subst s + have h : Tendsto (fun t : ℝ≥0 => (NNReal.sqrt t, NNReal.sqrt t)) + (𝓝 (0 * 0)) (𝓝 (0, 0)) := by + simpa using (NNReal.continuous_sqrt.prodMk NNReal.continuous_sqrt).tendsto 0 + filter_upwards [h.eventually (hS.mem_nhds hrs)] with t ht + exact ⟨(NNReal.sqrt t, NNReal.sqrt t), ht, NNReal.mul_self_sqrt t⟩ + · have h : Tendsto (fun t : ℝ≥0 => (t / s, s)) (𝓝 (0 * s)) (𝓝 (0, s)) := by + simpa using ((continuous_id.div_const s).prodMk continuous_const).tendsto 0 + filter_upwards [h.eventually (hS.mem_nhds hrs)] with t ht + exact ⟨(t / s, s), ht, div_mul_cancel₀ t hs⟩ + · have h : Tendsto (fun t : ℝ≥0 => (r, t / r)) (𝓝 (r * s)) (𝓝 (r, s)) := by + simpa [mul_div_cancel_left₀ s hr] using + (continuous_const.prodMk (continuous_id.div_const r)).tendsto (r * s) + filter_upwards [h.eventually (hS.mem_nhds hrs)] with t ht + exact ⟨(r, t / r), ht, mul_div_cancel₀ t hr⟩ + +/-- Positive weighted geometric interpolation is an open map on pairs of radius vectors. -/ +theorem isOpenMap_geometricCombination {a b : ℝ} (ha : 0 < a) (hb : 0 < b) : + IsOpenMap (fun p : (ι → ℝ≥0) × (ι → ℝ≥0) => geometricCombination a b p.1 p.2) := by + have hscalar : IsOpenMap (fun p : ℝ≥0 × ℝ≥0 => p.1 ^ a * p.2 ^ b) := + isOpenMap_nnreal_mul.comp + ((NNReal.orderIsoRpow a ha).toHomeomorph.isOpenMap.prodMap + (NNReal.orderIsoRpow b hb).toHomeomorph.isOpenMap) + have hsurj : Function.Surjective (fun p : ℝ≥0 × ℝ≥0 => p.1 ^ a * p.2 ^ b) := by + intro t + obtain ⟨r, hr⟩ := NNReal.rpow_left_surjective ha.ne' t + exact ⟨(r, 1), by simp [hr]⟩ + let e : ((ι → ℝ≥0) × (ι → ℝ≥0)) ≃ₜ (ι → ℝ≥0 × ℝ≥0) := + { toFun := fun p i => (p.1 i, p.2 i) + invFun := fun p => (fun i => (p i).1, fun i => (p i).2) + left_inv := fun _ => rfl + right_inv := fun _ => rfl + continuous_toFun := by fun_prop + continuous_invFun := by fun_prop } + exact (IsOpenMap.piMap (fun _ : ι => hscalar) (.of_forall fun _ => hsurj)).comp e.isOpenMap + +/-- The interior of a geometrically convex set of radii is geometrically convex. -/ +theorem IsGeometricallyConvex.interior {S : Set (ι → ℝ≥0)} + (hS : IsGeometricallyConvex S) : IsGeometricallyConvex (interior S) := by + intro r hr s hs a b ha hb hab + rcases ha.eq_or_lt with ha | ha + · have hb : b = 1 := by linarith + simpa [← ha, hb] using hs + rcases hb.eq_or_lt with hb | hb + · have ha : a = 1 := by linarith + simpa [ha, ← hb] using hr + let g := fun p : (ι → ℝ≥0) × (ι → ℝ≥0) => geometricCombination a b p.1 p.2 + have ho : IsOpen (g '' (_root_.interior S ×ˢ _root_.interior S)) := + isOpenMap_geometricCombination ha hb _ (isOpen_interior.prod isOpen_interior) + have hsub : g '' (_root_.interior S ×ˢ _root_.interior S) ⊆ S := by + rintro _ ⟨⟨x, y⟩, ⟨hx, hy⟩, rfl⟩ + exact hS (interior_subset hx) (interior_subset hy) ha.le hb.le hab + exact (ho.subset_interior_iff.mpr hsub) ⟨(r, s), ⟨hr, hs⟩, rfl⟩ + +/-- The geometric convex hull of an open set of nonnegative radii is open. -/ +theorem isOpen_geometricConvexHull {S : Set (ι → ℝ≥0)} (hS : IsOpen S) : + IsOpen (geometricConvexHull S) := + subset_interior_iff_isOpen.mp (geometricConvexHull_min + (hS.subset_interior_iff.mpr (subset_geometricConvexHull S)) + (isGeometricallyConvex_geometricConvexHull S).interior) + +/-- Taking a geometric convex hull twice has no further effect. -/ +@[simp] theorem geometricConvexHull_idem (S : Set (ι → ℝ≥0)) : + geometricConvexHull (geometricConvexHull S) = geometricConvexHull S := + (isGeometricallyConvex_geometricConvexHull S).geometricConvexHull_eq + +/-- The empty set has empty geometric convex hull. -/ +@[simp] theorem geometricConvexHull_empty : geometricConvexHull (∅ : Set (ι → ℝ≥0)) = ∅ := + isGeometricallyConvex_empty.geometricConvexHull_eq + +/-- A singleton is fixed by the geometric convex hull. -/ +@[simp] theorem geometricConvexHull_singleton (r : ι → ℝ≥0) : geometricConvexHull {r} = {r} := + (isGeometricallyConvex_singleton r).geometricConvexHull_eq + +/-- The modulus trace of a complex coordinate set, with values in nonnegative radii. -/ +@[expose] def modulusTrace (U : Set (ι → ℂ)) : Set (ι → ℝ≥0) := + (fun z i => ‖z i‖₊) '' U + +/-- Logarithmic convexity including zero coordinates is geometric convexity of the trace. This does +not impose Reinhardt symmetry, openness, or completeness. -/ +@[expose] def HasGeometricallyConvexModuli (U : Set (ι → ℂ)) : Prop := + IsGeometricallyConvex (modulusTrace U) + +/-- For a Reinhardt set, a radius vector belongs to the trace exactly when its positive real +representative belongs to the set. -/ +theorem IsReinhardt.mem_modulusTrace_iff {U : Set (ι → ℂ)} (hU : IsReinhardt U) + {r : ι → ℝ≥0} : r ∈ modulusTrace U ↔ (fun i => (r i : ℂ)) ∈ U := by + constructor + · rintro ⟨z, hz, rfl⟩ + exact hU hz (fun i => by simp) + · intro h + refine ⟨_, h, ?_⟩ + ext i + simp + +/-- Strong logarithmic convexity implies convexity of the positive logarithmic image. -/ +theorem HasGeometricallyConvexModuli.isLogarithmicallyConvex {U : Set (ι → ℂ)} + (h : HasGeometricallyConvexModuli U) (hU : IsReinhardt U) : IsLogarithmicallyConvex U := by + intro x hx y hy a b ha hb hab + let r : ι → ℝ≥0 := fun i => ⟨Real.exp (x i), (Real.exp_pos _).le⟩ + let s : ι → ℝ≥0 := fun i => ⟨Real.exp (y i), (Real.exp_pos _).le⟩ + have hr : r ∈ modulusTrace U := hU.mem_modulusTrace_iff.mpr hx + have hs : s ∈ modulusTrace U := hU.mem_modulusTrace_iff.mpr hy + have hm := hU.mem_modulusTrace_iff.mp (h hr hs ha hb hab) + have he : (fun i => (Real.exp ((a • x + b • y) i) : ℂ)) = + (fun i => (geometricCombination a b r s i : ℂ)) := by + ext i + apply congrArg Complex.ofReal + change Real.exp (a * x i + b * y i) = ((r i ^ a * s i ^ b : ℝ≥0) : ℝ) + rw [NNReal.coe_mul, NNReal.coe_rpow, NNReal.coe_rpow] + change Real.exp (a * x i + b * y i) = Real.exp (x i) ^ a * Real.exp (y i) ^ b + rw [← Real.exp_mul, ← Real.exp_mul, ← Real.exp_add] + congr 1 + ring + change (fun i => (Real.exp ((a • x + b • y) i) : ℂ)) ∈ U + rw [he] + exact hm + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/HolomorphicConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/HolomorphicConvexity.lean new file mode 100644 index 0000000000..b8326aea5e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/HolomorphicConvexity.lean @@ -0,0 +1,103 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation + +/-! +# Holomorphic convexity of complete Reinhardt domains + +An exterior point is separated from each compact subset by a monomial. The entire holomorphic +hull of the compact set therefore stays in the domain. Its compactness implies compactness of +the relative holomorphic hull. + +## Main results + +`exists_monomial_separator_of_isCompact` separates an exterior point from a compact subset by a +monomial. `isHolomorphicallyConvex_of_completeReinhardt` is holomorphic convexity of an open +complete logarithmically convex Reinhardt domain. +-/ + +public noncomputable section + +open Set +open scoped Topology NNReal + +namespace SeveralComplexVariables + +variable {ι : Type*} [Fintype ι] + +/-- A monomial separates a compact subset of an open complete logarithmically convex Reinhardt set +from any exterior point. -/ +theorem exists_monomial_separator_of_isCompact {U K : Set (ι → ℂ)} + (ho : IsOpen U) (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) + (hK : IsCompact K) (hKU : K ⊆ U) {z : ι → ℂ} (hz : z ∉ U) : + ∃ (m : ι → ℕ) (M : ℝ), (∀ w ∈ K, ‖∏ i, w i ^ m i‖ ≤ M) ∧ + M < ‖∏ i, z i ^ m i‖ := by + rcases K.eq_empty_or_nonempty with rfl | hne + · exact ⟨0, 0, by simp, by simp⟩ + let R := {r : ι → ℝ≥0 | (fun i => (r i : ℂ)) ∈ U ∧ ∀ i, 0 < r i} + let P (r : R) := polydisc (0 : ι → ℂ) (fun i => (r.val i : ℝ)) + have hcover : K ⊆ ⋃ r : R, P r := by + intro w hw + obtain ⟨r, hrU, hr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho (hKU hw) + have hrpos (i) : 0 < r i := (show (0 : ℝ≥0) ≤ ‖w i‖₊ from zero_le).trans_lt (hr i) + apply mem_iUnion.mpr + refine ⟨⟨r, hrU, hrpos⟩, ?_⟩ + apply mem_polydisc.mpr + intro i + simpa only [dist_zero_right, Pi.zero_apply] using (show ‖w i‖ < (r i : ℝ) from hr i) + obtain ⟨s, hs⟩ := hK.elim_finite_subcover P (fun r => isOpen_polydisc _ _) hcover + have hsne : s.Nonempty := by + obtain ⟨w, hw⟩ := hne + obtain ⟨r, hr, _⟩ := mem_iUnion₂.mp (hs hw) + exact ⟨r, hr⟩ + let : Nonempty s := hsne.to_subtype + let r (j : s) (i : ι) : ℝ := j.val.val i + have hr (j : s) (i : ι) : 0 < r j i := j.val.property.2 i + obtain ⟨m, hm⟩ := exists_monomial_separator_of_finite_radii ho hc hl hr + (fun j => j.val.property.1) hz + obtain ⟨j, _, hj⟩ := Finset.exists_max_image (Finset.univ : Finset s) + (fun j => ∏ i, r j i ^ m i) Finset.univ_nonempty + refine ⟨m, ∏ i, r j i ^ m i, ?_, ?_⟩ + · intro w hw + obtain ⟨q, hq, hwq⟩ := mem_iUnion₂.mp (hs hw) + rw [norm_prod] + simp only [norm_pow] + apply le_trans _ (hj ⟨q, hq⟩ (Finset.mem_univ _)) + apply Finset.prod_le_prod₀ (fun i _ => pow_nonneg (norm_nonneg _) _) + intro i _ + apply pow_le_pow_left₀ (norm_nonneg _) + simpa only [Pi.zero_apply, dist_zero_right] using + (mem_polydisc.mp hwq i).le + · simpa only [norm_prod, norm_pow] using hm j + +/-- Open complete logarithmically convex Reinhardt sets are holomorphically convex. This includes +unbounded sets, the empty set, and empty coordinate types. -/ +theorem isHolomorphicallyConvex_of_completeReinhardt {U : Set (ι → ℂ)} + (ho : IsOpen U) (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) : + IsHolomorphicallyConvex U := by + intro K hK hKU + have hC : IsCompact (holomorphicHull univ K) := + isHolomorphicallyConvex_univ K hK (subset_univ _) + have hCU : holomorphicHull univ K ⊆ U := by + intro z hz + by_contra hn + obtain ⟨m, M, hM, hMz⟩ := exists_monomial_separator_of_isCompact ho hc hl hK hKU hn + have hf : AnalyticOnNhd ℂ (fun w : ι → ℂ => ∏ i, w i ^ m i) univ := by + intro w _ + apply Finset.analyticAt_fun_prod + intro i _ + exact ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt w).pow (m i) + exact (hz.2 _ hf M hM).not_gt hMz + exact isCompact_holomorphicHull_of_subset_compact hC hCU + (holomorphicHull_mono_ambient (subset_univ _)) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean new file mode 100644 index 0000000000..077926f4ba --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean @@ -0,0 +1,237 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.MetricSpace.Pseudo.Pi +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity + +/-! +# Reinhardt hulls and comparison of logarithmic convexity conventions + +The complete Reinhardt hull allows coordinatewise shrinking. The logarithmic Reinhardt hull +closes the modulus trace under geometric interpolation, including zeros, and restores rotation +symmetry. Both are minimal hulls of sets; neither definition builds in openness. For open +complete Reinhardt sets in finite dimension, the two logarithmic convexity predicates agree. +References: [Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), §§2.2–2.5 and §2.8. + +## Main results + +`completeReinhardtHull` and `logarithmicReinhardtHull` are the two hulls. +`completeReinhardtHull_min` and `logarithmicReinhardtHull_min` are minimality. +`hasGeometricallyConvexModuli_iff` compares geometric and logarithmic convexity on open complete +Reinhardt sets. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Set Metric +open scoped NNReal Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} {U V : Set (ι → ℂ)} + +/-- An open Reinhardt set contains a strictly larger positive modulus vector above each point. -/ +theorem IsReinhardt.exists_strict_modulus_majorant [Fintype ι] + (hU : IsReinhardt U) (ho : IsOpen U) {z : ι → ℂ} (hz : z ∈ U) : + ∃ r : ι → ℝ≥0, (fun i => (r i : ℂ)) ∈ U ∧ ∀ i, ‖z i‖₊ < r i := by + have hz' : (fun i => (‖z i‖ : ℂ)) ∈ U := hU hz (fun i => by simp) + obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp ho _ hz' + let r : ι → ℝ≥0 := fun i => ‖z i‖₊ + ⟨δ / 2, by positivity⟩ + refine ⟨r, hball ?_, fun i => ?_⟩ + · rw [mem_ball, dist_pi_lt_iff hδ] + intro i + change dist ((‖z i‖ + δ / 2 : ℝ) : ℂ) (‖z i‖ : ℂ) < δ + rw [dist_eq_norm, ← Complex.ofReal_sub, Complex.norm_real, Real.norm_eq_abs] + simp only [add_sub_cancel_left, abs_of_pos (half_pos hδ)] + linarith + · change ‖z i‖₊ < ‖z i‖₊ + ⟨δ / 2, by positivity⟩ + exact lt_add_of_pos_right _ (by exact_mod_cast half_pos hδ) + +/-- Positive geometric combinations are controlled by convexity of the logarithmic image. -/ +theorem IsLogarithmicallyConvex.geometricCombination_mem {r s : ι → ℝ≥0} + (h : IsLogarithmicallyConvex U) (hr : (fun i => (r i : ℂ)) ∈ U) + (hs : (fun i => (s i : ℂ)) ∈ U) (hrp : ∀ i, 0 < r i) (hsp : ∀ i, 0 < s i) + {a b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a + b = 1) : + (fun i => (geometricCombination a b r s i : ℂ)) ∈ U := by + have hx : (fun i => Real.log (r i)) ∈ logarithmicImage U := by + simpa only [logarithmicImage, mem_ofPred_eq, Real.exp_log (show (0 : ℝ) < r _ from hrp _)] + using hr + have hy : (fun i => Real.log (s i)) ∈ logarithmicImage U := by + simpa only [logarithmicImage, mem_ofPred_eq, Real.exp_log (show (0 : ℝ) < s _ from hsp _)] + using hs + have hm := h hx hy ha hb hab + have he : (fun i => (Real.exp (a * Real.log (r i) + b * Real.log (s i)) : ℂ)) = + (fun i => (geometricCombination a b r s i : ℂ)) := by + ext i + apply congrArg Complex.ofReal + change Real.exp (a * Real.log (r i) + b * Real.log (s i)) = + ((r i ^ a * s i ^ b : ℝ≥0) : ℝ) + rw [NNReal.coe_mul, NNReal.coe_rpow, NNReal.coe_rpow, + Real.rpow_def_of_pos (show (0 : ℝ) < (r i : ℝ) from hrp i), + Real.rpow_def_of_pos (show (0 : ℝ) < (s i : ℝ) from hsp i), ← Real.exp_add] + congr 1 + ring + exact he ▸ hm + +/-- On open complete Reinhardt sets the logarithmic-image convention also controls zeros. -/ +theorem IsLogarithmicallyConvex.hasGeometricallyConvexModuli [Fintype ι] + (h : IsLogarithmicallyConvex U) (ho : IsOpen U) (hc : IsCompleteReinhardt U) : + HasGeometricallyConvexModuli U := by + rintro r ⟨z, hz, rfl⟩ s ⟨w, hw, rfl⟩ a b ha hb hab + obtain ⟨r, hr, hzr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho hz + obtain ⟨s, hs, hws⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho hw + apply hc.isReinhardt.mem_modulusTrace_iff.mpr + apply hc (h.geometricCombination_mem hr hs + (fun i => lt_of_le_of_lt (show (0 : ℝ≥0) ≤ _ from zero_le) (hzr i)) + (fun i => lt_of_le_of_lt (show (0 : ℝ≥0) ≤ _ from zero_le) (hws i)) ha hb hab) + intro i + simp only [Complex.norm_of_nonneg (NNReal.coe_nonneg _)] + exact_mod_cast mul_le_mul' (NNReal.rpow_le_rpow (hzr i).le ha) + (NNReal.rpow_le_rpow (hws i).le hb) + +/-- Equivalence of the two conventions on open complete Reinhardt sets. -/ +theorem hasGeometricallyConvexModuli_iff [Fintype ι] (ho : IsOpen U) + (hc : IsCompleteReinhardt U) : + HasGeometricallyConvexModuli U ↔ IsLogarithmicallyConvex U := + ⟨fun h => h.isLogarithmicallyConvex hc.isReinhardt, + fun h => h.hasGeometricallyConvexModuli ho hc⟩ + +/-- Away from all coordinate hyperplanes, the two convexity conventions coincide without openness or +completeness assumptions. -/ +theorem hasGeometricallyConvexModuli_iff_of_nonzero (hR : IsReinhardt U) + (hne : ∀ z ∈ U, ∀ i, z i ≠ 0) : + HasGeometricallyConvexModuli U ↔ IsLogarithmicallyConvex U := by + refine ⟨fun h => h.isLogarithmicallyConvex hR, ?_⟩ + intro h r hr s hs a b ha hb hab + obtain ⟨z, hz, rfl⟩ := hr + obtain ⟨w, hw, rfl⟩ := hs + exact hR.mem_modulusTrace_iff.mpr (h.geometricCombination_mem + (hR.mem_modulusTrace_iff.mp ⟨z, hz, rfl⟩) + (hR.mem_modulusTrace_iff.mp ⟨w, hw, rfl⟩) + (fun i => nnnorm_pos.mpr (hne z hz i)) (fun i => nnnorm_pos.mpr (hne w hw i)) ha hb hab) + +/-- The smallest complete Reinhardt set containing a given set. -/ +@[expose] def completeReinhardtHull (U : Set (ι → ℂ)) : Set (ι → ℂ) := + {w | ∃ z ∈ U, ∀ i, ‖w i‖ ≤ ‖z i‖} + +/-- A set is contained in its complete Reinhardt hull. -/ +theorem subset_completeReinhardtHull : U ⊆ completeReinhardtHull U := + fun z hz => ⟨z, hz, fun _ => le_rfl⟩ + +/-- The complete Reinhardt hull is complete Reinhardt. -/ +theorem isCompleteReinhardt_completeReinhardtHull : IsCompleteReinhardt (completeReinhardtHull U) + := by + rintro z ⟨v, hv, hz⟩ w hw + exact ⟨v, hv, fun i => (hw i).trans (hz i)⟩ + +/-- Minimality of the complete Reinhardt hull. -/ +theorem completeReinhardtHull_min (hUV : U ⊆ V) (hV : IsCompleteReinhardt V) : + completeReinhardtHull U ⊆ V := by + rintro w ⟨z, hz, hw⟩ + exact hV (hUV hz) hw + +/-- Complete Reinhardt sets are fixed by their hull. -/ +theorem IsCompleteReinhardt.hull_eq (h : IsCompleteReinhardt U) : completeReinhardtHull U = U := + Subset.antisymm (completeReinhardtHull_min Subset.rfl h) subset_completeReinhardtHull + +/-- Completing an open Reinhardt set preserves openness. -/ +theorem isOpen_completeReinhardtHull [Fintype ι] (ho : IsOpen U) (hR : IsReinhardt U) : + IsOpen (completeReinhardtHull U) := by + rw [isOpen_iff_mem_nhds] + rintro w ⟨z, hz, hwz⟩ + obtain ⟨r, hrU, hzr⟩ := hR.exists_strict_modulus_majorant ho hz + let W : Set (ι → ℂ) := {v | ∀ i, ‖v i‖ < (r i : ℝ)} + have hW : IsOpen W := by + simpa only [W, ofPred_forall] using + (isOpen_iInter_of_finite fun i => isOpen_lt (continuous_apply i).norm + (continuous_const (y := (r i : ℝ)))) + apply Filter.mem_of_superset (hW.mem_nhds (fun i => (hwz i).trans_lt (hzr i))) + intro v hv + exact ⟨_, hrU, fun i => by simpa only [Complex.norm_of_nonneg (NNReal.coe_nonneg _)] using (hv + i).le⟩ + +/-- The logarithmic Reinhardt hull uses geometric convexity including coordinate hyperplanes. -/ +@[expose] def logarithmicReinhardtHull (U : Set (ι → ℂ)) : Set (ι → ℂ) := + {z | (fun i => ‖z i‖₊) ∈ geometricConvexHull (modulusTrace U)} + +/-- A set is contained in its logarithmic Reinhardt hull. -/ +theorem subset_logarithmicReinhardtHull : U ⊆ logarithmicReinhardtHull U := + fun z hz => subset_geometricConvexHull _ ⟨z, hz, rfl⟩ + +/-- The logarithmic Reinhardt hull has coordinate rotation symmetry. -/ +theorem isReinhardt_logarithmicReinhardtHull : IsReinhardt (logarithmicReinhardtHull U) := by + intro z hz w hw + have he : (fun i => ‖w i‖₊) = (fun i => ‖z i‖₊) := funext fun i => Subtype.ext (hw i) + change (fun i => ‖w i‖₊) ∈ geometricConvexHull (modulusTrace U) + rw [he] + exact hz + +/-- The trace of the logarithmic Reinhardt hull is the geometric convex hull of the trace. -/ +theorem modulusTrace_logarithmicReinhardtHull : + modulusTrace (logarithmicReinhardtHull U) = geometricConvexHull (modulusTrace U) := by + ext r + constructor + · rintro ⟨z, hz, rfl⟩ + exact hz + · intro hr + refine ⟨fun i => (r i : ℂ), ?_, ?_⟩ + · simpa [logarithmicReinhardtHull] using hr + · ext i; simp + +/-- The logarithmic Reinhardt hull satisfies geometric convexity including zeros. -/ +theorem hasGeometricallyConvexModuli_logarithmicReinhardtHull : + HasGeometricallyConvexModuli (logarithmicReinhardtHull U) := by + rw [HasGeometricallyConvexModuli, modulusTrace_logarithmicReinhardtHull] + exact isGeometricallyConvex_geometricConvexHull _ + +/-- Minimality of the logarithmic Reinhardt hull among Reinhardt sets with convex moduli. -/ +theorem logarithmicReinhardtHull_min (hUV : U ⊆ V) (hV : IsReinhardt V) + (hg : HasGeometricallyConvexModuli V) : logarithmicReinhardtHull U ⊆ V := by + intro z hz + have hm : (fun i => ‖z i‖₊) ∈ modulusTrace V := + geometricConvexHull_min (image_mono hUV) hg hz + obtain ⟨w, hw, he⟩ := hm + exact hV hw (fun i => (congrArg (fun r : ι → ℝ≥0 => (r i : ℝ)) he).symm) + +/-- A Reinhardt set with geometrically convex moduli equals its logarithmic hull. -/ +theorem logarithmicReinhardtHull_eq (hU : IsReinhardt U) (hg : HasGeometricallyConvexModuli U) : + logarithmicReinhardtHull U = U := + Subset.antisymm (logarithmicReinhardtHull_min Subset.rfl hU hg) subset_logarithmicReinhardtHull + +/-- Openness of the geometric logarithmic hull in finite dimension, including zero coordinates. The +modulus trace of an open Reinhardt set is open, and so is its geometric convex hull. -/ +theorem isOpen_logarithmicReinhardtHull [Fintype ι] (ho : IsOpen U) (hU : IsReinhardt U) : + IsOpen (logarithmicReinhardtHull U) := by + have htrace : modulusTrace U = + (fun r : ι → ℝ≥0 => fun i => (r i : ℂ)) ⁻¹' U := by + ext r + exact hU.mem_modulusTrace_iff + have hto : IsOpen (modulusTrace U) := by + rw [htrace] + apply ho.preimage + fun_prop + exact (isOpen_geometricConvexHull hto).preimage (by fun_prop) + +/-- The logarithmic Reinhardt hull is monotone. -/ +theorem logarithmicReinhardtHull_mono (hUV : U ⊆ V) : + logarithmicReinhardtHull U ⊆ logarithmicReinhardtHull V := + logarithmicReinhardtHull_min (hUV.trans subset_logarithmicReinhardtHull) + isReinhardt_logarithmicReinhardtHull hasGeometricallyConvexModuli_logarithmicReinhardtHull + +/-- Taking the logarithmic Reinhardt hull twice has no further effect. -/ +@[simp] theorem logarithmicReinhardtHull_idem : + logarithmicReinhardtHull (logarithmicReinhardtHull U) = logarithmicReinhardtHull U := + logarithmicReinhardtHull_eq isReinhardt_logarithmicReinhardtHull + hasGeometricallyConvexModuli_logarithmicReinhardtHull + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean new file mode 100644 index 0000000000..007f4b567e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean @@ -0,0 +1,215 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.LocallyConvex.Separation +public import Mathlib.Analysis.SpecificLimits.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull + +/-! +# Monomial separation on complete logarithmically convex Reinhardt sets + +Logarithmic separation can be restricted to the nonzero coordinates of an exterior point. +Approximating the nonnegative separating weights by integer exponents then gives a monomial +separating that point from a compact subset of the domain. + +## Main results + +`exists_logarithmic_lift` produces a logarithmic lift of a modulus vector with some zero +coordinates. `exists_nat_weights` approximates nonnegative separating weights by integer +exponents. `exists_monomial_separator_of_finite_radii` is the resulting monomial separator. +-/ + +public noncomputable section + +open Set Filter +open scoped Topology NNReal + +namespace SeveralComplexVariables + +variable {ι : Type*} [Fintype ι] + +/-- Exponentiation on the coordinate face determined by the nonzero entries of `z`. -/ +private def faceExp (z : ι → ℂ) (t : ι → ℝ) : ι → ℂ := + fun i => if z i = 0 then 0 else (Real.exp (t i) : ℂ) + +omit [Fintype ι] in +/-- Exponentiation on a fixed coordinate face is continuous. -/ +private theorem continuous_faceExp (z : ι → ℂ) : Continuous (faceExp z) := by + classical + apply continuous_pi + intro i + by_cases hi : z i = 0 <;> simp only [faceExp, hi, ite_true, ite_false] + · exact continuous_const + · fun_prop + +/-- A face point in an open complete Reinhardt set has a positive lift with the same nonzero +coordinates. -/ +private theorem exists_logarithmic_lift {U : Set (ι → ℂ)} (ho : IsOpen U) + (hc : IsCompleteReinhardt U) {z : ι → ℂ} {t : ι → ℝ} (ht : faceExp z t ∈ U) : + ∃ y ∈ logarithmicImage U, ∀ i, z i ≠ 0 → y i = t i := by + classical + obtain ⟨r, hrU, hr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho ht + have hrpos (i) : 0 < (r i : ℝ) := by + exact_mod_cast (show (0 : ℝ≥0) ≤ ‖faceExp z t i‖₊ from zero_le).trans_lt (hr i) + let y (i : ι) := if z i = 0 then Real.log (r i) else t i + refine ⟨y, hc hrU ?_, ?_⟩ + · intro i + by_cases hi : z i = 0 + · simp [y, hi, Real.exp_log (hrpos i)] + · have hri : ‖faceExp z t i‖ < (r i : ℝ) := by exact_mod_cast hr i + simpa [y, faceExp, hi, abs_of_pos (hrpos i)] using hri.le + · intro i hi + simp [y, hi] + +/-- Logarithmic coordinates on any coordinate face form an open convex lower set. -/ +private theorem convex_faceLog {U : Set (ι → ℂ)} (ho : IsOpen U) + (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) (z : ι → ℂ) : + Convex ℝ {t | faceExp z t ∈ U} := by + classical + intro x hx y hy a b ha hb hab + obtain ⟨x', hx', hxx⟩ := exists_logarithmic_lift ho hc hx + obtain ⟨y', hy', hyy⟩ := exists_logarithmic_lift ho hc hy + apply hc (hl hx' hy' ha hb hab) + intro i + by_cases hi : z i = 0 + · simp [faceExp, hi] + · simp [faceExp, hi, hxx i hi, hyy i hi] + +omit [Fintype ι] in +/-- The logarithmic face set is closed under decreasing coordinates. -/ +private theorem faceExp_mem_of_le {U : Set (ι → ℂ)} (hc : IsCompleteReinhardt U) + {z : ι → ℂ} {x y : ι → ℝ} (hx : faceExp z x ∈ U) (hy : y ≤ x) : + faceExp z y ∈ U := by + classical + apply hc hx + intro i + by_cases hi : z i = 0 + · simp [faceExp, hi] + · simpa [faceExp, hi] using Real.exp_le_exp.mpr (hy i) + +omit [Fintype ι] in +/-- A separating functional for a lower set has nonnegative coordinate weights. -/ +private theorem nonneg_separating_weights [DecidableEq ι] {S : Set (ι → ℝ)} + (hdown : ∀ x ∈ S, ∀ y, y ≤ x → y ∈ S) {x y : ι → ℝ} (hy : y ∈ S) + {l : (ι → ℝ) →L[ℝ] ℝ} (hl : ∀ t ∈ S, l t < l x) (i : ι) : + 0 ≤ l (Pi.single i 1) := by + classical + by_contra h + have hi : l (Pi.single i 1) < 0 := lt_of_not_ge h + let a := (l x - l y + 1) / (-l (Pi.single i 1)) + have ha : 0 ≤ a := le_of_lt (div_pos (by linarith [hl y hy]) (neg_pos.mpr hi)) + have ht := hl (y - a • Pi.single i 1) (hdown y hy _ (by + intro j + simp only [Pi.sub_apply, Pi.smul_apply, smul_eq_mul, sub_le_self_iff] + exact mul_nonneg ha (by simp [Pi.single_apply]; split_ifs <;> norm_num))) + rw [map_sub, map_smul, smul_eq_mul] at ht + have he : a * (-l (Pi.single i 1)) = l x - l y + 1 := + div_mul_cancel₀ _ (neg_ne_zero.mpr hi.ne) + nlinarith + +omit [Fintype ι] in +/-- Coordinates absent from a face have zero weight in any separating functional. -/ +private theorem separating_weight_zero [DecidableEq ι] {U : Set (ι → ℂ)} {z : ι → ℂ} + {x y : ι → ℝ} (hy : faceExp z y ∈ U) {l : (ι → ℝ) →L[ℝ] ℝ} + (hl : ∀ t, faceExp z t ∈ U → l t < l x) (i : ι) (hi : z i = 0) : + l (Pi.single i 1) = 0 := by + classical + by_contra hn + let a := (l x - l y + 1) / l (Pi.single i 1) + have he : faceExp z (y + a • Pi.single i 1) = faceExp z y := by + funext j + by_cases hj : j = i + · subst j; simp [faceExp, hi] + · simp [faceExp, Pi.single_eq_of_ne hj] + have ht := hl _ (he ▸ hy) + rw [map_add, map_smul, smul_eq_mul] at ht + have heq : a * l (Pi.single i 1) = l x - l y + 1 := div_mul_cancel₀ _ hn + linarith + +/-- A linear functional on a finite coordinate space is the sum of its coordinate weights. -/ +private theorem linear_functional_eq_sum [DecidableEq ι] (l : (ι → ℝ) →L[ℝ] ℝ) (t : ι → ℝ) : + l t = ∑ i, l (Pi.single i 1) * t i := by + rw [← Finset.univ_sum_single t, map_sum] + apply Finset.sum_congr rfl + intro i _ + have he : Pi.single i (t i) = t i • Pi.single i (1 : ℝ) := by + ext j + simp [Pi.single_apply, mul_ite] + rw [he, map_smul, smul_eq_mul, mul_comm, Finset.univ_sum_single] + +/-- Finitely many strict inequalities with nonnegative real weights persist for suitable nonnegative +integer weights. Zero weights remain zero. -/ +private theorem exists_nat_weights {κ : Type*} [Fintype κ] {a x : ι → ℝ} + {y : κ → ι → ℝ} (ha : ∀ i, 0 ≤ a i) + (hxy : ∀ j, (∑ i, a i * y j i) < ∑ i, a i * x i) : + ∃ m : ι → ℕ, (∀ i, a i = 0 → m i = 0) ∧ + ∀ j, (∑ i, (m i : ℝ) * y j i) < ∑ i, (m i : ℝ) * x i := by + have hlim (j : κ) : Tendsto + (fun t : ℝ => ∑ i, ((⌊a i * t⌋₊ : ℝ) / t) * (x i - y j i)) atTop + (𝓝 (∑ i, a i * (x i - y j i))) := + tendsto_finsetSum _ (fun i _ => (tendsto_nat_floor_mul_div_atTop (ha i)).mul_const _) + have hpos (j : κ) : 0 < ∑ i, a i * (x i - y j i) := by + simpa only [mul_sub, Finset.sum_sub_distrib] using sub_pos.mpr (hxy j) + have hall : ∀ᶠ t : ℝ in atTop, ∀ j, 0 < ∑ i, ((⌊a i * t⌋₊ : ℝ) / t) * (x i - y j i) := + Filter.eventually_all.mpr (fun j => (hlim j).eventually (lt_mem_nhds (hpos j))) + obtain ⟨t, ht, h⟩ := (hall.and (eventually_gt_atTop (0 : ℝ))).exists + refine ⟨fun i => ⌊a i * t⌋₊, fun i hi => by simp [hi], ?_⟩ + intro j + have hj := ht j + simp only [div_mul_eq_mul_div, ← Finset.sum_div, mul_sub, Finset.sum_sub_distrib] at hj + exact (div_lt_div_iff_of_pos_right h).mp (sub_pos.mp hj) + +/-- A monomial separates an exterior point from finitely many positive radius vectors in an open +complete logarithmically convex Reinhardt set. -/ +theorem exists_monomial_separator_of_finite_radii {κ : Type*} [Fintype κ] [Nonempty κ] + {U : Set (ι → ℂ)} (ho : IsOpen U) (hc : IsCompleteReinhardt U) + (hl : IsLogarithmicallyConvex U) {r : κ → ι → ℝ} + (hr : ∀ j i, 0 < r j i) (hrU : ∀ j, (fun i => (r j i : ℂ)) ∈ U) + {z : ι → ℂ} (hz : z ∉ U) : + ∃ m : ι → ℕ, ∀ j, (∏ i, r j i ^ m i) < ∏ i, ‖z i‖ ^ m i := by + classical + let x (i : ι) := Real.log ‖z i‖ + let y (j : κ) (i : ι) := Real.log (r j i) + have hx : faceExp z x ∉ U := by + intro hx + apply hz (hc.isReinhardt hx ?_) + intro i + by_cases hi : z i = 0 + · simp [faceExp, hi] + · simp [faceExp, hi, x, Real.exp_log (norm_pos_iff.mpr hi)] + have hy (j : κ) : faceExp z (y j) ∈ U := by + apply hc (hrU j) + intro i + by_cases hi : z i = 0 + · simp [faceExp, hi] + · simp [faceExp, hi, y, Real.exp_log (hr j i)] + obtain ⟨l, hsep⟩ := geometric_hahn_banach_open_point (convex_faceLog ho hc hl z) + (ho.preimage (continuous_faceExp z)) hx + let a (i : ι) := l (Pi.single i 1) + have ha (i : ι) : 0 ≤ a i := nonneg_separating_weights + (fun _ ht _ hle => faceExp_mem_of_le hc ht hle) (hy (Classical.arbitrary κ)) hsep i + have ha0 (i : ι) (hi : z i = 0) : a i = 0 := + separating_weight_zero (hy (Classical.arbitrary κ)) hsep i hi + obtain ⟨m, hm0, hm⟩ := exists_nat_weights ha (fun j => by + simpa only [linear_functional_eq_sum l (y j), linear_functional_eq_sum l x] using hsep _ (hy j)) + refine ⟨m, fun j => ?_⟩ + have hexp (v : ι → ℝ) (hv : ∀ i, 0 < v i) : + Real.exp (∑ i, (m i : ℝ) * Real.log (v i)) = ∏ i, v i ^ m i := by + simp [Real.exp_sum, Real.exp_nat_mul, Real.exp_log (hv _)] + have hzexp : Real.exp (∑ i, (m i : ℝ) * x i) = ∏ i, ‖z i‖ ^ m i := by + rw [Real.exp_sum] + apply Finset.prod_congr rfl + intro i _ + by_cases hi : z i = 0 + · simp [hm0 i (ha0 i hi)] + · simp [x, Real.exp_nat_mul, Real.exp_log (norm_pos_iff.mpr hi)] + rw [← hexp (r j) (hr j), ← hzexp] + exact Real.exp_lt_exp.mpr (hm j) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean new file mode 100644 index 0000000000..1a2d5f3a49 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean @@ -0,0 +1,317 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension + +/-! +# Completion in selected Reinhardt coordinates + +The selected coordinates can decrease in modulus; the others retain their moduli. On Reinhardt +sets this is precisely coordinate contraction without a coordinate ordering. The geometric hull +works for arbitrary index types, and its openness is proved. For finite coordinates, absolute +convergence and vanishing of the relevant negative Laurent coefficients give locally uniform +convergence and an analytic sum on the hull. These coefficient-series results are independent of +the Laurent expansion theorem; extension of arbitrary holomorphic functions is deduced from that +theorem. Reference: [Scheidemann][Scheidemann2005] (2005), Corollary 2.1.15. + +## Main results + +`IsCompleteReinhardtIn` is completeness in a selected set of coordinates. `partialReinhardtHull` +is the corresponding hull. `exists_extension_partialReinhardtHull` extends a holomorphic +function to that hull. `hasSumLocallyUniformlyOn_laurent_partialReinhardtHull` is locally +uniform convergence of the relevant Laurent terms. + +## References + +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} {U V : Set (ι → ℂ)} {I : Set ι} + +/-- Reinhardt completeness restricted to a specified set of coordinates. -/ +@[expose] def IsCompleteReinhardtIn (I : Set ι) (U : Set (ι → ℂ)) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃w⦄, (∀ i, ‖w i‖ ≤ ‖z i‖) → + (∀ i ∉ I, ‖w i‖ = ‖z i‖) → w ∈ U + +/-- The hull formed by contracting selected moduli and preserving all other moduli. -/ +@[expose] def partialReinhardtHull (I : Set ι) (U : Set (ι → ℂ)) : Set (ι → ℂ) := + {w | ∃ z ∈ U, (∀ i, ‖w i‖ ≤ ‖z i‖) ∧ ∀ i ∉ I, ‖w i‖ = ‖z i‖} + +/-- The original set is contained in its partial hull. -/ +theorem subset_partialReinhardtHull : U ⊆ partialReinhardtHull I U := + fun z hz => ⟨z, hz, fun _ => le_rfl, fun _ _ => rfl⟩ + +/-- Partial completeness includes Reinhardt symmetry. -/ +theorem IsCompleteReinhardtIn.isReinhardt (h : IsCompleteReinhardtIn I U) : + IsReinhardt U := fun _ hz _ he => h hz (fun i => (he i).le) (fun i _ => he i) + +/-- The partial hull has the stated partial completeness property. -/ +theorem isCompleteReinhardtIn_partialReinhardtHull : + IsCompleteReinhardtIn I (partialReinhardtHull I U) := by + rintro z ⟨v, hv, hle, heq⟩ w hwl hwe + exact ⟨v, hv, fun i => (hwl i).trans (hle i), fun i hi => (hwe i hi).trans (heq i hi)⟩ + +/-- The partial hull is the smallest partially complete Reinhardt superset. -/ +theorem partialReinhardtHull_min (hUV : U ⊆ V) (hV : IsCompleteReinhardtIn I V) : + partialReinhardtHull I U ⊆ V := by + rintro w ⟨z, hz, hle, heq⟩ + exact hV (hUV hz) hle heq + +/-- Every partial hull retains independent coordinate rotations. -/ +theorem isReinhardt_partialReinhardtHull : IsReinhardt (partialReinhardtHull I U) := + isCompleteReinhardtIn_partialReinhardtHull.isReinhardt + +/-- Partial completion is monotone in the original set. -/ +theorem partialReinhardtHull_mono (hUV : U ⊆ V) : + partialReinhardtHull I U ⊆ partialReinhardtHull I V := + partialReinhardtHull_min (hUV.trans subset_partialReinhardtHull) + isCompleteReinhardtIn_partialReinhardtHull + +/-- Completing twice in the same coordinates has no further effect. -/ +theorem partialReinhardtHull_idem : + partialReinhardtHull I (partialReinhardtHull I U) = partialReinhardtHull I U := + Subset.antisymm (partialReinhardtHull_min Subset.rfl isCompleteReinhardtIn_partialReinhardtHull) + subset_partialReinhardtHull + +/-- Completion in all coordinates recovers the existing complete Reinhardt hull. -/ +theorem partialReinhardtHull_univ : partialReinhardtHull univ U = completeReinhardtHull U := by + ext z + simp [partialReinhardtHull, completeReinhardtHull] + +/-- With no selected coordinates, a Reinhardt set is unchanged. -/ +theorem partialReinhardtHull_empty (hU : IsReinhardt U) : partialReinhardtHull ∅ U = U := by + apply Subset.antisymm ?_ subset_partialReinhardtHull + rintro w ⟨z, hz, _, he⟩ + exact hU hz (fun i => he i (by simp)) + +/-- Partial hulls of open Reinhardt sets are open. A continuous modulus majorant supplies nearby +witnesses in the original open set. -/ +theorem isOpen_partialReinhardtHull [Fintype ι] (ho : IsOpen U) (hR : IsReinhardt U) : + IsOpen (partialReinhardtHull I U) := by + classical + rw [isOpen_iff_mem_nhds] + rintro w ⟨z, hz, hle, heq⟩ + let v : (ι → ℂ) → (ι → ℂ) := fun x i => + if i ∈ I then (max ‖x i‖ ‖z i‖ : ℝ) else (‖x i‖ : ℝ) + have hv : Continuous v := by + apply continuous_pi + intro i + dsimp [v] + split_ifs <;> fun_prop + have hvw : v w ∈ U := by + apply hR hz + intro i + by_cases hi : i ∈ I + · simp [v, hi, max_eq_right (hle i)] + · simp [v, hi, heq i hi] + apply Filter.mem_of_superset (hv.continuousAt.preimage_mem_nhds (ho.mem_nhds hvw)) + intro x hx + refine ⟨v x, hx, ?_, ?_⟩ + · intro i + by_cases hi : i ∈ I + · simp [v, hi, abs_of_nonneg (le_trans (norm_nonneg _) (le_max_left _ _))] + · simp [v, hi] + · intro i hi + simp [v, hi] + +/-- A Laurent monomial is largest at the corner selected by its exponent signs. Summing over all +corners gives a bound independent of the signs. -/ +private theorem norm_laurentTerm_le_sum_corners {n : ℕ} {F : Type*} + [NormedAddCommGroup F] [NormedSpace ℂ F] (c : (Fin n → ℤ) → F) + (a b : Fin n → ℝ) (ha : ∀ i, 0 < a i) (hb : ∀ i, 0 < b i) + (m : Fin n → ℤ) (x : Fin n → ℂ) + (hupper : ∀ i, ‖x i‖ ≤ b i) + (hlower : c m ≠ 0 → ∀ i, m i < 0 → a i ≤ ‖x i‖) : + ‖multivariableLaurentTerm c m x‖ ≤ + ∑ s : Finset (Fin n), ‖multivariableLaurentTerm c m + (fun i => ((if i ∈ s then b i else a i) : ℂ))‖ := by + classical + by_cases hc : c m = 0 + · simp [multivariableLaurentTerm, hc] + let s := Finset.univ.filter (fun i => 0 ≤ m i) + have hcoord (i : Fin n) : ‖x i‖ ^ m i ≤ + ‖((if i ∈ s then b i else a i) : ℂ)‖ ^ m i := by + by_cases hi : 0 ≤ m i + · simpa [s, hi, abs_of_pos (hb i)] using + zpow_le_zpow_left₀ hi (norm_nonneg _) (hupper i) + · have hmi : m i < 0 := lt_of_not_ge hi + have hpow := zpow_le_zpow_left₀ (neg_nonneg.mpr hmi.le) (ha i).le (hlower hc i hmi) + have hinv := one_div_le_one_div_of_le (zpow_pos (ha i) (-m i)) hpow + simpa [s, hi, abs_of_pos (ha i), one_div, zpow_neg] using hinv + calc + ‖multivariableLaurentTerm c m x‖ ≤ ‖multivariableLaurentTerm c m + (fun i => ((if i ∈ s then b i else a i) : ℂ))‖ := by + simp only [multivariableLaurentTerm, norm_smul, norm_prod, norm_zpow] + exact mul_le_mul_of_nonneg_right + (Finset.prod_le_prod₀ (fun i _ => zpow_nonneg (norm_nonneg _) _) (fun i _ => hcoord i)) + (norm_nonneg _) + _ ≤ _ := Finset.single_le_sum + (f := fun t : Finset (Fin n) => ‖multivariableLaurentTerm c m + (fun i => ((if i ∈ t then b i else a i) : ℂ))‖) + (fun _ _ => norm_nonneg _) (Finset.mem_univ s) + +/-- Near a point of the partial hull, choose upper and lower radii whose finitely many corners lie +in the original domain. Lower bounds are needed only in coordinates where a nonzero Laurent +coefficient has negative exponent. -/ +private theorem exists_laurent_box_partialHull {n : ℕ} {I : Set (Fin n)} + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hR : IsReinhardt U) + {F : Type*} [Zero F] (c : (Fin n → ℤ) → F) + (hzero : ∀ m i, (i ∈ I ∨ ∃ z ∈ U, z i = 0) → m i < 0 → c m = 0) + {w : Fin n → ℂ} (hw : w ∈ partialReinhardtHull I U) : + ∃ a b : Fin n → ℝ, (∀ i, 0 < a i) ∧ (∀ i, 0 < b i) ∧ + (∀ s : Finset (Fin n), (fun i => ((if i ∈ s then b i else a i) : ℂ)) ∈ U) ∧ + (∀ i, ‖w i‖ < b i) ∧ (∀ m, c m ≠ 0 → ∀ i, m i < 0 → a i < ‖w i‖) := by + classical + obtain ⟨z, hz, hwz, hweq⟩ := hw + let v (s : Finset (Fin n)) (t : ℝ) : Fin n → ℂ := fun i => + if z i = 0 then (t : ℂ) else ((1 + (if i ∈ s then t else -t)) * ‖z i‖ : ℝ) + have hv (s : Finset (Fin n)) : Continuous (v s) := by + apply continuous_pi + intro i + dsimp [v] + split_ifs <;> fun_prop + have hv0 (s : Finset (Fin n)) : v s 0 ∈ U := by + apply hR hz + intro i + by_cases hi : z i = 0 <;> simp [v, hi] + have hev : ∀ᶠ t in 𝓝 (0 : ℝ), ∀ s : Finset (Fin n), v s t ∈ U := + eventually_all.mpr fun s => (hv s).continuousAt.preimage_mem_nhds (ho.mem_nhds (hv0 s)) + obtain ⟨δ, hδ, hδv⟩ := Metric.eventually_nhds_iff.mp hev + let ε := min (δ / 2) (1 / 2) + have hε : 0 < ε := lt_min (half_pos hδ) (by norm_num) + have hεδ : ε < δ := (min_le_left _ _).trans_lt (half_lt_self hδ) + have hε1 : ε < 1 := (min_le_right _ _).trans_lt (by norm_num) + have hcorners := hδv (show dist ε 0 < δ by simpa [Real.dist_eq, abs_of_pos hε] using hεδ) + let a : Fin n → ℝ := fun i => if z i = 0 then ε else (1 - ε) * ‖z i‖ + let b : Fin n → ℝ := fun i => if z i = 0 then ε else (1 + ε) * ‖z i‖ + have ha (i : Fin n) : 0 < a i := by + dsimp [a] + split_ifs with hi + · exact hε + · exact mul_pos (sub_pos.mpr hε1) (norm_pos_iff.mpr hi) + have hb (i : Fin n) : ‖z i‖ < b i := by + dsimp [b] + split_ifs with hi + · simpa [hi] using hε + · nlinarith [norm_pos_iff.mpr hi] + refine ⟨a, b, ha, fun i => (norm_nonneg _).trans_lt (hb i), ?_, + fun i => (hwz i).trans_lt (hb i), ?_⟩ + · intro s + convert hcorners s using 1 + ext i + by_cases hi : z i = 0 <;> by_cases his : i ∈ s <;> simp [a, b, v, hi, his, sub_eq_add_neg] + · intro m hm i hmi + have hi : i ∉ I := fun hi => hm (hzero m i (Or.inl hi) hmi) + have hzi : z i ≠ 0 := fun hzi => hm (hzero m i (Or.inr ⟨z, hz, hzi⟩) hmi) + rw [hweq i hi] + dsimp [a] + rw [ite_eq_right hzi] + nlinarith [norm_pos_iff.mpr hzi] + +/-- An absolutely convergent Laurent series on an open Reinhardt set converges locally uniformly on +its partial hull when the relevant negative coefficients vanish. This convergence argument is +independent of Laurent expansion for functions. -/ +theorem hasSumLocallyUniformlyOn_laurent_partialReinhardtHull + {n : ℕ} {I : Set (Fin n)} {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hR : IsReinhardt U) + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + (c : (Fin n → ℤ) → F) + (hsum : ∀ z ∈ U, Summable (fun m => ‖multivariableLaurentTerm c m z‖)) + (hzero : ∀ m i, (i ∈ I ∨ ∃ z ∈ U, z i = 0) → m i < 0 → c m = 0) : + HasSumLocallyUniformlyOn (multivariableLaurentTerm c) + (fun z => ∑' m, multivariableLaurentTerm c m z) (partialReinhardtHull I U) := by + classical + apply hasSumLocallyUniformlyOn_of_of_forall_exists_nhds + intro w hw + obtain ⟨a, b, ha, hb, hcorners, hupper, hlower⟩ := + exists_laurent_box_partialHull ho hR c hzero hw + let W : Set (Fin n → ℂ) := {x | ∀ i, ‖x i‖ < b i ∧ (a i < ‖w i‖ → a i < ‖x i‖)} + have hW : IsOpen W := by + simp only [W, ofPred_forall, ofPred_and] + apply isOpen_iInter_of_finite + intro i + apply IsOpen.inter (isOpen_lt (continuous_apply i).norm continuous_const) + apply isOpen_iInter_of_finite + intro _ + exact isOpen_lt continuous_const (continuous_apply i).norm + have hwW : w ∈ W := fun i => ⟨hupper i, fun h => h⟩ + refine ⟨W, nhdsWithin_le_nhds (hW.mem_nhds hwW), ?_⟩ + apply hasSumUniformlyOn_iff_tendstoUniformlyOn.mpr + have hs : Summable (fun m => ∑ t : Finset (Fin n), + ‖multivariableLaurentTerm c m (fun i => ((if i ∈ t then b i else a i) : ℂ))‖) := + summable_sum (fun t _ => hsum _ (hcorners t)) + apply tendstoUniformlyOn_tsum hs + intro m x hx + exact norm_laurentTerm_le_sum_corners c a b ha hb m x + (fun i => (hx i).1.le) (fun hm i hmi => ((hx i).2 (hlower m hm i hmi)).le) + +/-- The Laurent sum is analytic on the partial hull. A term with a negative exponent is either +identically zero or has no coordinate singularity on the hull. -/ +theorem analyticOnNhd_laurentSum_partialReinhardtHull + {n : ℕ} {I : Set (Fin n)} {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hR : IsReinhardt U) + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + (c : (Fin n → ℤ) → F) + (hsum : ∀ z ∈ U, Summable (fun m => ‖multivariableLaurentTerm c m z‖)) + (hzero : ∀ m i, (i ∈ I ∨ ∃ z ∈ U, z i = 0) → m i < 0 → c m = 0) : + AnalyticOnNhd ℂ (fun z => ∑' m, multivariableLaurentTerm c m z) + (partialReinhardtHull I U) := by + apply (hasSumLocallyUniformlyOn_laurent_partialReinhardtHull ho hR c hsum hzero).analyticOnNhd_pi + _ (isOpen_partialReinhardtHull ho hR) + intro m w hw + change AnalyticAt ℂ (fun z => (∏ i, z i ^ m i) • c m) w + by_cases hm : c m = 0 + · simpa only [hm, smul_zero] using + (analyticAt_const : AnalyticAt ℂ (fun _ : Fin n → ℂ => (0 : F)) w) + apply AnalyticAt.smul _ analyticAt_const + apply Finset.analyticAt_fun_prod + intro i _ + by_cases hi : 0 ≤ m i + · exact ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt w).zpow_nonneg hi + · apply ((ContinuousLinearMap.proj (R := ℂ) i).analyticAt w).zpow + intro hwi + change w i = 0 at hwi + have hmi : m i < 0 := lt_of_not_ge hi + by_cases hiI : i ∈ I + · exact hm (hzero m i (Or.inl hiI) hmi) + · obtain ⟨z, hz, _, hweq⟩ := hw + have hzi : z i = 0 := norm_eq_zero.mp (by simpa [hwi] using (hweq i hiI).symm) + exact hm (hzero m i (Or.inr ⟨z, hz, hzi⟩) hmi) + +/-- Extension in the coordinates whose zero hyperplanes meet the connected domain. The Laurent +expansion theorem supplies the coefficients and their vanishing; the series converges locally +uniformly and is analytic on the partial hull. This deduction depends on the Laurent expansion. +No common point on the hyperplanes is required. -/ +theorem exists_extension_partialReinhardtHull {n : ℕ} {I : Set (Fin n)} + {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsConnected U) (hR : IsReinhardt U) + (hmeet : ∀ i ∈ I, ∃ z ∈ U, z i = 0) + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g (partialReinhardtHull I U) ∧ EqOn g f U := by + obtain ⟨z₀, hz₀⟩ := hc.nonempty + obtain ⟨r, hrU, hzr⟩ := hR.exists_strict_modulus_majorant ho hz₀ + have hr : ∀ i, (0 : ℝ) < r i := fun i => (norm_nonneg _).trans_lt (hzr i) + obtain ⟨hsum, hnorm, hneg, _, _⟩ := multivariableLaurent_expansion ho hc.isPreconnected hR hf hr + hrU + let c := multivariableLaurentCoeff f (fun i => (r i : ℝ)) + have hzero : ∀ m i, (i ∈ I ∨ ∃ z ∈ U, z i = 0) → m i < 0 → c m = 0 := by + intro m i hi hmi + exact hneg m i (hi.elim (hmeet i) id) hmi + exact ⟨fun z => ∑' m, multivariableLaurentTerm c m z, + analyticOnNhd_laurentSum_partialReinhardtHull ho hR c hnorm hzero, + fun z hz => (hsum.hasSum hz).tsum_eq⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean new file mode 100644 index 0000000000..1aaaa90d2f --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean @@ -0,0 +1,179 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic + +/-! +# Removable singularities and Riemann extension + +A continuous function analytic away from a countable set is analytic everywhere on its open +domain. The proof applies the one-variable Cauchy theorem off countable sets to coordinate +slices, then uses Osgood. The exceptional set need not be closed or discrete. + +This supplies a proved continuous-removal step toward the classical Riemann extension theory in +[Scheidemann][Scheidemann2005] (2005), Section 4.2, and [Jakóbczak–Jarnicki][JakobczakJarnicki2021] +(2021), Section 2.1. The codomain is a complex Banach space. + +Locally bounded removal across a proper holomorphic zero set is proved by a local Cauchy +construction and gluing. It includes singular zero sets and does not require Weierstrass +preparation, division, or any algebraic regularity of the zero set. + +## Main results + +`analyticOnNhd_of_continuousOn_off_countable` (and `_pi`, `_finiteDimensional`) remove a countable +exceptional set from a continuous function. `exists_analyticOnNhd_extension_across_zeroSet` is +Riemann extension across a proper holomorphic zero set, for locally bounded Banach-valued maps. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [J. Lebl, *Tasty Bits of Several Complex Variables: A Whirlwind Tour of the Subject*][Lebl2026] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +* [T. Suwa, *Complex Analytic Geometry: From the Localization Viewpoint*][Suwa2024] +-/ + +public section + +open Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- A continuous one-variable function analytic off a countable set is analytic on the whole open +domain, by Mathlib's Cauchy power-series theorem off countable sets. -/ +theorem analyticOnNhd_of_continuousOn_off_countable {U S : Set ℂ} {f : ℂ → F} + (hU : IsOpen U) (hS : S.Countable) (hc : ContinuousOn f U) + (hf : AnalyticOnNhd ℂ f (U \ S)) : AnalyticOnNhd ℂ f U := by + intro x hx + obtain ⟨r, hr, hball⟩ := nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hx) + exact (Complex.hasFPowerSeriesOnBall_of_differentiable_off_countable + (R := ⟨r, hr.le⟩) hS (hc.mono hball) + (fun z hz => (hf z ⟨hball (ball_subset_closedBall hz.1), hz.2⟩).differentiableAt) + hr).analyticAt + +/-- Continuous removal of a countable exceptional set in any finite complex coordinate space. Empty +coordinate types are allowed; no closedness of the exceptional set is required. -/ +theorem analyticOnNhd_of_continuousOn_off_countable_pi + {ι : Type*} [Fintype ι] {U S : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hU : IsOpen U) (hS : S.Countable) (hc : ContinuousOn f U) + (hf : AnalyticOnNhd ℂ f (U \ S)) : AnalyticOnNhd ℂ f U := by + classical + apply analyticOnNhd_pi_of_analyticOnNhd_update hU hc + intro z hz i + let L : ℂ → (ι → ℂ) := fun w => update z i w + have hL : Continuous L := by fun_prop + have hLd : Differentiable ℂ L := fun w => (hasDerivAt_update z i w).differentiableAt + have hslice : AnalyticOnNhd ℂ (f ∘ L) ((L ⁻¹' U) \ (L ⁻¹' S)) := by + intro w hw + exact (hf (L w) ⟨hw.1, hw.2⟩).comp (hLd.analyticAt w) + have hinj : Injective L := by + intro v w heq + simpa [L] using congrFun heq i + exact analyticOnNhd_of_continuousOn_off_countable (hU.preimage hL) + (hS.preimage hinj) (hc.comp hL.continuousOn (fun _ hw => hw)) hslice + (z i) (by simpa [L] using hz) + +/-- Continuous removal across a countable set in a finite-dimensional complex normed space. +Coordinates occur only in the proof. -/ +theorem analyticOnNhd_of_continuousOn_off_countable_of_finiteDimensional + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U S : Set E} {f : E → F} (hU : IsOpen U) (hS : S.Countable) + (hc : ContinuousOn f U) (hf : AnalyticOnNhd ℂ f (U \ S)) : + AnalyticOnNhd ℂ f U := by + let e := (Module.finBasis ℂ E).equivFunL + have ha : AnalyticOnNhd ℂ (f ∘ e.symm) (e.symm ⁻¹' U) := by + apply analyticOnNhd_of_continuousOn_off_countable_pi + (S := e.symm ⁻¹' S) (hU.preimage e.symm.continuous) + (hS.preimage e.symm.injective) + (hc.comp e.symm.continuous.continuousOn (fun _ hx => hx)) + intro z hz + exact (hf _ ⟨hz.1, hz.2⟩).comp (e.symm.toContinuousLinearMap.analyticAt z) + intro x hx + simpa [Function.comp_def] using + (ha (e x) (by simpa using hx)).comp (e.toContinuousLinearMap.analyticAt x) + +/-- Local Riemann extension at a point where the defining scalar germ is nonzero. A bound near this +point suffices; no connectedness assumption is needed. -/ +theorem exists_local_extension_across_zeroSet + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) + {a : E} (ha : a ∈ U) (hne : ¬ g =ᶠ[𝓝 a] 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + (hb : ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ g ⁻¹' {0}), ‖f z‖ ≤ C) : + ∃ (V : Set E) (f' : E → F), IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + AnalyticOnNhd ℂ f' V ∧ EqOn f' f (V \ g ⁻¹' {0}) := by + obtain ⟨r, hr, C, hC⟩ := hb + obtain ⟨V, H, hV, haV, hVU, hH, he⟩ := exists_local_extension_zeroSet_of_bounded + (hU.inter isOpen_ball) (hg.mono inter_subset_left) ⟨ha, mem_ball_self hr⟩ hne + (hf.mono (by intro z hz; exact ⟨hz.1.1, hz.2⟩)) + (C := C) (by intro z hz; exact hC z ⟨hz.1.2, hz.1.1, hz.2⟩) + exact ⟨V, H, hV, haV, fun z hz => (hVU hz).1, hH, he⟩ + +/-- Riemann extension on an arbitrary open set: it is enough that the defining scalar function has a +nonzero germ at every point. No connectedness assumption is needed. -/ +theorem exists_analyticOnNhd_extension_across_zeroSet_of_nonzero_germs + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) + (hne : ∀ a ∈ U, ¬ g =ᶠ[𝓝 a] 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + (hb : ∀ a ∈ U, g a = 0 → ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ g ⁻¹' {0}), ‖f z‖ ≤ C) : + ∃ f' : E → F, AnalyticOnNhd ℂ f' U ∧ EqOn f' f (U \ g ⁻¹' {0}) := by + apply exists_analyticOnNhd_extension_of_local sdiff_subset + (subset_closure_nonzero_of_nonzero_germs hU hne) + intro a ha + by_cases hga : g a = 0 + · obtain ⟨V, H, hV, haV, hVU, hH, he⟩ := + exists_local_extension_across_zeroSet hU hg ha (hne a ha) hf (hb a ha hga) + exact ⟨V, H, hV, haV, hVU, hH, fun z hz => he ⟨hz.1, hz.2.2⟩⟩ + · refine ⟨U \ g ⁻¹' {0}, f, ?_, ⟨ha, hga⟩, sdiff_subset, hf, fun _ _ => rfl⟩ + exact hg.continuousOn.isOpen_inter_preimage hU isClosed_singleton.isOpen_compl + +omit [NormedSpace ℂ F] [CompleteSpace F] in +/-- Extensions across a scalar zero set are unique on the domain. The defining germs are assumed +nonzero locally, so the domain may have several connected components. -/ +theorem eqOn_of_extension_across_zeroSet + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {U : Set E} (hU : IsOpen U) {g : E → ℂ} (hne : ∀ a ∈ U, ¬ g =ᶠ[𝓝 a] 0) + {f f₁ f₂ : E → F} (h₁ : ContinuousOn f₁ U) (h₂ : ContinuousOn f₂ U) + (he₁ : EqOn f₁ f (U \ g ⁻¹' {0})) (he₂ : EqOn f₂ f (U \ g ⁻¹' {0})) : + EqOn f₁ f₂ U := + (he₁.trans he₂.symm).of_subset_closure h₁ h₂ sdiff_subset + (subset_closure_nonzero_of_nonzero_germs hU hne) + +/-- **Riemann extension across a holomorphic zero set.** A holomorphic function locally +bounded near the zero set of a nonzero scalar holomorphic function extends across that set. +See [Suwa][Suwa2024] Theorem 1.13, [Lebl][Lebl2026] Theorem 1.6.1, and +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] Theorem 2.1.6. +The proof uses one-variable removability and parameter-dependent Cauchy integration. + +The local bound controls only values outside the removed set. The given function may have +arbitrary values on that set. Extension uniqueness on `U` follows from the independently proved +density and continuous-uniqueness theorems in `ZeroSets.Basic`. -/ +theorem exists_analyticOnNhd_extension_across_zeroSet + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) + {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) (hne : ∃ z ∈ U, g z ≠ 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + (hb : ∀ a ∈ U, g a = 0 → ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ g ⁻¹' {0}), ‖f z‖ ≤ C) : + ∃ f' : E → F, AnalyticOnNhd ℂ f' U ∧ EqOn f' f (U \ g ⁻¹' {0}) := by + apply exists_analyticOnNhd_extension_across_zeroSet_of_nonzero_germs hU hg ?_ hf hb + intro a ha hzero + obtain ⟨b, hbU, hgb⟩ := hne + exact hgb (hg.eqOn_zero_of_preconnected_of_eventuallyEq_zero hconn ha hzero hbU) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Cauchy.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Cauchy.lean new file mode 100644 index 0000000000..77027d52f1 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Cauchy.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.CircleIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral + +/-! +# Banach-valued holomorphic circle integrals + +A compact contour integral of a jointly analytic Banach-valued kernel is analytic in the +parameters. This is the parameter-dependent Cauchy integral used for Riemann extension. The +contour is fixed while its kernel may depend on all parameters. + +## Main results + +`analyticOnNhd_circleIntegral_kernel` is holomorphy of a circle integral of a jointly analytic +Banach-valued kernel. `analyticOnNhd_integral_smul_compact_kernel` is the compactly parametrized +form. +-/ + +public section + +open Complex MeasureTheory Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F α : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + [MeasurableSpace α] [TopologicalSpace α] [BorelSpace α] [T2Space α] + +omit [MeasurableSpace α] [TopologicalSpace α] [BorelSpace α] [T2Space α] in +/-- A Banach-valued jointly analytic kernel has an analytic circle integral. -/ +theorem analyticOnNhd_circleIntegral_kernel + {U : Set E} (hU : IsOpen U) {W : Set (E × ℂ)} + {H : E × ℂ → F} (hH : AnalyticOnNhd ℂ H W) + {c : ℂ} {R : ℝ} (hR : 0 ≤ R) + (hW : ∀ x ∈ U, ∀ t ∈ sphere c R, (x, t) ∈ W) : + AnalyticOnNhd ℂ (fun x => ∮ t in C(c, R), H (x, t)) U := by + have hg : ContinuousOn (fun t : ℝ => deriv (circleMap c R) t) (Icc 0 (2 * Real.pi)) := by + simp only [deriv_circleMap] + fun_prop + have h := analyticOnNhd_integral_smul_compact_kernel (μ := volume) isCompact_Icc + (hg.integrableOn_compact isCompact_Icc) (continuous_circleMap c R).continuousOn hU hH + (fun x hx t _ => hW x hx _ (circleMap_mem_sphere c hR t)) + simpa only [circleIntegral_def_Icc] using h + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/ExceptionalSet.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/ExceptionalSet.lean new file mode 100644 index 0000000000..83283ba5b9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/ExceptionalSet.lean @@ -0,0 +1,164 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity + +/-! +# Riemann extension across locally contained exceptional sets + +An exceptional set is locally contained in analytic zero sets if near each point of the open +domain it lies in the zero set of a nonzero scalar analytic germ. This is the condition called +“thin” in [Jakóbczak–Jarnicki][JakobczakJarnicki2021] §2.1. Closedness is a separate assumption, +expressed by openness of the complement within the open domain. Subsets and finite unions +satisfy the local containment condition. + +Locally bounded Banach-valued analytic functions extend uniquely across such sets. The proof +restricts to a locally containing zero set, applies Riemann extension, then recovers agreement +on the larger original domain by density and continuity. + +## Main results + +`LocallyContainedInAnalyticZeroSet` is the thinness predicate: near every point of the open domain, +the set lies in a proper scalar analytic zero set. +`exists_analyticOnNhd_extension_across_locallyContainedZeroSet` is Riemann extension across such a +set for locally bounded Banach-valued maps. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Near every point of `U`, the set `S` lies in the zero set of a nonzero scalar analytic germ. The +local neighborhoods imply openness of `U`; relative closedness of `S` and connectedness are not +imposed. -/ +@[expose] def LocallyContainedInAnalyticZeroSet (U S : Set E) : Prop := + ∀ a ∈ U, ∃ (V : Set E) (g : E → ℂ), IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + AnalyticOnNhd ℂ g V ∧ (¬ g =ᶠ[𝓝 a] 0) ∧ V ∩ S ⊆ g ⁻¹' {0} + +/-- Local containment provides an open neighborhood inside the ambient domain at every point. -/ +theorem LocallyContainedInAnalyticZeroSet.isOpen {U S : Set E} + (h : LocallyContainedInAnalyticZeroSet U S) : IsOpen U := by + rw [isOpen_iff_mem_nhds] + intro a ha + obtain ⟨V, g, hV, haV, hVU, _⟩ := h a ha + exact Filter.mem_of_superset (hV.mem_nhds haV) hVU + +/-- A subset inherits local containment in analytic zero sets. -/ +theorem LocallyContainedInAnalyticZeroSet.mono {U S T : Set E} + (h : LocallyContainedInAnalyticZeroSet U S) (hTS : T ⊆ S) : + LocallyContainedInAnalyticZeroSet U T := by + intro a ha + obtain ⟨V, g, hV, haV, hVU, hg, hne, hS⟩ := h a ha + exact ⟨V, g, hV, haV, hVU, hg, hne, fun z hz => hS ⟨hz.1, hTS hz.2⟩⟩ + +/-- The empty set is locally contained in analytic zero sets on any open domain. -/ +theorem locallyContainedInAnalyticZeroSet_empty {U : Set E} (hU : IsOpen U) : + LocallyContainedInAnalyticZeroSet U ∅ := by + intro a ha + refine ⟨U, fun _ => 1, hU, ha, Subset.rfl, analyticOnNhd_const, ?_, by simp⟩ + intro h + have he := h.self_of_nhds + simp at he + +/-- The union of two locally contained exceptional sets is locally contained, using the product of +their local defining functions. -/ +theorem LocallyContainedInAnalyticZeroSet.union {U S T : Set E} + (hS : LocallyContainedInAnalyticZeroSet U S) (hT : LocallyContainedInAnalyticZeroSet U T) : + LocallyContainedInAnalyticZeroSet U (S ∪ T) := by + intro a ha + obtain ⟨V, g, hV, haV, hVU, hg, hgn, hSg⟩ := hS a ha + obtain ⟨W, k, hW, haW, _, hk, hkn, hTk⟩ := hT a ha + refine ⟨V ∩ W, fun z => g z * k z, hV.inter hW, ⟨haV, haW⟩, + fun z hz => hVU hz.1, (hg.mono inter_subset_left).mul (hk.mono inter_subset_right), ?_, ?_⟩ + · intro hzero + exact (eventuallyEq_zero_or_eventuallyEq_zero_of_mul (hg a haV) (hk a haW) hzero).elim hgn hkn + · rintro z ⟨⟨hzV, hzW⟩, hzS | hzT⟩ + · exact mul_eq_zero.mpr (Or.inl (hSg ⟨hzV, hzS⟩)) + · exact mul_eq_zero.mpr (Or.inr (hTk ⟨hzW, hzT⟩)) + +/-- A scalar zero set has the local containment property when all defining germs are nonzero. -/ +theorem locallyContainedInAnalyticZeroSet_zeroSet {U : Set E} (hU : IsOpen U) + {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) (hne : ∀ a ∈ U, ¬ g =ᶠ[𝓝 a] 0) : + LocallyContainedInAnalyticZeroSet U (g ⁻¹' {0}) := + fun a ha => ⟨U, g, hU, ha, Subset.rfl, hg, hne a ha, inter_subset_right⟩ + +/-- The complement of a locally contained exceptional set is dense in the domain. -/ +theorem LocallyContainedInAnalyticZeroSet.subset_closure {U S : Set E} + (h : LocallyContainedInAnalyticZeroSet U S) : U ⊆ closure (U \ S) := by + intro a ha + obtain ⟨V, g, hV, haV, hVU, _, hne, hS⟩ := h a ha + rw [Metric.mem_closure_iff] + intro r hr + by_contra! hnone + apply hne + filter_upwards [hV.mem_nhds haV, ball_mem_nhds a hr] with z hz hzr + by_cases hzs : z ∈ S + · exact hS ⟨hz, hzs⟩ + · exact False.elim (not_lt_of_ge (hnone z ⟨hVU hz, hzs⟩) + (by simpa [dist_comm] using hzr)) + +/-- Extensions across a locally contained exceptional set are unique on the domain, with no +assumptions on their values outside the domain. -/ +theorem LocallyContainedInAnalyticZeroSet.extension_unique + {F : Type*} [TopologicalSpace F] [T2Space F] {U S : Set E} + (h : LocallyContainedInAnalyticZeroSet U S) {f f₁ f₂ : E → F} + (h₁ : ContinuousOn f₁ U) (h₂ : ContinuousOn f₂ U) + (he₁ : EqOn f₁ f (U \ S)) (he₂ : EqOn f₂ f (U \ S)) : EqOn f₁ f₂ U := + (he₁.trans he₂.symm).of_subset_closure h₁ h₂ sdiff_subset h.subset_closure + +/-- **Riemann extension for locally contained exceptional sets.** Relative closedness +is expressed by `IsOpen (U \ S)`. Local bounds control values on the complement. +The domain may be disconnected and the target may be any complex Banach space. -/ +theorem exists_analyticOnNhd_extension_across_locallyContainedZeroSet + [FiniteDimensional ℂ E] {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + [CompleteSpace F] {U S : Set E} (hUS : IsOpen (U \ S)) + (hS : LocallyContainedInAnalyticZeroSet U S) {f : E → F} + (hf : AnalyticOnNhd ℂ f (U \ S)) + (hb : ∀ a ∈ U, ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ S), ‖f z‖ ≤ C) : + ∃ H : E → F, AnalyticOnNhd ℂ H U ∧ EqOn H f (U \ S) := by + apply exists_analyticOnNhd_extension_of_local sdiff_subset hS.subset_closure + intro a ha + obtain ⟨V, g, hV, haV, hVU, hg, hne, hSg⟩ := hS a ha + obtain ⟨r, hr, hBV⟩ := Metric.mem_nhds_iff.mp (hV.mem_nhds haV) + let B := ball a r + have hBU : B ⊆ U := hBV.trans hVU + have hgB : AnalyticOnNhd ℂ g B := hg.mono hBV + have hnB : ∃ b ∈ B, g b ≠ 0 := by + by_contra! h + exact hne (Filter.mem_of_superset (ball_mem_nhds a hr) (fun z hz => h z hz)) + have hcomp : B \ g ⁻¹' {0} ⊆ U \ S := by + intro z hz + exact ⟨hBU hz.1, fun hzs => hz.2 (hSg ⟨hBV hz.1, hzs⟩)⟩ + obtain ⟨H, hH, he⟩ := exists_analyticOnNhd_extension_across_zeroSet + isOpen_ball isPreconnected_ball hgB hnB (hf.mono hcomp) (by + intro b hbB _ + obtain ⟨s, hs, C, hC⟩ := hb b (hBU hbB) + exact ⟨s, hs, C, fun z hz => hC z ⟨hz.1, hcomp hz.2⟩⟩) + have hng : ∀ b ∈ B, ¬ g =ᶠ[𝓝 b] 0 := by + intro b hbB hz + obtain ⟨c, hcB, hgc⟩ := hnB + exact hgc (hgB.eqOn_zero_of_preconnected_of_eventuallyEq_zero isPreconnected_ball hbB hz hcB) + refine ⟨B, H, isOpen_ball, mem_ball_self hr, hBU, hH, ?_⟩ + apply eqOn_of_extension_across_zeroSet (g := g) (isOpen_ball.inter hUS) + (fun b hbO => hng b hbO.1) (hH.continuousOn.mono inter_subset_left) + (hf.continuousOn.mono inter_subset_right) + (fun z hz => he ⟨hz.1.1, hz.2⟩) (fun _ _ => rfl) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Geometry.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Geometry.lean new file mode 100644 index 0000000000..d1f5788aa2 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Geometry.lean @@ -0,0 +1,116 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.IsolatedZeros +public import Mathlib.Topology.Compactness.Compact +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic + +/-! +# Circles avoiding an analytic zero set + +A nonzero analytic germ admits a complex line on which it is not identically zero. A small +circle on that line avoids its zeros. Compactness then gives a fixed circle that continues to +avoid the zeros under small translations of its centre. A slightly larger closed disc remains in +the original open domain. No preparation or division theorem is used. + +## Main results + +`exists_nonzero_line_of_analyticAt` produces a complex line on which a nonzero germ is not +identically zero. `exists_translated_circle_avoiding_zeroSet` produces a circle that continues +to avoid the zeros under small translations of its centre. +-/ + +public section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A nonzero analytic germ has a nonzero germ on some complex line through its centre. -/ +theorem exists_nonzero_line_of_analyticAt {g : E → ℂ} {a : E} + (hg : AnalyticAt ℂ g a) (hne : ¬ g =ᶠ[𝓝 a] 0) : + ∃ v : E, ¬ (fun w : ℂ => g (a + w • v)) =ᶠ[𝓝 0] 0 := by + by_cases hga : g a = 0 + · obtain ⟨r, hr, hgon⟩ := hg.exists_ball_analyticOnNhd + obtain ⟨b, hb, hgb⟩ : ∃ b ∈ ball a r, g b ≠ 0 := by + by_contra! h + exact hne (Filter.mem_of_superset (ball_mem_nhds a hr) (fun z hz => h z hz)) + let v := b - a + have hv : 0 < ‖v‖ := norm_pos_iff.mpr (sub_ne_zero.mpr (fun h => hgb (h ▸ hga))) + have hline : AnalyticOnNhd ℂ (fun w : ℂ => g (a + w • v)) (ball 0 (r / ‖v‖)) := by + intro w hw + have hm : a + w • v ∈ ball a r := by + rw [mem_ball, dist_eq_norm, add_sub_cancel_left, norm_smul] + exact (lt_div_iff₀ hv).mp (mem_ball_zero_iff.mp hw) + exact (hgon _ hm).comp_of_eq (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) rfl + refine ⟨v, fun h => ?_⟩ + have he := hline.eqOn_zero_of_preconnected_of_eventuallyEq_zero + (convex_ball (0 : ℂ) (r / ‖v‖)).isPreconnected (mem_ball_self (div_pos hr hv)) h + have h1 : (1 : ℂ) ∈ ball 0 (r / ‖v‖) := by + rw [mem_ball_zero_iff, norm_one, lt_div_iff₀ hv, one_mul] + exact mem_ball_iff_norm.mp hb + exact hgb (by simpa [v] using he h1) + · exact ⟨0, fun h => hga (by simpa using h.self_of_nhds)⟩ + +/-- A fixed translated circle avoids the zero set for all nearby centres, while a larger closed disc +stays in the original domain. This also permits the zero direction when the defining function is +already nonzero at the centre. -/ +theorem exists_translated_circle_avoiding_zeroSet {U : Set E} (hU : IsOpen U) + {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) {a : E} (ha : a ∈ U) + (hne : ¬ g =ᶠ[𝓝 a] 0) : + ∃ (v : E) (r R : ℝ) (V : Set E), 0 < r ∧ r < R ∧ IsOpen V ∧ a ∈ V ∧ + (∀ z ∈ V, ∀ w ∈ closedBall (0 : ℂ) R, z + w • v ∈ U) ∧ + (∀ z ∈ V, ∀ w ∈ sphere (0 : ℂ) r, g (z + w • v) ≠ 0) := by + obtain ⟨v, hv⟩ := exists_nonzero_line_of_analyticAt (hg a ha) hne + have hal : AnalyticAt ℂ (fun w : ℂ => g (a + w • v)) 0 := + (hg a ha).comp_of_eq (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) (by simp) + have he : ∀ᶠ w : ℂ in 𝓝 0, w ≠ 0 → g (a + w • v) ≠ 0 := + eventually_nhdsWithin_iff.mp (hal.eventually_eq_zero_or_eventually_ne_zero.resolve_left hv) + have ht : Tendsto (fun w : ℂ => a + w • v) (𝓝 0) (𝓝 a) := by + have hcont : Continuous (fun w : ℂ => a + w • v) := by fun_prop + simpa using hcont.tendsto (0 : ℂ) + obtain ⟨δ, hδ, hd⟩ := Metric.mem_nhds_iff.mp (inter_mem (ht (hU.mem_nhds ha)) he) + let r := δ / 4 + let R := δ / 2 + have hr : 0 < r := by dsimp [r]; positivity + have hrR : r < R := by dsimp [r, R]; linarith + have hRd : R < δ := by dsimp [R]; linarith + let A : E × ℂ → E := fun p => p.1 + p.2 • v + have hA : Continuous A := continuous_fst.add (continuous_snd.smul continuous_const) + obtain ⟨V₁, W₁, hV₁, _, ha₁, hW₁, hsub₁⟩ := generalized_tube_lemma + (isCompact_singleton (x := a)) (isCompact_closedBall (0 : ℂ) R) + (hU.preimage hA) (by + rintro ⟨z, w⟩ ⟨hz, hw⟩ + rcases hz with rfl + exact (hd (closedBall_subset_ball hRd hw)).1) + have hgood : IsOpen {z ∈ U | g z ≠ 0} := + hg.continuousOn.isOpen_inter_preimage hU isClosed_singleton.isOpen_compl + obtain ⟨V₂, W₂, hV₂, _, ha₂, hW₂, hsub₂⟩ := generalized_tube_lemma + (isCompact_singleton (x := a)) (isCompact_sphere (0 : ℂ) r) + (hgood.preimage hA) (by + rintro ⟨z, w⟩ ⟨hz, hw⟩ + rcases hz with rfl + have hwδ : w ∈ ball (0 : ℂ) δ := + mem_ball.mpr ((mem_sphere.mp hw).trans_lt (hrR.trans hRd)) + refine ⟨(hd hwδ).1, (hd hwδ).2 ?_⟩ + intro h + have heq := mem_sphere.mp hw + simp [h] at heq + linarith) + refine ⟨v, r, R, V₁ ∩ V₂, hr, hrR, hV₁.inter hV₂, + ⟨ha₁ (mem_singleton a), ha₂ (mem_singleton a)⟩, ?_, ?_⟩ + · intro z hz w hw + exact hsub₁ (a := (z, w)) ⟨hz.1, hW₁ hw⟩ + · intro z hz w hw + exact (hsub₂ (a := (z, w)) ⟨hz.2, hW₂ hw⟩).2 + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Gluing.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Gluing.lean new file mode 100644 index 0000000000..7a54bfe1d9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Gluing.lean @@ -0,0 +1,79 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity + +/-! +# Gluing local analytic extensions from a dense subset + +Local continuous extensions of a function on a dense subset agree. The filter limit along that +subset therefore gives a single analytic extension on the whole domain. This elementary +construction uses no sheaf machinery and imposes no connectedness. + +## Main results + +`exists_analyticOnNhd_extension_of_local` glues local analytic extensions from a dense subset. +`subset_closure_nonzero_of_nonzero_germs` is density of the nonvanishing locus from nonzero +germs, without analyticity of a global function. +-/ + +public noncomputable section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +omit [NormedSpace ℂ E] in +/-- A function with nonzero germs everywhere on an open set has dense nonvanishing locus. This +topological statement needs no analyticity assumption. -/ +theorem subset_closure_nonzero_of_nonzero_germs {U : Set E} (hU : IsOpen U) + {g : E → ℂ} (hne : ∀ a ∈ U, ¬ g =ᶠ[𝓝 a] 0) : + U ⊆ closure (U \ g ⁻¹' {0}) := by + intro a ha + rw [Metric.mem_closure_iff] + intro r hr + by_contra! h + apply hne a ha + filter_upwards [hU.mem_nhds ha, ball_mem_nhds a hr] with z hz hzr + by_contra hgz + exact not_lt_of_ge (h z ⟨hz, hgz⟩) (by simpa [dist_comm] using hzr) + +/-- Local analytic extensions from a relatively dense subset glue to an extension on an open set. +Uniqueness is only asserted on that set, not outside it. -/ +theorem exists_analyticOnNhd_extension_of_local + {U S : Set E} {f : E → F} (hSU : S ⊆ U) (hdense : U ⊆ closure S) + (hloc : ∀ a ∈ U, ∃ (V : Set E) (H : E → F), IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + AnalyticOnNhd ℂ H V ∧ EqOn H f (V ∩ S)) : + ∃ H : E → F, AnalyticOnNhd ℂ H U ∧ EqOn H f S := by + let H : E → F := fun a => limUnder (𝓝[S] a) f + have heq : ∀ (V : Set E) (G : E → F), IsOpen V → V ⊆ U → + AnalyticOnNhd ℂ G V → EqOn G f (V ∩ S) → EqOn H G V := by + intro V G hV hVU hG hGf a ha + have : (𝓝[S] a).NeBot := mem_closure_iff_nhdsWithin_neBot.mp (hdense (hVU ha)) + have he : G =ᶠ[𝓝[S] a] f := by + filter_upwards [nhdsWithin_le_nhds (hV.mem_nhds ha), self_mem_nhdsWithin] with z hz hzs + exact hGf ⟨hz, hzs⟩ + have ht : Tendsto f (𝓝[S] a) (𝓝 (G a)) := + ((hG a ha).continuousAt.tendsto.mono_left nhdsWithin_le_nhds).congr' he + exact ht.limUnder_eq + refine ⟨H, ?_, ?_⟩ + · intro a ha + obtain ⟨V, G, hV, haV, hVU, hG, hGf⟩ := hloc a ha + have he : H =ᶠ[𝓝 a] G := + Filter.mem_of_superset (hV.mem_nhds haV) (fun z hz => heq V G hV hVU hG hGf hz) + exact (analyticAt_congr he).mpr (hG a haV) + · intro a ha + obtain ⟨V, G, hV, haV, hVU, hG, hGf⟩ := hloc a (hSU ha) + exact (heq V G hV hVU hG hGf haV).trans (hGf ⟨haV, ha⟩) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Local.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Local.lean new file mode 100644 index 0000000000..6e184e06eb --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/Local.lean @@ -0,0 +1,105 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable + +/-! +# Local Riemann extension in finite-dimensional complex spaces + +Translate a fixed small complex circle through nearby points and integrate the original function +along it. The circle avoids the defining zero set. One-variable removability identifies the +integral with the original function off the zero set; parameter-dependent integration proves +joint analyticity. The target is a complex Banach space, and no Weierstrass or Hartogs extension +theorem is used. + +## Main results + +`exists_local_extension_zeroSet_of_bounded` is local Riemann extension across a scalar zero set +for a locally bounded Banach-valued holomorphic map. +-/ + +public noncomputable section + +open Complex Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- A bounded analytic function off a scalar zero set admits a local analytic extension at every +point where the defining germ is nonzero. The neighborhood need not be connected. -/ +theorem exists_local_extension_zeroSet_of_bounded + {U : Set E} (hU : IsOpen U) {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) + {a : E} (ha : a ∈ U) (hne : ¬ g =ᶠ[𝓝 a] 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + {C : ℝ} (hb : ∀ z ∈ U \ g ⁻¹' {0}, ‖f z‖ ≤ C) : + ∃ (V : Set E) (f' : E → F), IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + AnalyticOnNhd ℂ f' V ∧ EqOn f' f (V \ g ⁻¹' {0}) := by + obtain ⟨v, r, R, V, hr, hrR, hV, haV, hdisc, hcircle⟩ := + exists_translated_circle_avoiding_zeroSet hU hg ha hne + have hR : 0 < R := hr.trans hrR + have hVU : V ⊆ U := by + intro z hz + simpa using hdisc z hz 0 (mem_closedBall_self hR.le) + let W : Set (E × ℂ) := {p | p.2 ≠ 0 ∧ p.1 + p.2 • v ∈ U ∧ g (p.1 + p.2 • v) ≠ 0} + let H : E × ℂ → F := fun p => p.2⁻¹ • f (p.1 + p.2 • v) + have hH : AnalyticOnNhd ℂ H W := by + intro p hp + have hA : AnalyticAt ℂ (fun q : E × ℂ => q.1 + q.2 • v) p := + analyticAt_fst.add (analyticAt_snd.smul analyticAt_const) + exact (analyticAt_snd.inv hp.1).smul ((hf _ hp.2).comp_of_eq hA rfl) + have hW : ∀ z ∈ V, ∀ t ∈ sphere (0 : ℂ) r, (z, t) ∈ W := by + intro z hz t ht + refine ⟨?_, hdisc z hz t (closedBall_subset_closedBall hrR.le (sphere_subset_closedBall ht)), + hcircle z hz t ht⟩ + change t ≠ 0 + intro h + have heq := mem_sphere.mp ht + simp [h] at heq + linarith + let f' : E → F := fun z => (2 * Real.pi * I : ℂ)⁻¹ • ∮ t in C(0, r), H (z, t) + have hfa : AnalyticOnNhd ℂ f' V := + (analyticOnNhd_circleIntegral_kernel hV hH hr.le hW).const_smul + refine ⟨V, f', hV, haV, hVU, hfa, ?_⟩ + intro z hz + have hsl : AnalyticOnNhd ℂ (fun t : ℂ => g (z + t • v)) (ball 0 R) := by + intro t ht + exact (hg _ (hdisc z hz.1 t (ball_subset_closedBall ht))).comp_of_eq + (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) rfl + have hfs : AnalyticOnNhd ℂ (fun t : ℂ => f (z + t • v)) + (ball 0 R \ (fun t : ℂ => g (z + t • v)) ⁻¹' {0}) := by + intro t ht + exact (hf _ ⟨hdisc z hz.1 t (ball_subset_closedBall ht.1), ht.2⟩).comp_of_eq + (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) rfl + have hsne : ∃ t ∈ ball (0 : ℂ) R, g (z + t • v) ≠ 0 := + ⟨0, mem_ball_self hR, by simpa using hz.2⟩ + obtain ⟨fsl, hfsl, heq⟩ := exists_analyticOnNhd_extension_zeroSet_oneVariable + isOpen_ball (convex_ball (0 : ℂ) R).isPreconnected hsl hsne hfs (by + intro t ht _ + refine ⟨1, zero_lt_one, C, ?_⟩ + intro w hw + exact hb _ ⟨hdisc z hz.1 w (ball_subset_closedBall hw.2.1), hw.2.2⟩) + have hcauchy := + Complex.two_pi_I_inv_smul_circleIntegral_sub_inv_smul_of_differentiable_on_off_countable + (f := fsl) countable_empty (mem_ball_self hr) + (hfsl.continuousOn.mono (closedBall_subset_ball hrR)) + (fun w hw => (hfsl w (ball_subset_ball hrR.le hw.1)).differentiableAt) + have hboundary : (∮ t in C(0, r), H (z, t)) = ∮ t in C(0, r), (t - 0)⁻¹ • fsl t := by + apply circleIntegral.integral_congr hr.le + intro t ht + have htR : t ∈ ball (0 : ℂ) R := closedBall_subset_ball hrR (sphere_subset_closedBall ht) + simp only [H, sub_zero, heq ⟨htR, hcircle z hz.1 t ht⟩] + exact (congrArg (fun q => (2 * Real.pi * I : ℂ)⁻¹ • q) hboundary).trans + (hcauchy.trans (by simpa using heq ⟨mem_ball_self hR, by simpa using hz.2⟩)) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/OneVariable.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/OneVariable.lean new file mode 100644 index 0000000000..796fde70b4 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity/OneVariable.lean @@ -0,0 +1,81 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.IsolatedZeros +public import Mathlib.Analysis.Complex.RemovableSingularity + +/-! +# One-variable extension across analytic zero sets + +Mathlib's Banach-valued isolated-singularity theorem applies at every zero of a nonzero scalar +analytic function. Redefining the function by its punctured limit at each zero gives one +extension on the whole open set. This is the slice theorem used in the several-variable Riemann +extension argument. + +## Main results + +`exists_analyticOnNhd_extension_zeroSet_oneVariable` extends a Banach-valued holomorphic +function across the zeros of a nonzero scalar analytic function of one variable. +-/ + +public noncomputable section + +open Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- A bounded Banach-valued function analytic off the zeros of a nonzero one-variable analytic +function extends across all of those zeros. Bounds are needed only near zeros. -/ +theorem exists_analyticOnNhd_extension_zeroSet_oneVariable + {U : Set ℂ} (hU : IsOpen U) (hc : IsPreconnected U) + {g : ℂ → ℂ} (hg : AnalyticOnNhd ℂ g U) (hne : ∃ z ∈ U, g z ≠ 0) + {f : ℂ → F} (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + (hb : ∀ a ∈ U, g a = 0 → ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ (U \ g ⁻¹' {0}), ‖f z‖ ≤ C) : + ∃ f' : ℂ → F, AnalyticOnNhd ℂ f' U ∧ EqOn f' f (U \ g ⁻¹' {0}) := by + classical + let f' : ℂ → F := fun z => if g z = 0 then limUnder (𝓝[≠] z) f else f z + refine ⟨f', ?_, fun z hz => by simp [f', show g z ≠ 0 from hz.2]⟩ + intro a ha + by_cases hga : g a = 0 + · have hnloc : ¬ g =ᶠ[𝓝 a] 0 := by + intro h + obtain ⟨b, hb, hgb⟩ := hne + exact hgb (hg.eqOn_zero_of_preconnected_of_eventuallyEq_zero hc ha h hb) + have hisol := ((hg a ha).eventually_eq_zero_or_eventually_ne_zero).resolve_left hnloc + obtain ⟨r, hr, C, hC⟩ := hb a ha hga + have he : ∀ᶠ z in 𝓝 a, z ≠ a → g z ≠ 0 := eventually_nhdsWithin_iff.mp hisol + obtain ⟨s, hs, hsa⟩ := Metric.mem_nhds_iff.mp + (inter_mem (hU.mem_nhds ha) (inter_mem (ball_mem_nhds a hr) he)) + have hdiff : DifferentiableOn ℂ f (ball a s \ {a}) := by + intro z hz + exact (hf z ⟨(hsa hz.1).1, (hsa hz.1).2.2 hz.2⟩).differentiableAt.differentiableWithinAt + have hbound : BddAbove ((norm ∘ f) '' (ball a s \ {a})) := by + refine ⟨C, ?_⟩ + rintro _ ⟨z, hz, rfl⟩ + exact hC z ⟨(hsa hz.1).2.1, (hsa hz.1).1, (hsa hz.1).2.2 hz.2⟩ + have hd := Complex.differentiableOn_update_limUnder_of_bddAbove + (ball_mem_nhds a hs) hdiff hbound + have han : AnalyticAt ℂ (update f a (limUnder (𝓝[≠] a) f)) a := + hd.analyticAt (ball_mem_nhds a hs) + apply (analyticAt_congr (g := update f a (limUnder (𝓝[≠] a) f)) ?_).mpr han + filter_upwards [he] with z hz + by_cases hza : z = a + · subst z + simp [f', hga] + · simp [f', hz hza, hza] + · have he : f' =ᶠ[𝓝 a] f := by + filter_upwards [(hg a ha).continuousAt.eventually_ne hga] with z hz + simp [f', hz] + exact (analyticAt_congr he).mpr (hf a ⟨ha, hga⟩) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge.lean new file mode 100644 index 0000000000..6db956e137 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge.lean @@ -0,0 +1,382 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.MvPolynomial.Basic +public import Mathlib.Analysis.Analytic.Polynomial +public import Mathlib.Topology.Algebra.InfiniteSum.UniformOn +public import Mathlib.Topology.Algebra.MvPolynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor + +/-! +# Runge pairs, Runge domains and polynomial hulls + +A pair of sets `U ⊆ V` is a Runge pair if every holomorphic function on `U` is a locally uniform +limit of holomorphic functions on `V`; an open subset of `ℂⁿ` is a Runge domain if every +holomorphic function on it is a locally uniform limit of polynomials. Both notions are stated +through approximation within `ε` on compact subsets, and for open sets this is shown equivalent +to convergence of a sequence locally uniformly. + +The polynomial hull of a compact set is the set of points where every polynomial is bounded by +its supremum on the set; it agrees with the hull relative to all entire functions, because +entire functions are locally uniform limits of their Taylor polynomials. Consequently a set is a +Runge domain exactly when it forms a Runge pair with the whole space. + +For a Runge domain `U`, the polynomial hull of a compact `K ⊆ U` meets `U` in the holomorphic +hull of `K` relative to `U`, and for a Runge domain of holomorphy this set is compact. These are +the elementary implications of the hull characterization of Runge domains +([Hörmander][Hormander1973], Theorem 2.7.3; [Jakóbczak–Jarnicki][JakobczakJarnicki2021], Theorem +4.3.3). The converse implications constitute the Oka–Weil theorem and are not included. + +References: [Hörmander][Hormander1973] (1973), Section 2.7; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Section 4.3; +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Section 1.7. + +## Main definitions + +* `polynomialHull`: The polynomial hull of a set: the points at which every polynomial is bounded by + each of its bounds on the set. +* `IsPolynomiallyConvex`: A set is polynomially convex if it equals its polynomial hull. +* `IsRungePair`: A **Runge pair**: `U ⊆ V`, and every holomorphic function on `U` is approximated + within `ε` on every compact subset of `U` by a holomorphic function on `V`. +* `IsRungeDomain`: A **Runge domain** in `ℂⁿ`: every holomorphic function is approximated within `ε` + on every compact subset by a polynomial. + +## Main results + +* `exists_mvPolynomial_approx_of_entire`: **Entire functions are locally uniform limits of + polynomials.** On a compact set, an entire function is approximated within `ε` by a Taylor + polynomial. +* `polynomialHull_eq_holomorphicHull_univ`: **Polynomial and entire hulls agree** on compact sets, + since entire functions are locally uniform limits of polynomials. +* `IsRungeDomain.polynomialHull_inter`: **Hull identity for Runge domains.** For a Runge domain `U` + and a compact `K ⊆ U`, the polynomial hull of `K` meets `U` exactly in the holomorphic hull of `K` + relative to `U`. +* `IsRungePair.exists_seq_tendstoLocallyUniformlyOn`: **Sequence formulation.** For an open `U`, a + Runge pair provides, for each holomorphic function on `U`, a sequence of holomorphic functions on + `V` converging locally uniformly. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +section Polynomials + +variable {n : ℕ} + +/-- A finite sum of monomials with complex coefficients, indexed by finitely supported +multi-indices, is the evaluation of a polynomial. -/ +theorem exists_mvPolynomial_eval_eq_sum (s : Finset (Fin n →₀ ℕ)) (c : (Fin n →₀ ℕ) → ℂ) : + ∃ P : MvPolynomial (Fin n) ℂ, ∀ z : Fin n → ℂ, + MvPolynomial.eval z P = ∑ m ∈ s, (∏ i, z i ^ m i) * c m := by + refine ⟨∑ m ∈ s, MvPolynomial.C (c m) * ∏ i, MvPolynomial.X i ^ (m i), fun z => ?_⟩ + simp only [map_sum, map_mul, MvPolynomial.eval_C, map_prod, map_pow, MvPolynomial.eval_X] + refine Finset.sum_congr rfl fun m _ => ?_ + ring + +/-- A finite sum of monomials with complex coefficients, indexed by functions `Fin n → ℕ`, is the +evaluation of a polynomial. -/ +theorem exists_mvPolynomial_eval_eq_sum' (s : Finset (Fin n → ℕ)) (c : (Fin n → ℕ) → ℂ) : + ∃ P : MvPolynomial (Fin n) ℂ, ∀ z : Fin n → ℂ, + MvPolynomial.eval z P = ∑ m ∈ s, (∏ i, z i ^ m i) * c m := by + refine ⟨∑ m ∈ s, MvPolynomial.C (c m) * ∏ i, MvPolynomial.X i ^ (m i), fun z => ?_⟩ + simp only [map_sum, map_mul, MvPolynomial.eval_C, map_prod, map_pow, MvPolynomial.eval_X] + refine Finset.sum_congr rfl fun m _ => ?_ + ring + +/-- **Entire functions are locally uniform limits of polynomials.** On a compact set, an entire +function is approximated within `ε` by a Taylor polynomial. -/ +theorem exists_mvPolynomial_approx_of_entire {g : (Fin n → ℂ) → ℂ} + (hg : AnalyticOnNhd ℂ g univ) {K : Set (Fin n → ℂ)} (hK : IsCompact K) {ε : ℝ} (hε : 0 < ε) : + ∃ P : MvPolynomial (Fin n) ℂ, ∀ z ∈ K, ‖g z - MvPolynomial.eval z P‖ < ε := by + obtain ⟨B, hB⟩ := hK.isBounded.subset_closedBall 0 + set R : Fin n → ℝ := fun _ => max B 0 + 1 with hRdef + have hR : ∀ i, 0 < R i := fun _ => by positivity + set s : Fin n → ℝ := fun _ => max B 0 with hsdef + have hs : ∀ i, 0 ≤ s i := fun _ => le_max_right _ _ + have hsR : ∀ i, s i < R i := fun _ => by simp [hsdef, hRdef] + have hKs : K ⊆ closedPolydisc 0 s := by + intro z hz + rw [mem_closedPolydisc] + intro i + have h1 : ‖z i‖ ≤ ‖z‖ := norm_le_pi_norm z i + have h2 : ‖z‖ ≤ B := mem_closedBall_zero_iff.mp (hB hz) + rw [Pi.zero_apply, dist_zero_right] + exact h1.trans (h2.trans (le_max_left _ _)) + have hcont : ContinuousOn g (closedPolydisc 0 R) := hg.continuousOn.mono (subset_univ _) + have hslice : ∀ z ∈ closedPolydisc 0 R, ∀ i, + AnalyticAt ℂ (fun v => g (update z i v)) (z i) := + fun z _ i => by convert hg.analyticAt_update (mem_univ z) i + obtain ⟨M, hM⟩ := (isCompact_closedPolydisc 0 R).exists_bound_of_continuousOn hcont + have hsum := hasSumUniformlyOn_polydiscTaylor hR hs hsR hcont hslice hM + rw [hasSumUniformlyOn_iff_tendstoUniformlyOn, Metric.tendstoUniformlyOn_iff] at hsum + obtain ⟨t, ht⟩ := (hsum ε hε).exists + obtain ⟨P, hP⟩ := exists_mvPolynomial_eval_eq_sum' t + (fun m => polydiscCauchyCoeffWithRadii g 0 R m) + refine ⟨P, fun z hz => ?_⟩ + have := ht z (hKs hz) + rw [dist_eq_norm, zero_add] at this + rw [hP z] + simpa only [smul_eq_mul] using this + +end Polynomials + +section Hull + +variable {n : ℕ} {σ : Type*} + +/-- The polynomial hull of a set: the points at which every polynomial is bounded by each of its +bounds on the set. The variables may be indexed by any type. -/ +@[expose] def polynomialHull (K : Set (σ → ℂ)) : Set (σ → ℂ) := + {z | ∀ P : MvPolynomial σ ℂ, ∀ M : ℝ, + (∀ w ∈ K, ‖MvPolynomial.eval w P‖ ≤ M) → ‖MvPolynomial.eval z P‖ ≤ M} + +/-- A set is polynomially convex if it equals its polynomial hull. -/ +@[expose] def IsPolynomiallyConvex (K : Set (σ → ℂ)) : Prop := polynomialHull K = K + +/-- A set lies in its polynomial hull. -/ +theorem subset_polynomialHull (K : Set (σ → ℂ)) : K ⊆ polynomialHull K := + fun z hz _ _ hM => hM z hz + +/-- The polynomial hull is monotone. -/ +theorem polynomialHull_mono {K L : Set (σ → ℂ)} (h : K ⊆ L) : + polynomialHull K ⊆ polynomialHull L := + fun _ hz P M hM => hz P M fun w hw => hM w (h hw) + +/-- The polynomial hull is closed. -/ +theorem isClosed_polynomialHull (K : Set (σ → ℂ)) : IsClosed (polynomialHull K) := by + have : polynomialHull K = ⋂ P : MvPolynomial σ ℂ, ⋂ M : ℝ, + ⋂ _ : (∀ w ∈ K, ‖MvPolynomial.eval w P‖ ≤ M), {z | ‖MvPolynomial.eval z P‖ ≤ M} := by + ext z + simp only [polynomialHull, mem_ofPred_eq, mem_iInter] + rw [this] + exact isClosed_iInter fun P => isClosed_iInter fun M => isClosed_iInter fun _ => + isClosed_le (P.continuous_eval).norm continuous_const + +/-- The polynomial hull of a bounded set is bounded, by the coordinate polynomials. -/ +theorem polynomialHull_subset_closedBall {K : Set (Fin n → ℂ)} {B : ℝ} (hB0 : 0 ≤ B) + (hK : K ⊆ closedBall 0 B) : polynomialHull K ⊆ closedBall 0 B := by + intro z hz + rw [mem_closedBall_zero_iff, pi_norm_le_iff_of_nonneg hB0] + intro i + have := hz (MvPolynomial.X i) B fun w hw => by + rw [MvPolynomial.eval_X] + exact (norm_le_pi_norm w i).trans (mem_closedBall_zero_iff.mp (hK hw)) + rwa [MvPolynomial.eval_X] at this + +/-- The polynomial hull of a compact set is compact. -/ +theorem isCompact_polynomialHull {K : Set (Fin n → ℂ)} (hK : IsCompact K) : + IsCompact (polynomialHull K) := by + obtain ⟨B, hB⟩ := hK.isBounded.subset_closedBall 0 + have hB' : K ⊆ closedBall 0 (max B 0) := + hB.trans (closedBall_subset_closedBall (le_max_left _ _)) + exact isCompact_of_isClosed_isBounded (isClosed_polynomialHull K) + (isBounded_closedBall.subset (polynomialHull_subset_closedBall (le_max_right _ _) hB')) + +/-- **Polynomial and entire hulls agree** on compact sets, since entire functions are locally +uniform limits of polynomials. -/ +theorem polynomialHull_eq_holomorphicHull_univ {K : Set (Fin n → ℂ)} (hK : IsCompact K) : + polynomialHull K = holomorphicHull univ K := by + ext z + constructor + · intro hz + refine ⟨mem_univ z, fun f hf M hM => ?_⟩ + refine le_of_forall_pos_le_add fun ε hε => ?_ + obtain ⟨P, hP⟩ := exists_mvPolynomial_approx_of_entire hf (hK.insert z) (half_pos hε) + have hPK : ∀ w ∈ K, ‖MvPolynomial.eval w P‖ ≤ M + ε / 2 := fun w hw => by + have h1 := hP w (mem_insert_of_mem z hw) + have h2 := hM w hw + calc ‖MvPolynomial.eval w P‖ = ‖f w - (f w - MvPolynomial.eval w P)‖ := by ring_nf + _ ≤ ‖f w‖ + ‖f w - MvPolynomial.eval w P‖ := norm_sub_le _ _ + _ ≤ M + ε / 2 := by linarith + have hz' := hz P (M + ε / 2) hPK + have h3 := hP z (mem_insert z K) + calc ‖f z‖ = ‖(f z - MvPolynomial.eval z P) + MvPolynomial.eval z P‖ := by ring_nf + _ ≤ ‖f z - MvPolynomial.eval z P‖ + ‖MvPolynomial.eval z P‖ := norm_add_le _ _ + _ ≤ M + ε := by linarith + · intro hz P M hM + exact hz.2 _ (AnalyticOnNhd.eval_mvPolynomial P) M hM + +/-- The polynomial hull is polynomially convex. -/ +theorem isPolynomiallyConvex_polynomialHull (K : Set (σ → ℂ)) : + IsPolynomiallyConvex (polynomialHull K) := by + refine Subset.antisymm (fun z hz P M hM => ?_) (subset_polynomialHull _) + exact hz P M fun w hw => hw P M hM + +end Hull + +section Runge + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A **Runge pair**: `U ⊆ V`, and every holomorphic function on `U` is approximated within `ε` on +every compact subset of `U` by a holomorphic function on `V`. -/ +@[expose] def IsRungePair (U V : Set E) : Prop := + U ⊆ V ∧ ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → ∀ K : Set E, IsCompact K → K ⊆ U → ∀ ε > 0, + ∃ g : E → ℂ, AnalyticOnNhd ℂ g V ∧ ∀ z ∈ K, ‖f z - g z‖ < ε + +/-- A Runge pair is an inclusion. -/ +theorem IsRungePair.subset {U V : Set E} (h : IsRungePair U V) : U ⊆ V := h.1 + +/-- Every set forms a Runge pair with itself. -/ +theorem isRungePair_refl (U : Set E) : IsRungePair U U := + ⟨Subset.rfl, fun f hf _ _ _ ε hε => ⟨f, hf, fun _ _ => by simpa using hε⟩⟩ + +/-- Runge pairs are transitive. -/ +theorem IsRungePair.trans {U V W : Set E} (h₁ : IsRungePair U V) (h₂ : IsRungePair V W) : + IsRungePair U W := by + refine ⟨h₁.1.trans h₂.1, fun f hf K hK hKU ε hε => ?_⟩ + obtain ⟨g, hg, hfg⟩ := h₁.2 f hf K hK hKU (ε / 2) (half_pos hε) + obtain ⟨k, hk, hgk⟩ := h₂.2 g hg K hK (hKU.trans h₁.1) (ε / 2) (half_pos hε) + refine ⟨k, hk, fun z hz => ?_⟩ + calc ‖f z - k z‖ = ‖(f z - g z) + (g z - k z)‖ := by ring_nf + _ ≤ ‖f z - g z‖ + ‖g z - k z‖ := norm_add_le _ _ + _ < ε / 2 + ε / 2 := add_lt_add (hfg z hz) (hgk z hz) + _ = ε := add_halves ε + +/-- A **Runge domain** in `ℂ^ι`, for a finite index type `ι`: every holomorphic function is + approximated within `ε` on every +compact subset by a polynomial. Being a domain of holomorphy is not part of the definition. -/ +@[expose] def IsRungeDomain {ι : Type*} [Fintype ι] (U : Set (ι → ℂ)) : Prop := + ∀ f : (ι → ℂ) → ℂ, AnalyticOnNhd ℂ f U → ∀ K : Set (ι → ℂ), IsCompact K → K ⊆ U → + ∀ ε > 0, ∃ P : MvPolynomial ι ℂ, ∀ z ∈ K, ‖f z - MvPolynomial.eval z P‖ < ε + +variable {n : ℕ} + +/-- A set is a Runge domain exactly when it forms a Runge pair with the whole space. -/ +theorem isRungeDomain_iff_isRungePair_univ (U : Set (Fin n → ℂ)) : + IsRungeDomain U ↔ IsRungePair U univ := by + constructor + · intro h + refine ⟨subset_univ U, fun f hf K hK hKU ε hε => ?_⟩ + obtain ⟨P, hP⟩ := h f hf K hK hKU ε hε + exact ⟨fun z => MvPolynomial.eval z P, AnalyticOnNhd.eval_mvPolynomial P, hP⟩ + · intro h f hf K hK hKU ε hε + obtain ⟨g, hg, hfg⟩ := h.2 f hf K hK hKU (ε / 2) (half_pos hε) + obtain ⟨P, hP⟩ := exists_mvPolynomial_approx_of_entire hg hK (half_pos hε) + refine ⟨P, fun z hz => ?_⟩ + calc ‖f z - MvPolynomial.eval z P‖ = ‖(f z - g z) + (g z - MvPolynomial.eval z P)‖ := by ring_nf + _ ≤ ‖f z - g z‖ + ‖g z - MvPolynomial.eval z P‖ := norm_add_le _ _ + _ < ε / 2 + ε / 2 := add_lt_add (hfg z hz) (hP z hz) + _ = ε := add_halves ε + +/-- The whole space is a Runge domain. -/ +theorem isRungeDomain_univ : IsRungeDomain (univ : Set (Fin n → ℂ)) := + (isRungeDomain_iff_isRungePair_univ _).mpr (isRungePair_refl _) + +/-- **Hull identity for Runge domains.** For a Runge domain `U` and a compact `K ⊆ U`, the +polynomial hull of `K` meets `U` exactly in the holomorphic hull of `K` relative to `U`. -/ +theorem IsRungeDomain.polynomialHull_inter {U : Set (Fin n → ℂ)} (h : IsRungeDomain U) + {K : Set (Fin n → ℂ)} (hK : IsCompact K) (hKU : K ⊆ U) : + polynomialHull K ∩ U = holomorphicHull U K := by + ext z + constructor + · rintro ⟨hz, hzU⟩ + refine ⟨hzU, fun f hf M hM => ?_⟩ + refine le_of_forall_pos_le_add fun ε hε => ?_ + obtain ⟨P, hP⟩ := h f hf (insert z K) (hK.insert z) (insert_subset hzU hKU) (ε / 2) (half_pos + hε) + have hPK : ∀ w ∈ K, ‖MvPolynomial.eval w P‖ ≤ M + ε / 2 := fun w hw => by + have h1 := hP w (mem_insert_of_mem z hw) + have h2 := hM w hw + calc ‖MvPolynomial.eval w P‖ = ‖f w - (f w - MvPolynomial.eval w P)‖ := by ring_nf + _ ≤ ‖f w‖ + ‖f w - MvPolynomial.eval w P‖ := norm_sub_le _ _ + _ ≤ M + ε / 2 := by linarith + have hz' := hz P (M + ε / 2) hPK + have h3 := hP z (mem_insert z K) + calc ‖f z‖ = ‖(f z - MvPolynomial.eval z P) + MvPolynomial.eval z P‖ := by ring_nf + _ ≤ ‖f z - MvPolynomial.eval z P‖ + ‖MvPolynomial.eval z P‖ := norm_add_le _ _ + _ ≤ M + ε := by linarith + · intro hz + refine ⟨fun P M hM => hz.2 _ ((AnalyticOnNhd.eval_mvPolynomial P).mono (subset_univ U)) M hM, + hz.1⟩ + +/-- If the polynomial hull of every compact subset agrees with its holomorphic hull, then in +particular the intersection with `U` does. -/ +theorem polynomialHull_inter_eq_of_eq {U K : Set (Fin n → ℂ)} + (h : polynomialHull K = holomorphicHull U K) : + polynomialHull K ∩ U = holomorphicHull U K := by + rw [h] + exact inter_eq_left.mpr (holomorphicHull_subset U K) + +/-- For a Runge domain of holomorphy, the polynomial hull of a compact subset meets the domain in a +compact set. The converse implications are the Oka–Weil theorem. -/ +theorem IsRungeDomain.isCompact_polynomialHull_inter {U : Set (Fin n → ℂ)} (h : IsRungeDomain U) + (hU : IsDomainOfHolomorphy U) (ho : IsOpen U) {K : Set (Fin n → ℂ)} (hK : IsCompact K) + (hKU : K ⊆ U) : IsCompact (polynomialHull K ∩ U) := by + rw [h.polynomialHull_inter hK hKU] + exact hU.isHolomorphicallyConvex ho K hK hKU + +end Runge + +section Sequences + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Approximation on compact sets follows from locally uniform convergence of a sequence. -/ +theorem isRungePair_of_forall_exists_seq {U V : Set E} (hUV : U ⊆ V) + (h : ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → ∃ g : ℕ → E → ℂ, + (∀ k, AnalyticOnNhd ℂ (g k) V) ∧ TendstoLocallyUniformlyOn g f atTop U) : + IsRungePair U V := by + refine ⟨hUV, fun f hf K hK hKU ε hε => ?_⟩ + obtain ⟨g, hg, hlim⟩ := h f hf + have hu := (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK).mp (hlim.mono hKU) + rw [Metric.tendstoUniformlyOn_iff] at hu + obtain ⟨k, hk⟩ := (hu ε hε).exists + exact ⟨g k, hg k, fun z hz => by rw [← dist_eq_norm]; exact hk z hz⟩ + +variable [ProperSpace E] + +/-- **Sequence formulation.** For an open `U`, a Runge pair provides, for each holomorphic +function on `U`, a sequence of holomorphic functions on `V` converging locally uniformly. -/ +theorem IsRungePair.exists_seq_tendstoLocallyUniformlyOn {U V : Set E} (hU : IsOpen U) + (h : IsRungePair U V) {f : E → ℂ} (hf : AnalyticOnNhd ℂ f U) : + ∃ g : ℕ → E → ℂ, (∀ k, AnalyticOnNhd ℂ (g k) V) ∧ TendstoLocallyUniformlyOn g f atTop U := by + obtain ⟨L, hLc, hLU, hLmono, hLex⟩ := hU.exists_compact_exhaustion + have hchoice : ∀ k : ℕ, ∃ g : E → ℂ, AnalyticOnNhd ℂ g V ∧ + ∀ z ∈ L k, ‖f z - g z‖ < 1 / ((k : ℝ) + 1) := + fun k => h.2 f hf (L k) (hLc k) (hLU k) _ (by positivity) + choose g hg using hchoice + refine ⟨g, fun k => (hg k).1, ?_⟩ + rw [tendstoLocallyUniformlyOn_iff_forall_isCompact hU] + intro K hKU hK + obtain ⟨k₀, hk₀⟩ := hLex K hK hKU + have hLmono' : ∀ k, k₀ ≤ k → L k₀ ⊆ L k := fun k hk => by + induction hk with + | refl => exact Subset.rfl + | step _ ih => exact ih.trans (hLmono _) + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + obtain ⟨N, hN⟩ := exists_nat_gt (1 / ε) + filter_upwards [eventually_ge_atTop (max k₀ N)] with k hk z hz + have hzk : z ∈ L k := hLmono' k ((le_max_left _ _).trans hk) (hk₀ hz) + have h1 := (hg k).2 z hzk + rw [dist_eq_norm] + refine h1.trans_le ?_ + have hkN : (N : ℝ) ≤ (k : ℝ) := by exact_mod_cast (le_max_right _ _).trans hk + rw [div_le_iff₀ (by positivity)] + rw [div_lt_iff₀ hε] at hN + nlinarith + +end Sequences + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge/Examples.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge/Examples.lean new file mode 100644 index 0000000000..ef5ba77bac --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Runge/Examples.lean @@ -0,0 +1,206 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.MvPolynomial.Monad +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge + +/-! +# Examples of Runge domains + +Complete Reinhardt open sets in `ℂⁿ` are Runge domains, since holomorphic functions on them are +represented by their Taylor series at the origin, converging locally uniformly. More generally, +circular connected open sets containing the origin are Runge domains, since holomorphic +functions on them are locally uniform sums of their homogeneous expansions, whose terms are +polynomials. In particular polydiscs and balls centered at the origin, and the whole space, are +Runge domains. + +Runge domains are transported by holomorphic maps with polynomial inverses: if `U` is Runge, `Φ` +is holomorphic on `U` with values in `U'`, and `Ψ` is a polynomial map from `U'` into `U` with +`Φ ∘ Ψ = id` on `U'`, then `U'` is Runge. Translates and polynomial-automorphic images of Runge +domains are Runge ([Jakóbczak–Jarnicki][JakobczakJarnicki2021], Proposition 4.3.2). + +References: [Hörmander][Hormander1973] (1973), Section 2.7; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Section 4.3. + +## Main definitions + +* `mvPolynomialMap`: The polynomial map with components `G i`. + +## Main results + +* `IsCompleteReinhardt.isRungeDomain`: **Complete Reinhardt open sets are Runge domains** : + holomorphic functions are locally uniform sums of their Taylor series at the origin. +* `IsCircular.isRungeDomain`: **Circular connected open sets containing the origin are Runge + domains** : holomorphic functions are locally uniform sums of their homogeneous expansions, whose + terms are polynomials. +* `IsRungeDomain.transport`: **Transport of Runge domains.** If `U` is a Runge domain, `Φ` is + holomorphic on `U` with values in `U'`, and `Ψ` is a polynomial map from `U'` into `U` with `Φ ∘ Ψ + = id` on `U'`, then `U'` is a Runge domain. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {n : ℕ} + +section Reinhardt + +/-- **Complete Reinhardt open sets are Runge domains**: holomorphic functions are locally uniform +sums of their Taylor series at the origin. -/ +theorem IsCompleteReinhardt.isRungeDomain {U : Set (Fin n → ℂ)} (ho : IsOpen U) + (hc : IsCompleteReinhardt U) : IsRungeDomain U := by + intro f hf K hK hKU ε hε + obtain ⟨hdom, heq⟩ + := IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum ho hc hf + have hsum := hasSumUniformlyOn_powerSeries (taylorCoefficientsAtZero f) hK (hKU.trans hdom) + rw [hasSumUniformlyOn_iff_tendstoUniformlyOn, Metric.tendstoUniformlyOn_iff] at hsum + obtain ⟨t, ht⟩ := (hsum ε hε).exists + obtain ⟨P, hP⟩ := exists_mvPolynomial_eval_eq_sum t (fun m => taylorCoefficientsAtZero f m) + refine ⟨P, fun z hz => ?_⟩ + have := ht z hz + rw [dist_eq_norm, heq (hKU hz)] at this + rw [hP z] + simpa only [smul_eq_mul] using this + +/-- Polydiscs centered at the origin are Runge domains. -/ +theorem isRungeDomain_polydisc (r : Fin n → ℝ) : + IsRungeDomain (polydisc (0 : Fin n → ℂ) r) := + (isCompleteReinhardt_polydisc r).isRungeDomain (isOpen_polydisc 0 r) + +/-- Balls centered at the origin are Runge domains. -/ +theorem isRungeDomain_ball (r : ℝ) : IsRungeDomain (ball (0 : Fin n → ℂ) r) := by + refine IsCompleteReinhardt.isRungeDomain isOpen_ball fun z hz w hw => ?_ + rw [mem_ball_zero_iff] at hz ⊢ + refine lt_of_le_of_lt ?_ hz + rw [pi_norm_le_iff_of_nonneg (norm_nonneg z)] + exact fun i => (hw i).trans (norm_le_pi_norm z i) + +end Reinhardt + +section Circular + +/-- The restriction of a continuous multilinear map on `ℂⁿ` to the diagonal is a polynomial. -/ +theorem exists_mvPolynomial_eval_eq_multilinear_diagonal {k : ℕ} + (m : ContinuousMultilinearMap ℂ (fun _ : Fin k => (Fin n → ℂ)) ℂ) : + ∃ P : MvPolynomial (Fin n) ℂ, ∀ z, MvPolynomial.eval z P = m (fun _ => z) := by + refine ⟨∑ r : Fin k → Fin n, MvPolynomial.C (m fun j => Pi.single (r j) (1 : ℂ)) * + ∏ j, MvPolynomial.X (r j), fun z => ?_⟩ + have hz : (fun _ : Fin k => z) = fun _ => ∑ i : Fin n, z i • Pi.single i (1 : ℂ) := by + funext _ j + simp [Finset.sum_apply, Pi.single_apply] + rw [hz, ContinuousMultilinearMap.map_sum] + simp only [map_sum, map_mul, MvPolynomial.eval_C, map_prod, MvPolynomial.eval_X] + refine Finset.sum_congr rfl fun r _ => ?_ + rw [ContinuousMultilinearMap.map_smul_univ, smul_eq_mul, mul_comm] + +/-- Homogeneous terms of power series on `ℂⁿ` are polynomials. -/ +theorem exists_mvPolynomial_eval_eq_homogeneousTerm + (p : FormalMultilinearSeries ℂ (Fin n → ℂ) ℂ) (k : ℕ) : + ∃ P : MvPolynomial (Fin n) ℂ, ∀ z, MvPolynomial.eval z P = homogeneousTerm p k z := by + obtain ⟨P, hP⟩ := exists_mvPolynomial_eval_eq_multilinear_diagonal (p k) + exact ⟨P, fun z => by rw [hP, homogeneousTerm_apply]⟩ + +/-- **Circular connected open sets containing the origin are Runge domains**: holomorphic +functions are locally uniform sums of their homogeneous expansions, whose terms are +polynomials. -/ +theorem IsCircular.isRungeDomain {U : Set (Fin n → ℂ)} (ho : IsOpen U) (hc : IsPreconnected U) + (hrot : IsCircular U) (hzero : (0 : Fin n → ℂ) ∈ U) : IsRungeDomain U := by + intro f hf K hK hKU ε hε + obtain ⟨p, hp⟩ := hf 0 hzero + have hsum := + (IsCircular.hasSumLocallyUniformlyOn_homogeneousTerm_balancedHull ho hc hrot hzero hf hp).1 + rw [hasSumLocallyUniformlyOn_iff_tendstoLocallyUniformlyOn] at hsum + have hu := (tendstoLocallyUniformlyOn_iff_tendstoUniformlyOn_of_compact hK).mp (hsum.mono hKU) + rw [Metric.tendstoUniformlyOn_iff] at hu + obtain ⟨t, ht⟩ := (hu ε hε).exists + choose Q hQ using exists_mvPolynomial_eval_eq_homogeneousTerm p + refine ⟨∑ k ∈ t, Q k, fun z hz => ?_⟩ + have := ht z hz + rw [dist_eq_norm] at this + simpa only [map_sum, hQ] using this + +end Circular + +section Transport + +/-- The polynomial map with components `G i`. -/ +@[expose] def mvPolynomialMap (G : Fin n → MvPolynomial (Fin n) ℂ) (z : Fin n → ℂ) : Fin n → ℂ := + fun i => MvPolynomial.eval z (G i) + +/-- Polynomial maps are continuous. -/ +theorem continuous_mvPolynomialMap (G : Fin n → MvPolynomial (Fin n) ℂ) : + Continuous (mvPolynomialMap G) := + continuous_pi fun i => (G i).continuous_eval + +/-- Substitution of a polynomial map into a polynomial. -/ +theorem eval_bind₁_mvPolynomialMap (G : Fin n → MvPolynomial (Fin n) ℂ) + (P : MvPolynomial (Fin n) ℂ) (z : Fin n → ℂ) : + MvPolynomial.eval z (MvPolynomial.bind₁ G P) = MvPolynomial.eval (mvPolynomialMap G z) P := by + simp only [MvPolynomial.eval, MvPolynomial.eval₂Hom_bind₁] + rfl + +/-- **Transport of Runge domains.** If `U` is a Runge domain, `Φ` is holomorphic on `U` with +values in `U'`, and `Ψ` is a polynomial map from `U'` into `U` with `Φ ∘ Ψ = id` on `U'`, then +`U'` is a Runge domain. -/ +theorem IsRungeDomain.transport {U U' : Set (Fin n → ℂ)} (hU : IsRungeDomain U) + {Φ : (Fin n → ℂ) → (Fin n → ℂ)} (hΦ : AnalyticOnNhd ℂ Φ U) (hΦU : MapsTo Φ U U') + (G : Fin n → MvPolynomial (Fin n) ℂ) (hGU : MapsTo (mvPolynomialMap G) U' U) + (hinv : ∀ z ∈ U', Φ (mvPolynomialMap G z) = z) : IsRungeDomain U' := by + intro f hf K hK hKU ε hε + have hfΦ : AnalyticOnNhd ℂ (f ∘ Φ) U := hf.comp hΦ hΦU + have hK' : IsCompact (mvPolynomialMap G '' K) := hK.image (continuous_mvPolynomialMap G) + obtain ⟨P, hP⟩ := hU (f ∘ Φ) hfΦ _ hK' (image_subset_iff.mpr fun z hz => hGU (hKU hz)) ε hε + refine ⟨MvPolynomial.bind₁ G P, fun z hz => ?_⟩ + have := hP (mvPolynomialMap G z) (mem_image_of_mem _ hz) + rw [eval_bind₁_mvPolynomialMap] + simpa [comp_apply, hinv z (hKU hz)] using this + +/-- Runge domains are transported by polynomial automorphisms with polynomial inverses. -/ +theorem IsRungeDomain.image_mvPolynomialMap {U : Set (Fin n → ℂ)} (hU : IsRungeDomain U) + (F G : Fin n → MvPolynomial (Fin n) ℂ) + (hFG : ∀ z, mvPolynomialMap F (mvPolynomialMap G z) = z) + (hGF : ∀ z, mvPolynomialMap G (mvPolynomialMap F z) = z) : + IsRungeDomain (mvPolynomialMap F '' U) := by + refine hU.transport (Φ := mvPolynomialMap F) ?_ (mapsTo_image _ _) G ?_ fun z _ => hFG z + · exact fun z _ => by + apply analyticAt_pi_iff.mpr + intro i + exact AnalyticOnNhd.eval_mvPolynomial (F i) z (mem_univ z) + · rintro _ ⟨z, hz, rfl⟩ + rw [hGF] + exact hz + +/-- Translates of Runge domains are Runge domains. -/ +theorem IsRungeDomain.translate {U : Set (Fin n → ℂ)} (hU : IsRungeDomain U) (a : Fin n → ℂ) : + IsRungeDomain ((fun z => z + a) '' U) := by + have hF : (fun z : Fin n → ℂ => z + a) = + mvPolynomialMap (fun i => MvPolynomial.X i + MvPolynomial.C (a i)) := by + funext z i + simp [mvPolynomialMap] + rw [hF] + refine hU.image_mvPolynomialMap _ (fun i => MvPolynomial.X i - MvPolynomial.C (a i)) ?_ ?_ <;> + · intro z + funext i + simp [mvPolynomialMap] + +end Transport + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean new file mode 100644 index 0000000000..d924f9321c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean @@ -0,0 +1,273 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension + +/-! +# Separate analyticity + +Hartogs' theorem asserts joint analyticity from analyticity of all coordinate slices, without +continuity or local boundedness assumptions. The versions with those extra hypotheses are proved +in `Osgood` and `LocallyBounded`. + +The proof is by induction on the number of coordinates. One coordinate is split off as a fiber +variable. Baire's theorem and the locally bounded Osgood theorem give joint analyticity on a +thin cylinder whose fiber disc is close to the given point. Hartogs' fiber extension lemma, +which rests on Hartogs' growth lemma for roots of the fiber Taylor coefficients, then gives a +local bound at the given point. The locally bounded Osgood theorem completes the induction step. + +References: [Boas][Boas2013] (2013), Section 2.4; [Hörmander][Hormander1973] (1973), Theorem +2.2.8; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 1.5.1. + +## Main definitions + +* `optionSplit`: Splitting off the `none` coordinate of a finite coordinate space as the fiber + variable. + +## Main results + +* `analyticOnNhd_of_separately_analytic`: **Hartogs' separate-holomorphy theorem.** On an open + finite complex coordinate domain, analyticity of every coordinate slice implies joint analyticity, + with no continuity or local boundedness hypothesis. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Function Metric Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +section Split + +variable (κ : Type*) [Fintype κ] [DecidableEq κ] + +/-- Splitting off the `none` coordinate of a finite coordinate space as the fiber variable. The +remaining coordinates form the base. -/ +@[expose] def optionSplit : (Option κ → ℂ) ≃L[ℂ] (κ → ℂ) × ℂ := + ((LinearEquiv.piOptionEquivProd ℂ (M := fun _ : Option κ => ℂ)).trans + (LinearEquiv.prodComm ℂ ℂ (κ → ℂ))).toContinuousLinearEquiv + +variable {κ} + +omit [DecidableEq κ] in +/-- The splitting map records the base coordinates and the fiber coordinate. -/ +theorem optionSplit_apply (z : Option κ → ℂ) : + optionSplit κ z = (fun i => z (some i), z none) := rfl + +omit [DecidableEq κ] in +/-- The inverse splitting map reassembles a point from base and fiber coordinates. -/ +theorem optionSplit_symm_apply (z' : κ → ℂ) (w : ℂ) : + (optionSplit κ).symm (z', w) = fun o => o.elim w z' := by + rw [ContinuousLinearEquiv.symm_apply_eq] + rfl + +/-- Updating the missing coordinate of a split point changes only the fiber. -/ +theorem optionSplit_symm_update_none (z' : κ → ℂ) (w v : ℂ) : + update ((optionSplit κ).symm (z', w)) none v = (optionSplit κ).symm (z', v) := by + rw [optionSplit_symm_apply, optionSplit_symm_apply] + funext o + cases o <;> simp [update] + +/-- Updating a present coordinate of a split point changes only the corresponding base +coordinate. -/ +theorem optionSplit_symm_update_some (z' : κ → ℂ) (w v : ℂ) (i : κ) : + update ((optionSplit κ).symm (z', w)) (some i) v = + (optionSplit κ).symm (update z' i v, w) := by + rw [optionSplit_symm_apply, optionSplit_symm_apply] + funext o + cases o with + | none => simp + | some j => by_cases hji : j = i <;> simp [hji, update] + +omit [DecidableEq κ] in +/-- Closed balls in the product coordinates are products of closed balls. -/ +theorem optionSplit_symm_mem_closedBall {c : Option κ → ℂ} {R : ℝ} (hR : 0 ≤ R) + (z' : κ → ℂ) (w : ℂ) : + (optionSplit κ).symm (z', w) ∈ closedBall c R ↔ + z' ∈ closedBall ((optionSplit κ) c).1 R ∧ w ∈ closedBall ((optionSplit κ) c).2 R := by + have hnone : (optionSplit κ).symm (z', w) none = w := by rw [optionSplit_symm_apply]; rfl + have hsome (i : κ) : (optionSplit κ).symm (z', w) (some i) = z' i := by + rw [optionSplit_symm_apply]; rfl + rw [mem_closedBall, dist_pi_le_iff hR, Option.forall, mem_closedBall, mem_closedBall, + dist_pi_le_iff hR, hnone] + simp only [hsome, optionSplit_apply] + exact and_comm + +end Split + +/-- The induction step of Hartogs' theorem: one further coordinate. The hypothesis is Hartogs' +theorem for the coordinate type `κ`. -/ +theorem analyticOnNhd_of_separately_analytic_option {κ : Type*} [Fintype κ] [DecidableEq κ] + (ih : ∀ {U : Set (κ → ℂ)} {g : (κ → ℂ) → F}, IsOpen U → + (∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => g (update z i w)) (z i)) → AnalyticOnNhd ℂ g U) + {U : Set (Option κ → ℂ)} {f : (Option κ → ℂ) → F} (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + set L := optionSplit κ with hL + -- analyticity of the base slices, by the induction hypothesis + have hslice_base (w : ℂ) : + AnalyticOnNhd ℂ (fun z' => f (L.symm (z', w))) {z' | L.symm (z', w) ∈ U} := by + apply ih (hU.preimage (by fun_prop)) + intro z' hz' i + have h := hf _ hz' (some i) + dsimp only at h + have : L.symm (z', w) (some i) = z' i := by rw [optionSplit_symm_apply]; rfl + rw [this] at h + convert h using 2 + rw [optionSplit_symm_update_some] + -- analyticity of the fiber slices + have hslice_fiber (z' : κ → ℂ) : + AnalyticOnNhd ℂ (fun w => f (L.symm (z', w))) {w | L.symm (z', w) ∈ U} := by + intro w hw + have h := hf _ hw none + have : L.symm (z', w) none = w := by rw [optionSplit_symm_apply]; rfl + rw [this] at h + convert h using 2 + rw [optionSplit_symm_update_none] + -- the decidability instance of the coordinate type is adjusted by `convert` + refine analyticOnNhd_of_separately_analytic_locally_bounded hU + (fun z hz i => by convert hf z hz i) ?_ + intro c hc + obtain ⟨R, hR, hRU⟩ := nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds hc) + set z₀ : κ → ℂ := (L c).1 with hz₀ + set w₀ : ℂ := (L c).2 with hw₀ + have hmem (z' : κ → ℂ) (w : ℂ) : + L.symm (z', w) ∈ closedBall c R ↔ z' ∈ closedBall z₀ R ∧ w ∈ closedBall w₀ R := by + simpa [hz₀, hw₀] using optionSplit_symm_mem_closedBall hR.le z' w + -- Baire: a bounded cylinder over the whole closed base ball + have hR2 : 0 < R / 2 := by positivity + obtain ⟨W, hWo, hWne, hWsub, M₁, hM₁⟩ := exists_open_bounded_cylinder_of_separately_continuous + (X := ℂ) (Y := κ → ℂ) (f := fun w z' => f (L.symm (z', w))) isOpen_ball + (nonempty_ball.mpr hR2) (isCompact_closedBall z₀ R) + (fun z' hz' => (hslice_fiber z').continuousOn.mono fun w hw => hRU ((hmem z' w).mpr + ⟨hz', ball_subset_closedBall (ball_subset_ball (half_le_self hR.le) hw)⟩)) + (fun w hw => (hslice_base w).continuousOn.mono fun z' hz' => hRU ((hmem z' w).mpr + ⟨hz', ball_subset_closedBall (ball_subset_ball (half_le_self hR.le) hw)⟩)) + obtain ⟨b, hb⟩ := hWne + obtain ⟨ε₁, hε₁, hbW⟩ := nhds_basis_closedBall.mem_iff.mp (hWo.mem_nhds hb) + have hbw₀ : dist b w₀ < R / 2 := mem_ball.mp (hWsub hb) + -- Osgood: joint analyticity on the bounded cylinder + set Ω := L ⁻¹' (ball z₀ R ×ˢ W) with hΩ + have hΩo : IsOpen Ω := (isOpen_ball.prod hWo).preimage L.continuous + have hΩU : Ω ⊆ U := by + intro z hz + have := (hmem (L z).1 (L z).2).mpr ⟨ball_subset_closedBall hz.1, + ball_subset_closedBall (ball_subset_ball (half_le_self hR.le) (hWsub hz.2))⟩ + rw [Prod.mk.eta, L.symm_apply_apply] at this + exact hRU this + have hfΩ : AnalyticOnNhd ℂ f Ω := by + refine analyticOnNhd_of_separately_analytic_locally_bounded hΩo + (fun z hz i => by convert hf z (hΩU hz) i) ?_ + intro z hz + refine ⟨M₁, Filter.mem_of_superset (hΩo.mem_nhds hz) fun y hy => ?_⟩ + have := hM₁ (L y).2 hy.2 (L y).1 (ball_subset_closedBall hy.1) + rwa [Prod.mk.eta, L.symm_apply_apply] at this + -- Hartogs' fiber extension lemma in product coordinates + have hg1 : AnalyticOnNhd ℂ (f ∘ L.symm) (ball z₀ R ×ˢ ball b ε₁) := by + intro q hq + have hq' : L.symm q ∈ Ω := by + show L (L.symm q) ∈ ball z₀ R ×ˢ W + rw [L.apply_symm_apply] + exact ⟨hq.1, hbW (ball_subset_closedBall hq.2)⟩ + exact (hfΩ _ hq').comp_of_eq (L.symm.analyticAt q) rfl + have hg2 : ∀ z' ∈ ball z₀ R, + AnalyticOnNhd ℂ (fun w => (f ∘ L.symm) (z', w)) (ball b (R - dist b w₀)) := by + intro z' hz' + apply (hslice_fiber z').mono + intro w hw + apply hRU + rw [hmem] + refine ⟨ball_subset_closedBall hz', ?_⟩ + rw [mem_closedBall] + have := mem_ball.mp hw + calc dist w w₀ ≤ dist w b + dist b w₀ := dist_triangle _ _ _ + _ ≤ R := by linarith + have hw₀ : w₀ ∈ ball b (R - dist b w₀) := by + rw [mem_ball, dist_comm] + linarith + obtain ⟨M, hM⟩ := exists_eventually_norm_le_of_fiber_analytic isOpen_ball hε₁ hg1 hg2 + (mem_ball_self hR) hw₀ + refine ⟨M, ?_⟩ + have := (L.continuous.tendsto c).eventually hM + simpa only [Function.comp_def, L.symm_apply_apply] using this + +omit [CompleteSpace F] in +/-- Hartogs' theorem transports along a bijection of coordinate types. -/ +theorem analyticOnNhd_of_separately_analytic_of_equiv {α β : Type*} + [Fintype α] [DecidableEq α] [Fintype β] [DecidableEq β] (e : α ≃ β) + (hα : ∀ {U : Set (α → ℂ)} {g : (α → ℂ) → F}, IsOpen U → + (∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => g (update z i w)) (z i)) → AnalyticOnNhd ℂ g U) + {U : Set (β → ℂ)} {f : (β → ℂ) → F} (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + let L : (α → ℂ) ≃L[ℂ] (β → ℂ) := ContinuousLinearEquiv.piCongrLeft ℂ (fun _ : β => ℂ) e + have hL_apply (z : α → ℂ) (j : α) : L z (e j) = z j := + Equiv.piCongrLeft_apply_apply (fun _ : β => ℂ) e z j + have hL_update (z : α → ℂ) (j : α) (w : ℂ) : L (update z j w) = update (L z) (e j) w := by + funext i + obtain ⟨k, rfl⟩ := e.surjective i + by_cases hkj : k = j + · subst k + simp [hL_apply] + · have hek : e k ≠ e j := fun he => hkj (e.injective he) + simp [hkj, hek, hL_apply] + have hg : AnalyticOnNhd ℂ (f ∘ L) (L ⁻¹' U) := by + apply hα (hU.preimage L.continuous) + intro z hz j + have h := hf (L z) hz (e j) + rw [← hL_apply z j] + convert h using 2 + simp only [Function.comp_apply, hL_update] + intro z hz + have hzV : L.symm z ∈ L ⁻¹' U := by + show L (L.symm z) ∈ U + simpa + have := (hg _ hzV).comp_of_eq (L.symm.analyticAt z) rfl + simpa only [Function.comp_def, L.apply_symm_apply] using this + +/-- **Hartogs' separate-holomorphy theorem.** On an open finite complex coordinate domain, +analyticity of every coordinate slice implies joint analyticity, with no continuity or local +boundedness hypothesis. Empty and singleton coordinate types are included. -/ +theorem analyticOnNhd_of_separately_analytic + {ι : Type*} [Fintype ι] [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + suffices H : ∀ [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → F}, IsOpen U → + (∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) → AnalyticOnNhd ℂ f U from + H hU hf + refine Fintype.induction_empty_option + (P := fun ι _ => ∀ [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → F}, IsOpen U → + (∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) → AnalyticOnNhd ℂ f U) + ?_ ?_ ?_ ι + · intro α β _ e hα _ U f hU hf + classical + let _ : Fintype α := Fintype.ofEquiv β e.symm + exact analyticOnNhd_of_separately_analytic_of_equiv e (fun hU hf => hα hU hf) hU hf + · intro _ U f hU hf + exact analyticOnNhd_of_separately_analytic_locally_bounded hU hf fun c _ => + ⟨‖f c‖, .of_forall fun z => by rw [Subsingleton.elim z c]⟩ + · intro α _ ih _ U f hU hf + classical + exact analyticOnNhd_of_separately_analytic_option (fun hU hf => ih hU hf) hU + (fun z hz i => by convert hf z hz i) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean new file mode 100644 index 0000000000..e61c7a13d4 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Baire.Lemmas +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded + +/-! +# The Baire step in Hartogs' separate-analyticity theorem + +A separately continuous function on a product with a compact second factor is uniformly bounded +on some open cylinder. For separately analytic functions of two complex variables, locally +bounded Osgood then gives joint analyticity on that cylinder, retaining the entire interior of +the second factor. + +This is the initial cylinder in the proof of Hartogs' theorem in [Boas][Boas2013] (2013), +Section 2.4. No joint continuity or boundedness is assumed. + +## Main results + +`exists_open_bounded_cylinder_of_separately_continuous` produces an open cylinder of uniform +boundedness. `exists_analytic_cylinder_of_separately_analytic` is joint analyticity on that +cylinder for separately analytic functions of two variables. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +-/ + +public section + +open Filter Function Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +/-- Baire's theorem gives a uniform bound on an open cylinder from separate continuity and +compactness of the second factor. The compact set may be empty. -/ +theorem exists_open_bounded_cylinder_of_separately_continuous + {X Y F : Type*} [TopologicalSpace X] [BaireSpace X] [TopologicalSpace Y] + [NormedAddCommGroup F] {U : Set X} {K : Set Y} {f : X → Y → F} + (hU : IsOpen U) (hne : U.Nonempty) (hK : IsCompact K) + (hx : ∀ y ∈ K, ContinuousOn (fun x => f x y) U) + (hy : ∀ x ∈ U, ContinuousOn (f x) K) : + ∃ V : Set X, IsOpen V ∧ V.Nonempty ∧ V ⊆ U ∧ + ∃ M : ℝ, ∀ x ∈ V, ∀ y ∈ K, ‖f x y‖ ≤ M := by + let : BaireSpace U := hU.baireSpace + let : Nonempty U := hne.to_subtype + let S : ℕ → Set U := fun n => {x | ∀ y ∈ K, ‖f x y‖ ≤ n} + have hclosed (n : ℕ) : IsClosed (S n) := by + simp only [S, ofPred_forall] + exact isClosed_iInter fun y => isClosed_iInter fun hy => + isClosed_le ((continuousOn_iff_continuous_domRestrict.mp (hx y hy)).norm) continuous_const + have hcover : ⋃ n, S n = univ := by + apply eq_univ_of_forall + intro x + obtain ⟨M, hM⟩ := hK.bddAbove_image (hy x x.property).norm + obtain ⟨n, hn⟩ := exists_nat_ge M + exact mem_iUnion.mpr ⟨n, fun y hy => (hM (mem_image_of_mem _ hy)).trans hn⟩ + obtain ⟨n, hn⟩ := nonempty_interior_of_iUnion_of_closed hclosed hcover + refine ⟨Subtype.val '' interior (S n), + hU.isOpenMap_subtype_val _ isOpen_interior, hn.image _, ?_, n, ?_⟩ + · rintro _ ⟨x, _, rfl⟩ + exact x.property + · rintro _ ⟨x, hx, rfl⟩ y hy + exact interior_subset hx y hy + +/-- A separately analytic function on a two-variable cylinder is jointly analytic on a smaller +nonempty base times the entire open fiber disc. Only the base shrinks. -/ +theorem exists_analytic_cylinder_of_separately_analytic + {U : Set ℂ} {c : ℂ} {R : ℝ} {F : Type*} + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {f : (Fin 2 → ℂ) → F} (hU : IsOpen U) (hne : U.Nonempty) + (hf : ∀ z : Fin 2 → ℂ, z 0 ∈ U → z 1 ∈ closedBall c R → + ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + ∃ V : Set ℂ, IsOpen V ∧ V.Nonempty ∧ V ⊆ U ∧ + AnalyticOnNhd ℂ f {z | z 0 ∈ V ∧ z 1 ∈ ball c R} := by + have hx (y : ℂ) (hy : y ∈ closedBall c R) : + ContinuousOn (fun x => f ![x, y]) U := by + intro x hx + have h := (hf ![x, y] hx hy 0).continuousAt + simpa [show (fun w => update ![x, y] 0 w) = (fun w => ![w, y]) by + funext w i; fin_cases i <;> simp] using h.continuousWithinAt (s := U) + have hy (x : ℂ) (hx : x ∈ U) : + ContinuousOn (fun y => f ![x, y]) (closedBall c R) := by + intro y hy + have h := (hf ![x, y] hx hy 1).continuousAt + simpa [show (fun w => update ![x, y] 1 w) = (fun w => ![x, w]) by + funext w i; fin_cases i <;> simp] using + h.continuousWithinAt (s := closedBall c R) + obtain ⟨V, hV, hneV, hVU, M, hM⟩ := + exists_open_bounded_cylinder_of_separately_continuous hU hne + (isCompact_closedBall c R) hx hy + have hopen : IsOpen {z : Fin 2 → ℂ | z 0 ∈ V ∧ z 1 ∈ ball c R} := by + change IsOpen ((fun z : Fin 2 → ℂ => z 0) ⁻¹' V ∩ + (fun z : Fin 2 → ℂ => z 1) ⁻¹' ball c R) + exact (hV.preimage (continuous_apply 0)).inter + (isOpen_ball.preimage (continuous_apply 1)) + refine ⟨V, hV, hneV, hVU, + analyticOnNhd_of_separately_analytic_locally_bounded hopen + (fun z hz i => by + simpa +unfoldPartialApp only [update] using + hf z (hVU hz.1) (ball_subset_closedBall hz.2) i) ?_⟩ + intro z hz + refine ⟨M, Filter.mem_of_superset (hopen.mem_nhds hz) ?_⟩ + intro w hw + change ‖f w‖ ≤ M + have he : ![w 0, w 1] = w := by ext i; fin_cases i <;> rfl + simpa only [he] using hM (w 0) hw.1 (w 1) (ball_subset_closedBall hw.2) + +/-- A separately analytic function of two complex variables has a point of joint analyticity in +every nonempty open part of its domain. -/ +theorem exists_analyticAt_of_separately_analytic_fin_two + {U : Set (Fin 2 → ℂ)} {F : Type*} + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {f : (Fin 2 → ℂ) → F} (hU : IsOpen U) (hne : U.Nonempty) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + ∃ z ∈ U, AnalyticAt ℂ f z := by + obtain ⟨a, ha⟩ := hne + obtain ⟨R, hR, hRU⟩ := nhds_basis_closedBall.mem_iff.mp (hU.mem_nhds ha) + have hprod {z : Fin 2 → ℂ} (h0 : z 0 ∈ ball (a 0) R) + (h1 : z 1 ∈ closedBall (a 1) R) : z ∈ U := by + apply hRU + rw [mem_closedBall, dist_pi_le_iff hR.le] + intro i + fin_cases i + · exact (mem_ball.mp h0).le + · exact h1 + obtain ⟨V, hV, ⟨x, hx⟩, hVB, hfa⟩ := exists_analytic_cylinder_of_separately_analytic + isOpen_ball (nonempty_ball.mpr hR) (fun z h0 h1 => hf z (hprod h0 h1)) + have hz : (![x, a 1] : Fin 2 → ℂ) ∈ {z | z 0 ∈ V ∧ z 1 ∈ ball (a 1) R} := + ⟨hx, mem_ball_self hR⟩ + exact ⟨![x, a 1], hprod (hVB hx) (mem_closedBall_self hR.le), hfa _ hz⟩ + +/-- The locus of joint analyticity of a separately analytic two-variable function is a dense open +subset of its open domain. -/ +theorem dense_isOpen_analyticAt_of_separately_analytic_fin_two + {U : Set (Fin 2 → ℂ)} {F : Type*} + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {f : (Fin 2 → ℂ) → F} (hU : IsOpen U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + Dense {z : U | AnalyticAt ℂ f z} ∧ IsOpen {z : U | AnalyticAt ℂ f z} := by + refine ⟨dense_iff_inter_open.mpr ?_, + (isOpen_analyticAt ℂ f).preimage continuous_subtype_val⟩ + intro V hV hne + have hVU : Subtype.val '' V ⊆ U := by rintro _ ⟨z, _, rfl⟩; exact z.property + obtain ⟨z, ⟨w, hw, rfl⟩, ha⟩ := exists_analyticAt_of_separately_analytic_fin_two + (hU.isOpenMap_subtype_val V hV) (hne.image _) (fun z hz => hf z (hVU hz)) + exact ⟨w, hw, ha⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean new file mode 100644 index 0000000000..90b9f95833 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean @@ -0,0 +1,307 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma + +/-! +# Hartogs' fiber extension lemma + +A function of a base variable and one fiber variable, jointly analytic on a thin cylinder and +analytic on a larger disc in each fiber, is locally bounded on the larger cylinder. The fiber +Taylor coefficients are analytic in the base variable by Cauchy's formula on a small circle. +Cauchy's estimates on the large discs give a pointwise eventual bound on their roots, and +Hartogs' lemma makes this bound uniform near each base point, so the fiber Taylor series is +dominated by a geometric series near every point of the larger cylinder. + +This is the continuation step in the proof of Hartogs' separate-analyticity theorem. Reference: +[Hörmander][Hormander1973] (1973), proof of Theorem 2.2.8; [Boas][Boas2013] (2013), Section 2.4. + +## Main results + +`fiberCoeff` is the Taylor coefficient of a fiber slice. `analyticOnNhd_fiberCoeff` is its +holomorphy in the base. `exists_eventually_norm_le_of_fiber_analytic` is local boundedness on +the larger cylinder. `exists_hartogs_fiber_radii` chooses the intermediate radii for the +geometric majorant. + +## References + +* [H. P. Boas, *Lecture Notes on Several Complex Variables*][Boas2013] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +-/ + +public noncomputable section + +open Complex Filter Function MeasureTheory Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +omit [CompleteSpace F] in +/-- Radii for the geometric majorant in Hartogs' fiber extension: an intermediate circle `σ < ρ` and +a contraction ratio `q < 1`. -/ +theorem exists_hartogs_fiber_radii {b w₁ : ℂ} {R : ℝ} (hdist : dist w₁ b < R) : + ∃ σ ρ ε q : ℝ, dist w₁ b < σ ∧ σ < ρ ∧ ρ < R ∧ 0 < σ ∧ 0 < ρ ∧ 0 < ε ∧ + 0 < q ∧ q < 1 ∧ q = σ * (ρ⁻¹ + ε) := by + obtain ⟨ρ, hρ₁, hρR⟩ := exists_between hdist + have hρ : 0 < ρ := dist_nonneg.trans_lt hρ₁ + set σ : ℝ := (dist w₁ b + ρ) / 2 + have hσ₁ : dist w₁ b < σ := by dsimp [σ]; linarith + have hσρ : σ < ρ := by dsimp [σ]; linarith + have hσ0 : 0 < σ := by + dsimp [σ] + nlinarith [dist_nonneg (x := w₁) (y := b)] + set ε : ℝ := (1 - σ / ρ) / (2 * σ) + have hσρ' : σ / ρ < 1 := (div_lt_one hρ).mpr hσρ + have hε0 : 0 < ε := div_pos (by linarith) (by positivity) + set q : ℝ := σ * (ρ⁻¹ + ε) + have hq_eq : q = (1 + σ / ρ) / 2 := by + dsimp [q, ε]; field_simp; ring + have hq1 : q < 1 := by rw [hq_eq]; linarith + have hq0 : 0 < q := by rw [hq_eq]; positivity + exact ⟨σ, ρ, ε, q, hσ₁, hσρ, hρR, hσ0, hρ, hε0, hq0, hq1, rfl⟩ + +omit [CompleteSpace F] in +/-- Cauchy's estimate for the scalar values of the Cauchy power series coefficients, from a bound on +the closed disc. -/ +theorem norm_cauchyPowerSeries_apply_one_le {g : ℂ → F} {b : ℂ} {ρ M : ℝ} (hρ : 0 < ρ) + (hM : ∀ w ∈ closedBall b ρ, ‖g w‖ ≤ M) (k : ℕ) : + ‖cauchyPowerSeries g b ρ k (fun _ => 1)‖ ≤ M * ρ⁻¹ ^ k := by + have hint : ∫ θ in (0:ℝ)..2 * π, ‖g (circleMap b ρ θ)‖ ≤ M * (2 * π) := by + have := intervalIntegral.norm_integral_le_of_norm_le_const (a := 0) (b := 2 * π) + (f := fun θ => ‖g (circleMap b ρ θ)‖) (C := M) (fun θ _ => by + rw [Real.norm_eq_abs, abs_of_nonneg (norm_nonneg _)] + exact hM _ (circleMap_mem_closedBall b hρ.le θ)) + rw [sub_zero, abs_of_pos Real.two_pi_pos, Real.norm_eq_abs] at this + exact (le_abs_self _).trans this + calc ‖cauchyPowerSeries g b ρ k (fun _ => 1)‖ + ≤ ‖cauchyPowerSeries g b ρ k‖ * ∏ _i : Fin k, ‖(1 : ℂ)‖ := + ContinuousMultilinearMap.le_opNorm _ _ + _ = ‖cauchyPowerSeries g b ρ k‖ := by simp + _ ≤ ((2 * π)⁻¹ * ∫ θ in (0:ℝ)..2 * π, ‖g (circleMap b ρ θ)‖) * |ρ|⁻¹ ^ k := + norm_cauchyPowerSeries_le g b ρ k + _ ≤ M * ρ⁻¹ ^ k := by + rw [abs_of_pos hρ] + apply mul_le_mul_of_nonneg_right _ (by positivity) + calc (2 * π)⁻¹ * ∫ θ in (0:ℝ)..2 * π, ‖g (circleMap b ρ θ)‖ + ≤ (2 * π)⁻¹ * (M * (2 * π)) := by gcongr + _ = M := by field_simp + +/-- The Cauchy power series of a function analytic on a closed disc converges on the open disc, with +the radius given as an extended real number. -/ +theorem hasFPowerSeriesOnBall_cauchyPowerSeries_of_analyticOnNhd {g : ℂ → F} {b : ℂ} + {r : ℝ} (hr : 0 < r) (hg : AnalyticOnNhd ℂ g (closedBall b r)) : + HasFPowerSeriesOnBall g (cauchyPowerSeries g b r) b (ENNReal.ofReal r) := by + have := hg.differentiableOn.hasFPowerSeriesOnBall (R := ⟨r, hr.le⟩) hr + rwa [ENNReal.ofReal_eq_coe_nnreal hr.le] + +/-- Roots of a fixed positive constant tend to one. -/ +theorem tendsto_rpow_inv_natCast_succ {M : ℝ} (hM : 0 < M) : + Tendsto (fun n : ℕ => M ^ ((n + 1 : ℕ) : ℝ)⁻¹) atTop (𝓝 1) := by + have h : Tendsto (fun n : ℕ => Real.log M * ((n + 1 : ℕ) : ℝ)⁻¹) atTop (𝓝 0) := by + have := (tendsto_const_div_atTop_nhds_zero_nat (Real.log M)).comp (tendsto_add_atTop_nat 1) + simpa [Function.comp_def, div_eq_mul_inv] using this + simpa [Function.comp_def, Real.rpow_def_of_pos hM] using + Real.tendsto_exp_nhds_zero_nhds_one.comp h + +/-- A root of an exponential-type bound is bounded by a root of the constant times the reciprocal +radius. -/ +theorem rpow_inv_succ_le_of_le_mul_pow {x M ρ : ℝ} (hx : 0 ≤ x) (hM : 0 ≤ M) (hρ : 0 < ρ) + (n : ℕ) (h : x ≤ M * ρ⁻¹ ^ (n + 1)) : + x ^ ((n + 1 : ℕ) : ℝ)⁻¹ ≤ M ^ ((n + 1 : ℕ) : ℝ)⁻¹ * ρ⁻¹ := by + calc x ^ ((n + 1 : ℕ) : ℝ)⁻¹ ≤ (M * ρ⁻¹ ^ (n + 1)) ^ ((n + 1 : ℕ) : ℝ)⁻¹ := + Real.rpow_le_rpow hx h (by positivity) + _ = M ^ ((n + 1 : ℕ) : ℝ)⁻¹ * ρ⁻¹ := by + rw [Real.mul_rpow hM (by positivity), + Real.pow_rpow_inv_natCast (inv_nonneg.mpr hρ.le) n.succ_ne_zero] + +/-- A sequence with a uniform exponential bound and an eventual geometric bound has a single +geometric majorant. -/ +theorem le_geometric_of_bounds {a : ℕ → ℝ} {M s q : ℝ} {N : ℕ} (hM : 0 ≤ M) (hs : 0 ≤ s) + (hq0 : 0 < q) (hq1 : q ≤ 1) (h1 : ∀ k, a k ≤ M * s ^ k) + (h2 : ∀ k, N + 1 ≤ k → a k ≤ q ^ k) (k : ℕ) : + a k ≤ max 1 (M * max 1 s ^ N / q ^ N) * q ^ k := by + have hqk : 0 ≤ q ^ k := pow_nonneg hq0.le k + by_cases hk : N + 1 ≤ k + · exact (h2 k hk).trans (le_mul_of_one_le_left hqk (le_max_left _ _)) + · have hkN : k ≤ N := by omega + have hqN : q ^ N ≤ q ^ k := pow_le_pow_of_le_one hq0.le hq1 hkN + have hC₀ : M * s ^ k ≤ M * max 1 s ^ N := + mul_le_mul_of_nonneg_left ((pow_le_pow_left₀ hs (le_max_right 1 s) k).trans + (pow_le_pow_right₀ (le_max_left 1 s) hkN)) hM + have hqN0 : 0 < q ^ N := pow_pos hq0 N + calc a k ≤ M * max 1 s ^ N := (h1 k).trans hC₀ + _ = M * max 1 s ^ N / q ^ N * q ^ N := by field_simp + _ ≤ M * max 1 s ^ N / q ^ N * q ^ k := + mul_le_mul_of_nonneg_left hqN (div_nonneg (by positivity) hqN0.le) + _ ≤ max 1 (M * max 1 s ^ N / q ^ N) * q ^ k := + mul_le_mul_of_nonneg_right (le_max_right _ _) hqk + +/-- Fiber Taylor coefficients of a function of a base variable and a fiber variable, computed by +Cauchy's formula on the circle of radius `r` about `b` in the fiber. -/ +private def fiberCoeff (f : E × ℂ → F) (b : ℂ) (r : ℝ) (k : ℕ) (z : E) : F := + cauchyPowerSeries (fun w => f (z, w)) b r k (fun _ => 1) + +/-- The fiber coefficients are analytic in the base variable wherever the function is jointly +analytic on a cylinder containing the integration circle. -/ +private theorem analyticOnNhd_fiberCoeff {D : Set E} (hD : IsOpen D) {b : ℂ} {r ε₁ : ℝ} + (hr : 0 < r) (hrε : r < ε₁) {f : E × ℂ → F} + (hf : AnalyticOnNhd ℂ f (D ×ˢ ball b ε₁)) (k : ℕ) : + AnalyticOnNhd ℂ (fiberCoeff f b r k) D := by + have hH : AnalyticOnNhd ℂ (fun q : E × ℂ => (1 / (q.2 - b)) ^ k • (q.2 - b)⁻¹ • f q) + {q | q ∈ D ×ˢ ball b ε₁ ∧ q.2 ≠ b} := by + intro q hq + have hsub : AnalyticAt ℂ (fun q : E × ℂ => q.2 - b) q := analyticAt_snd.sub analyticAt_const + have hne : q.2 - b ≠ 0 := sub_ne_zero.mpr hq.2 + exact ((analyticAt_const.div hsub hne).pow k).smul ((hsub.inv hne).smul (hf q hq.1)) + have h := analyticOnNhd_circleIntegral_kernel hD hH hr.le (c := b) (R := r) ?_ + · unfold fiberCoeff + simp_rw [cauchyPowerSeries_apply] + exact analyticOnNhd_const.smul h + · intro z hz t ht + have htb : dist t b = r := mem_sphere.mp ht + refine ⟨⟨hz, ?_⟩, ?_⟩ + · rw [mem_ball, htb]; exact hrε + · intro h + have h' : t = b := h + rw [h', dist_self] at htb + exact hr.ne htb + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] [CompleteSpace F] in +/-- A bound on a closed cylinder bounds all fiber coefficients over its base. -/ +private theorem norm_fiberCoeff_le {f : E × ℂ → F} {b : ℂ} {r M : ℝ} (hr : 0 < r) {z : E} + (hM : ∀ w ∈ closedBall b r, ‖f (z, w)‖ ≤ M) (k : ℕ) : + ‖fiberCoeff f b r k z‖ ≤ M * r⁻¹ ^ k := + norm_cauchyPowerSeries_apply_one_le hr hM k + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- Fiber coefficients are independent of the radius when the fiber function is analytic on both +closed discs. -/ +private theorem fiberCoeff_eq_of_radii {f : E × ℂ → F} {b : ℂ} {r ρ : ℝ} (hr : 0 < r) (hρ : 0 < ρ) + {z : E} (hgr : AnalyticOnNhd ℂ (fun w => f (z, w)) (closedBall b r)) + (hgρ : AnalyticOnNhd ℂ (fun w => f (z, w)) (closedBall b ρ)) (k : ℕ) : + fiberCoeff f b r k z = cauchyPowerSeries (fun w => f (z, w)) b ρ k (fun _ => 1) := by + unfold fiberCoeff + rw [(hasFPowerSeriesOnBall_cauchyPowerSeries_of_analyticOnNhd hr + hgr).hasFPowerSeriesAt.eq_formalMultilinearSeries + (hasFPowerSeriesOnBall_cauchyPowerSeries_of_analyticOnNhd hρ hgρ).hasFPowerSeriesAt] + +variable [MeasureSpace E] [BorelSpace E] [(volume : Measure E).IsAddHaarMeasure] + +/-- **Hartogs' fiber extension lemma.** A function jointly analytic on a thin cylinder over +an open base, whose fiber slices are analytic on a larger disc, is locally bounded on the +larger cylinder. The fiber Taylor series is dominated by a geometric series near each point, +by Hartogs' lemma applied to the roots of the fiber coefficients. -/ +theorem exists_eventually_norm_le_of_fiber_analytic {D : Set E} (hD : IsOpen D) {b : ℂ} + {ε₁ R : ℝ} (hε₁ : 0 < ε₁) {f : E × ℂ → F} (hf : AnalyticOnNhd ℂ f (D ×ˢ ball b ε₁)) + (hfib : ∀ z ∈ D, AnalyticOnNhd ℂ (fun w => f (z, w)) (ball b R)) + {z₁ : E} (hz₁ : z₁ ∈ D) {w₁ : ℂ} (hw₁ : w₁ ∈ ball b R) : + ∃ M : ℝ, ∀ᶠ q in 𝓝 (z₁, w₁), ‖f q‖ ≤ M := by + have hdist : dist w₁ b < R := mem_ball.mp hw₁ + obtain ⟨σ, ρ, ε, q, hσ₁, hσρ, hρR, hσ0, hρ, hε0, hq0, hq1, hq⟩ := + exists_hartogs_fiber_radii hdist + obtain ⟨r₀, hr₀, hr₀D⟩ := nhds_basis_closedBall.mem_iff.mp (hD.mem_nhds hz₁) + set r : ℝ := min r₀ (ε₁ / 2) + have hr0 : 0 < r := lt_min hr₀ (by positivity) + have hrε : r < ε₁ := (min_le_right _ _).trans_lt (by linarith) + have hrD : closedBall z₁ r ⊆ D := + (closedBall_subset_closedBall (min_le_left _ _)).trans hr₀D + have hcyl : closedBall z₁ r ×ˢ closedBall b r ⊆ D ×ˢ ball b ε₁ := + prod_mono hrD (closedBall_subset_ball hrε) + obtain ⟨M₀, hM₀⟩ := ((isCompact_closedBall z₁ r).prod + (isCompact_closedBall b r)).exists_bound_of_continuousOn (hf.continuousOn.mono hcyl) + set M₁ : ℝ := max M₀ 1 + have hM₁1 : 1 ≤ M₁ := le_max_right _ _ + have hM₁0 : 0 < M₁ := by linarith + have hM₁' : ∀ z ∈ closedBall z₁ r, ∀ w ∈ closedBall b r, ‖f (z, w)‖ ≤ M₁ := + fun z hz w hw => (hM₀ (z, w) ⟨hz, hw⟩).trans (le_max_left _ _) + -- slice analyticity on the small and large closed discs + have hgr : ∀ z ∈ D, AnalyticOnNhd ℂ (fun w => f (z, w)) (closedBall b r) := by + intro z hz w hw + exact (hf (z, w) ⟨hz, closedBall_subset_ball hrε hw⟩).comp_of_eq + (analyticAt_const.prod analyticAt_id) rfl + have hgρ : ∀ z ∈ D, AnalyticOnNhd ℂ (fun w => f (z, w)) (closedBall b ρ) := + fun z hz => (hfib z hz).mono (closedBall_subset_ball hρR) + -- the coefficient family and its bounds + have hp0 : ∀ n : ℕ, (0 : ℝ) < ((n + 1 : ℕ) : ℝ)⁻¹ := fun n => by positivity + have hcan : ∀ n : ℕ, AnalyticOnNhd ℂ (fiberCoeff f b r (n + 1)) (closedBall z₁ r) := + fun n => (analyticOnNhd_fiberCoeff hD hr0 hrε hf (n + 1)).mono hrD + have hB : ∀ n : ℕ, ∀ z ∈ closedBall z₁ r, + ‖fiberCoeff f b r (n + 1) z‖ ^ ((n + 1 : ℕ) : ℝ)⁻¹ ≤ M₁ * r⁻¹ := by + intro n z hz + refine (rpow_inv_succ_le_of_le_mul_pow (norm_nonneg _) hM₁0.le hr0 n + (norm_fiberCoeff_le hr0 (hM₁' z hz) (n + 1))).trans ?_ + gcongr + exact Real.rpow_le_self_of_one_le hM₁1 (inv_le_one_of_one_le₀ (by exact_mod_cast n.succ_pos)) + have hlim : ∀ z ∈ closedBall z₁ r, ∀ δ > 0, ∀ᶠ n : ℕ in atTop, + ‖fiberCoeff f b r (n + 1) z‖ ^ ((n + 1 : ℕ) : ℝ)⁻¹ ≤ ρ⁻¹ + δ := by + intro z hz δ hδ + have hzD : z ∈ D := hrD hz + obtain ⟨M₂, hM₂⟩ := (isCompact_closedBall b ρ).exists_bound_of_continuousOn + (hgρ z hzD).continuousOn + have hM₃0 : 0 < max M₂ 1 := lt_of_lt_of_le one_pos (le_max_right _ _) + have hcoef : ∀ n : ℕ, ‖fiberCoeff f b r (n + 1) z‖ ^ ((n + 1 : ℕ) : ℝ)⁻¹ ≤ + (max M₂ 1) ^ ((n + 1 : ℕ) : ℝ)⁻¹ * ρ⁻¹ := by + intro n + apply rpow_inv_succ_le_of_le_mul_pow (norm_nonneg _) hM₃0.le hρ + rw [fiberCoeff_eq_of_radii hr0 hρ (hgr z hzD) (hgρ z hzD)] + exact norm_cauchyPowerSeries_apply_one_le hρ + (fun w hw => (hM₂ w hw).trans (le_max_left _ _)) _ + have ht := ((tendsto_rpow_inv_natCast_succ hM₃0).mul_const ρ⁻¹).eventually + (eventually_le_nhds (show 1 * ρ⁻¹ < ρ⁻¹ + δ by linarith)) + filter_upwards [ht] with n hn using (hcoef n).trans hn + obtain ⟨r', hr'0, hev⟩ := eventually_norm_rpow_lt_on_ball hr0 hp0 hcan hB hlim hε0 + obtain ⟨N, hN⟩ := eventually_atTop.mp hev + have hbig : ∀ k, N + 1 ≤ k → ∀ z ∈ ball z₁ r', + ‖fiberCoeff f b r k z‖ ≤ (ρ⁻¹ + ε) ^ k := by + intro k hk z hz + obtain ⟨n, rfl⟩ : ∃ n, k = n + 1 := ⟨k - 1, by omega⟩ + have := hN n (by omega) z hz + rw [Real.rpow_inv_lt_iff_of_pos (norm_nonneg _) (by positivity) (by positivity), + Real.rpow_natCast] at this + exact this.le + -- the geometric majorant + refine ⟨max 1 (M₁ * max 1 (σ / r) ^ N / q ^ N) * (1 - q)⁻¹, ?_⟩ + have hopen : IsOpen (ball z₁ (min r' r) ×ˢ ball b σ) := isOpen_ball.prod isOpen_ball + have hmem : (z₁, w₁) ∈ ball z₁ (min r' r) ×ˢ ball b σ := + ⟨mem_ball_self (lt_min hr'0 hr0), mem_ball.mpr hσ₁⟩ + filter_upwards [hopen.mem_nhds hmem] + rintro ⟨z, w⟩ ⟨hz, hw⟩ + have hzr' : z ∈ ball z₁ r' := ball_subset_ball (min_le_left _ _) hz + have hzr : z ∈ closedBall z₁ r := ball_subset_closedBall (ball_subset_ball (min_le_right _ _) hz) + have hzD : z ∈ D := hrD hzr + have hwσ : ‖w - b‖ < σ := by rwa [← dist_eq_norm] + have hps := hasFPowerSeriesOnBall_cauchyPowerSeries_of_analyticOnNhd hρ (hgρ z hzD) + have hsum := hps.hasSum (y := w - b) (by + show edist (w - b) 0 < ENNReal.ofReal ρ + rw [edist_lt_ofReal, dist_zero_right] + exact hwσ.trans hσρ) + rw [add_sub_cancel] at hsum + have hterm (k : ℕ) : (cauchyPowerSeries (fun w => f (z, w)) b ρ k fun _ => w - b) = + (w - b) ^ k • fiberCoeff f b r k z := by + rw [fiberCoeff_eq_of_radii hr0 hρ (hgr z hzD) (hgρ z hzD)] + simp + refine hsum.norm_le_of_bounded ((hasSum_geometric_of_lt_one hq0.le hq1).mul_left _) ?_ + apply le_geometric_of_bounds (s := σ / r) hM₁0.le (by positivity) hq0 hq1.le + · intro k + rw [hterm, norm_smul, norm_pow] + calc ‖w - b‖ ^ k * ‖fiberCoeff f b r k z‖ ≤ σ ^ k * (M₁ * r⁻¹ ^ k) := + mul_le_mul (pow_le_pow_left₀ (norm_nonneg _) hwσ.le k) + (norm_fiberCoeff_le hr0 (hM₁' z hzr) k) (norm_nonneg _) (by positivity) + _ = M₁ * (σ / r) ^ k := by rw [div_pow, inv_pow]; ring + · intro k hk + rw [hterm, norm_smul, norm_pow, hq, mul_pow] + exact mul_le_mul (pow_le_pow_left₀ (norm_nonneg _) hwσ.le k) (hbig k hk z hzr') + (norm_nonneg _) (by positivity) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/HartogsLemma.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/HartogsLemma.lean new file mode 100644 index 0000000000..0b59bb09ed --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/HartogsLemma.lean @@ -0,0 +1,143 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.DominatedConvergence +public import Mathlib.MeasureTheory.Measure.Lebesgue.VolumeOfBalls +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue + +/-! +# Hartogs' lemma for powers of holomorphic norms + +Under a common upper bound, pointwise eventual bounds for positive powers of holomorphic norms +become uniform on a neighborhood of each point. The exponents may vary with the sequence, so the +result applies to roots of Taylor coefficients. The domain is a closed ball in a +finite-dimensional complex normed space carrying an additive Haar volume, such as a finite +complex coordinate space. + +The proof combines dominated convergence for the positive excess above the limiting bound with +the ball submean inequality. A ball centered at a nearby point fits inside a fixed ball; +nonnegativity bounds its integral by the fixed integral. + +## Main results + +`eventually_norm_rpow_lt_on_ball` is Hartogs' lemma: a pointwise eventual bound on positive +powers of holomorphic norms becomes uniform on a neighborhood of each point. +`exists_radius_area_bound` produces a nearby ball of controlled volume. +-/ + +public section + +open Complex Filter MeasureTheory Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [MeasureSpace E] [BorelSpace E] [(volume : Measure E).IsAddHaarMeasure] + +omit [NormedSpace ℂ E] [FiniteDimensional ℂ E] in +/-- On a compact set, a uniformly bounded-above sequence of continuous functions with pointwise +eventual upper bound `A` has the corresponding integral upper bound. -/ +theorem eventually_integral_lt_of_pointwise_eventually_le + {K : Set E} {u : ℕ → E → ℝ} {A B ε : ℝ} (hK : IsCompact K) + (hu : ∀ n, ContinuousOn (u n) K) (hB : ∀ n, ∀ z ∈ K, u n z ≤ B) + (hlim : ∀ z ∈ K, ∀ δ > 0, ∀ᶠ n in atTop, u n z ≤ A + δ) (hε : 0 < ε) : + ∀ᶠ n in atTop, ∫ z in K, u n z < volume.real K * A + ε := by + let v := fun n z => max (u n z - A) 0 + have hv (n : ℕ) : ContinuousOn (v n) K := ((hu n).sub continuousOn_const).sup continuousOn_const + have ht (z : E) (hz : z ∈ K) : Tendsto (fun n => v n z) atTop (𝓝 0) := by + apply tendsto_order.mpr + constructor + · intro a ha + exact .of_forall fun n => ha.trans_le (le_max_right _ _) + · intro b hb + filter_upwards [hlim z hz (b / 2) (by positivity)] with n hn + exact max_lt (by linarith) hb + have hdom := tendsto_integral_of_dominated_convergence + (μ := volume.restrict K) (fun _ => max (B - A) 0) + (fun n => ((hv n).integrableOn_compact hK).aestronglyMeasurable) + (integrableOn_const hK.measure_lt_top.ne) + (fun n => (ae_restrict_mem hK.measurableSet).mono fun z hz => by + change |max (u n z - A) 0| ≤ max (B - A) 0 + rw [abs_of_nonneg (le_max_right _ _)] + exact max_le_max (sub_le_sub_right (hB n z hz) A) le_rfl) + ((ae_restrict_mem hK.measurableSet).mono fun z hz => ht z hz) + simp only [integral_zero] at hdom + filter_upwards [hdom.eventually (gt_mem_nhds hε)] with n hn + have hi : (∫ z in K, u n z - A) ≤ ∫ z in K, v n z := + setIntegral_mono_on (((hu n).sub continuousOn_const).integrableOn_compact hK) + ((hv n).integrableOn_compact hK) hK.measurableSet (fun z _ => le_max_left _ _) + rw [integral_sub ((hu n).integrableOn_compact hK) (integrableOn_const hK.measure_lt_top.ne), + integral_const] at hi + simp only [Measure.real, Measure.restrict_apply_univ, smul_eq_mul] at hi + change (∫ z in K, u n z) - volume.real K * A ≤ ∫ z in K, v n z at hi + linarith + +/-- The Haar volume of a closed ball scales with the real dimension. -/ +private theorem real_volume_closedBall (c : E) {R : ℝ} (hR : 0 ≤ R) : + volume.real (closedBall c R) = + R ^ Module.finrank ℝ E * volume.real (ball (0 : E) 1) := + Measure.addHaar_real_closedBall volume c hR + +omit [NormedSpace ℂ E] [FiniteDimensional ℂ E] [MeasureSpace E] [BorelSpace E] + [(volume : Measure E).IsAddHaarMeasure] in +/-- A slightly smaller ball retains enough volume to absorb an arbitrarily small increase in an +average bound. -/ +private theorem exists_radius_area_bound {R A ε v : ℝ} (d : ℕ) (hR : 0 < R) + (hv : 0 < v) (hε : 0 < ε) : + ∃ r ∈ Ioo 0 R, R ^ d * v * (A + ε / 2) < r ^ d * v * (A + ε) := by + have hcont : Continuous (fun r : ℝ => r ^ d * v * (A + ε)) := by fun_prop + have hstrict : R ^ d * v * (A + ε / 2) < R ^ d * v * (A + ε) := by + have hp : 0 < R ^ d * v := mul_pos (pow_pos hR d) hv + nlinarith + have hnhds := (isOpen_lt continuous_const hcont).mem_nhds hstrict + exact nonempty_of_mem (inter_mem (Ioo_mem_nhdsLT hR) (nhdsWithin_le_nhds hnhds)) + +/-- **Hartogs' lemma for holomorphic norms.** A pointwise eventual bound on +positive powers of holomorphic norms, under a common upper bound on a closed +ball, becomes uniform on a neighborhood of its center. The powers may vary. -/ +theorem eventually_norm_rpow_lt_on_ball + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + {f : ℕ → E → F} {p : ℕ → ℝ} {c : E} {R A B ε : ℝ} + (hR : 0 < R) (hp : ∀ n, 0 < p n) + (hf : ∀ n, AnalyticOnNhd ℂ (f n) (closedBall c R)) + (hB : ∀ n, ∀ z ∈ closedBall c R, ‖f n z‖ ^ p n ≤ B) + (hlim : ∀ z ∈ closedBall c R, ∀ δ > 0, + ∀ᶠ n in atTop, ‖f n z‖ ^ p n ≤ A + δ) (hε : 0 < ε) : + ∃ r > 0, ∀ᶠ n in atTop, ∀ z ∈ ball c r, ‖f n z‖ ^ p n < A + ε := by + have hunit : 0 < volume.real (ball (0 : E) 1) := + ENNReal.toReal_pos (measure_ball_pos volume (0 : E) one_pos).ne' measure_ball_lt_top.ne + obtain ⟨s, ⟨hs, hsR⟩, harea⟩ := + exists_radius_area_bound (A := A) (Module.finrank ℝ E) hR hunit hε + have hvol : 0 < volume.real (closedBall c R) := by + rw [real_volume_closedBall c hR.le] + positivity + have hint := eventually_integral_lt_of_pointwise_eventually_le (isCompact_closedBall c R) + (fun n => (hf n).continuousOn.norm.rpow_const (fun _ _ => Or.inr (hp n).le)) hB hlim + (mul_pos hvol (half_pos hε)) + refine ⟨R - s, sub_pos.mpr hsR, ?_⟩ + filter_upwards [hint] with n hn z hz + have hsub : closedBall z s ⊆ closedBall c R := + closedBall_subset_closedBall' (by have := mem_ball.mp hz; linarith) + have hmean := volume_mul_norm_rpow_le_integral_closedBall (E := E) (hp n) ((hf n).mono hsub) + have hmono : (∫ w in closedBall z s, ‖f n w‖ ^ p n) ≤ + ∫ w in closedBall c R, ‖f n w‖ ^ p n := + setIntegral_mono_set + (((hf n).continuousOn.norm.rpow_const (fun _ _ => Or.inr (hp n).le)).integrableOn_compact + (isCompact_closedBall c R)) + (.of_forall fun w => Real.rpow_nonneg (norm_nonneg _) _) hsub.eventuallySubset + rw [real_volume_closedBall z hs.le] at hmean + rw [real_volume_closedBall c hR.le] at hn + have hbound : s ^ Module.finrank ℝ E * volume.real (ball (0 : E) 1) * (‖f n z‖ ^ p n) < + s ^ Module.finrank ℝ E * volume.real (ball (0 : E) 1) * (A + ε) := + (hmean.trans hmono).trans_lt (hn.trans_le (by nlinarith only [harea])) + exact (mul_lt_mul_iff_right₀ + (mul_pos (pow_pos hs _) hunit)).mp hbound + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/MeanValue.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/MeanValue.lean new file mode 100644 index 0000000000..e849583c02 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/MeanValue.lean @@ -0,0 +1,139 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.MeasureTheory.Integral.Prod +public import Mathlib.MeasureTheory.Measure.Haar.InnerProductSpace +public import Mathlib.MeasureTheory.Measure.Lebesgue.Complex +public import Mathlib.MeasureTheory.Measure.Lebesgue.EqHaar +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean + +/-! +# Ball submean estimates for holomorphic norms + +Averaging unit complex rotations converts the circle submean inequality into a volume submean +inequality on closed balls of a finite-dimensional complex normed space carrying an additive +Haar volume. This avoids polar-coordinate integration and applies to all positive powers of +norms, including the roots used in Hartogs' lemma. The one-variable case is the disc inequality; +the case of a finite coordinate space is used for the base variables in Hartogs' +separate-analyticity theorem. + +## Main results + +`volume_mul_norm_rpow_le_integral_closedBall` is the volume submean inequality for positive +powers of holomorphic norms on a closed ball. `integral_closedBall_smul_rotation` averages unit +complex rotations. +-/ + +public section + +open Complex Filter Function MeasureTheory Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [MeasureSpace E] [BorelSpace E] [(volume : Measure E).IsAddHaarMeasure] + +/-- Unit complex rotations preserve the integral of any real function on a closed ball. Rotation +preserves the unit ball, so it has unit determinant and preserves Haar volume. -/ +private theorem integral_closedBall_smul_rotation (u : E → ℝ) (R : ℝ) + {w : ℂ} (hw : ‖w‖ = 1) : + ∫ z in closedBall (0 : E) R, u (w • z) = ∫ z in closedBall (0 : E) R, u z := by + have hw0 : w ≠ 0 := by intro h; simp [h] at hw + let e : E ≃L[ℝ] E := + ((LinearEquiv.smulOfNeZero ℂ E w hw0).restrictScalars ℝ).toContinuousLinearEquiv + have he (z : E) : e z = w • z := rfl + have hpre (s : ℝ) : e ⁻¹' closedBall 0 s = closedBall 0 s := by + ext z + simp only [mem_preimage, mem_closedBall, dist_zero_right, he, norm_smul, hw, one_mul] + have hdet : ENNReal.ofReal |LinearMap.det (e.symm : E →ₗ[ℝ] E)| = 1 := by + have h := Measure.addHaar_preimage_continuousLinearEquiv volume e (closedBall (0 : E) 1) + rw [hpre] at h + exact (ENNReal.mul_left_inj (measure_closedBall_pos volume (0 : E) one_pos).ne' + measure_closedBall_lt_top.ne).mp (by rw [one_mul]; exact h.symm) + have hmp : MeasurePreserving e volume volume := by + refine ⟨e.continuous.measurable, Measure.ext fun s hs => ?_⟩ + rw [Measure.map_apply e.continuous.measurable hs, + Measure.addHaar_preimage_continuousLinearEquiv, hdet, one_mul] + simpa only [hpre, he] using hmp.setIntegral_preimage_emb + e.toHomeomorph.isClosedEmbedding.measurableEmbedding u (closedBall 0 R) + +/-- Averaging rotations turns circle submean inequalities into a ball inequality. Only continuity on +the ball is required of the real-valued function. -/ +theorem volume_mul_le_integral_closedBall_of_circle_submean {u : E → ℝ} {R A : ℝ} + (hu : ContinuousOn u (closedBall 0 R)) + (hmean : ∀ z ∈ closedBall (0 : E) R, + A ≤ Real.circleAverage (fun w => u (w • z)) 0 1) : + volume.real (closedBall (0 : E) R) * A ≤ ∫ z in closedBall (0 : E) R, u z := by + let B := closedBall (0 : E) R + let T := Icc (0 : ℝ) (2 * π) + let H := fun (z : E) (θ : ℝ) => u (circleMap 0 1 θ • z) + have hrot (θ : ℝ) : ‖circleMap 0 1 θ‖ = 1 := by simp + have hmap : MapsTo (fun p : E × ℝ => circleMap 0 1 p.2 • p.1) (B ×ˢ T) B := by + intro z hz + simpa only [B, mem_closedBall, dist_zero_right, norm_smul, hrot, one_mul] using hz.1 + have hcont : ContinuousOn (uncurry H) (B ×ˢ T) := hu.comp (by fun_prop) hmap + have hint : Integrable (uncurry H) ((volume.restrict B).prod (volume.restrict T)) := by + rw [Measure.prod_restrict, ← Measure.volume_eq_prod] + exact hcont.integrableOn_compact ((isCompact_closedBall _ _).prod isCompact_Icc) + have hpoint (z : E) (hz : z ∈ B) : (2 * π) * A ≤ ∫ θ in T, H z θ := by + have h := hmean z hz + rw [Real.circleAverage, intervalIntegral.integral_of_le Real.two_pi_pos.le, + ← integral_Icc_eq_integral_Ioc, smul_eq_mul] at h + exact (le_inv_mul_iff₀ Real.two_pi_pos).mp h + have hbound := setIntegral_mono_on + (integrableOn_const (isCompact_closedBall (0 : E) R).measure_lt_top.ne) + hint.integral_prod_left measurableSet_closedBall hpoint + have hswap := integral_integral_swap hint + have hright : (∫ θ in T, ∫ z in B, H z θ) = (2 * π) * ∫ z in B, u z := by + simp_rw [H, B, integral_closedBall_smul_rotation u R (hrot _)] + simp [T, integral_const, Real.volume_Icc, Measure.real, ENNReal.toReal_ofReal Real.pi_pos.le] + simp only [uncurry_apply_pair] at hbound + rw [integral_const, hswap, hright] at hbound + simp only [Measure.real, Measure.restrict_apply_univ, smul_eq_mul] at hbound + change volume.real B * (2 * π * A) ≤ 2 * π * ∫ z in B, u z at hbound + change volume.real B * A ≤ ∫ z in B, u z + apply (mul_le_mul_iff_right₀ Real.two_pi_pos).mp + nlinarith only [hbound] + +/-- Every positive power of a holomorphic norm satisfies the volume submean inequality on a closed +ball. No completeness of the target is needed. -/ +theorem volume_mul_norm_rpow_le_integral_closedBall + {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + {f : E → F} {c : E} {R p : ℝ} (hp : 0 < p) + (hf : AnalyticOnNhd ℂ f (closedBall c R)) : + volume.real (closedBall c R) * ‖f c‖ ^ p ≤ ∫ z in closedBall c R, ‖f z‖ ^ p := by + have hpre : (fun z : E => c + z) ⁻¹' closedBall c R = closedBall 0 R := by + ext z + simp [mem_closedBall, dist_eq_norm] + have hvol : volume (closedBall (0 : E) R) = volume (closedBall c R) := by + rw [← hpre] + exact measure_preimage_add volume c _ + have htrans : AnalyticOnNhd ℂ (fun z => f (c + z)) (closedBall 0 R) := by + intro z hz + exact (hf _ (by simpa [mem_closedBall, dist_eq_norm] using hz)).comp_of_eq + (analyticAt_const.add analyticAt_id) rfl + have hb := volume_mul_le_integral_closedBall_of_circle_submean + (htrans.continuousOn.norm.rpow_const (fun _ _ => Or.inr hp.le)) (A := ‖f c‖ ^ p) ?_ + · have hm := (measurePreserving_add_left (volume : Measure E) c).setIntegral_preimage_emb + (Homeomorph.addLeft c).isClosedEmbedding.measurableEmbedding + (fun z => ‖f z‖ ^ p) (closedBall c R) + rw [hpre] at hm + simpa only [Measure.real, hvol, hm] using hb + · intro z hz + have hline : AnalyticOnNhd ℂ (fun w : ℂ => f (c + w • z)) (closedBall 0 1) := by + intro w hw + apply (hf (c + w • z) ?_).comp_of_eq + (analyticAt_const.add (analyticAt_id.smul analyticAt_const)) rfl + rw [mem_closedBall, dist_eq_norm, add_sub_cancel_left, norm_smul] + exact (mul_le_mul_of_nonneg_right (mem_closedBall_zero_iff.mp hw) + (norm_nonneg z)).trans (by simpa using hz) + simpa only [zero_smul, add_zero] using norm_rpow_le_circleAverage zero_lt_one hp hline + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Submean.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Submean.lean new file mode 100644 index 0000000000..14463c2e73 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Submean.lean @@ -0,0 +1,155 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.JensenFormula +public import Mathlib.Analysis.Normed.Module.HahnBanach + +/-! +# Submean estimates for positive powers of holomorphic norms + +Jensen's formula and the tangent-line inequality for the exponential give the submean inequality +for every positive real power of a holomorphic norm. In particular, the exponent may be less +than one, as needed for the roots of Taylor coefficients in the proof of Hartogs' +separate-analyticity theorem. + +Hahn–Banach transfers the scalar estimate to arbitrary complex normed targets. + +## Main results + +`norm_rpow_le_circleAverage` is the circle submean inequality for every positive real power of a +holomorphic norm. `log_norm_le_circleAverage` is Jensen's formula for a nonvanishing holomorphic +function. +-/ + +public section + +open Complex Filter MeasureTheory MeromorphicOn Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +/-- Circle averages preserve inequalities outside a discrete exceptional set. -/ +theorem circleAverage_le_of_eventually_le {u v : ℂ → ℝ} {c : ℂ} {R : ℝ} + (hR : R ≠ 0) (hu : CircleIntegrable u c R) (hv : CircleIntegrable v c R) + (h : ∀ᶠ z in codiscreteWithin (sphere c |R|), u z ≤ v z) : + Real.circleAverage u c R ≤ Real.circleAverage v c R := by + simp only [Real.circleAverage, smul_eq_mul] + apply mul_le_mul_of_nonneg_left _ (by positivity) + apply intervalIntegral.integral_mono_ae_restrict Real.two_pi_pos.le hu hv + apply ae_restrict_le_codiscreteWithin measurableSet_Icc + exact codiscreteWithin_mono (by simp) (circleMap_preimage_codiscrete hR h) + +/-- For an analytic scalar function nonzero at the center, Jensen's zero terms are nonnegative, so +the mean of its logarithmic norm bounds the center value. -/ +theorem log_norm_le_circleAverage {f : ℂ → ℂ} {c : ℂ} {R : ℝ} + (hR : 0 < R) (hf : AnalyticOnNhd ℂ f (closedBall c R)) (hc : f c ≠ 0) : + Real.log ‖f c‖ ≤ Real.circleAverage (fun z => Real.log ‖f z‖) c R := by + have hf' : AnalyticOnNhd ℂ f (closedBall c |R|) := by simpa [abs_of_pos hR] using hf + rw [hf'.circleAverage_log_norm hR.ne' hc] + apply le_add_of_nonneg_left + apply finsum_nonneg + intro z + by_cases hz : MeromorphicOn.divisor f (closedBall c |R|) z = 0 + · simp [hz] + have hzmem : z ∈ closedBall c |R| := + (MeromorphicOn.divisor f (closedBall c |R|)).supportWithinDomain hz + have hzc : c ≠ z := by + rintro rfl + apply hz + rw [hf'.divisor_apply hzmem, (hf' c hzmem).analyticOrderAt_eq_zero.mpr hc] + simp + apply mul_nonneg (by exact_mod_cast hf'.divisor_nonneg z) + apply Real.log_nonneg + rw [← div_eq_mul_inv, one_le_div (norm_pos_iff.mpr (sub_ne_zero.mpr hzc))] + simpa [mem_closedBall, dist_eq_norm, norm_sub_rev, abs_of_pos hR] using hzmem + +/-- A positive power lies above the affine tangent expressed in logarithmic coordinates. This form +can be integrated even when the exponent is below one. -/ +private theorem rpow_log_tangent_le {a b : ℝ} (ha : 0 < a) (hb : 0 < b) (p : ℝ) : + a ^ p * (1 + p * (Real.log b - Real.log a)) ≤ b ^ p := by + rw [Real.rpow_def_of_pos ha, Real.rpow_def_of_pos hb] + calc + Real.exp (Real.log a * p) * (1 + p * (Real.log b - Real.log a)) ≤ + Real.exp (Real.log a * p) * Real.exp (p * (Real.log b - Real.log a)) := + mul_le_mul_of_nonneg_left + (by simpa [add_comm] using Real.add_one_le_exp (p * (Real.log b - Real.log a))) + (Real.exp_pos _).le + _ = Real.exp (Real.log b * p) := by rw [← Real.exp_add]; congr 1; ring + +/-- Every positive real power of the norm of a scalar holomorphic function satisfies the circle +submean inequality, including powers less than one. -/ +theorem norm_rpow_le_circleAverage_scalar {f : ℂ → ℂ} {c : ℂ} {R p : ℝ} + (hR : 0 < R) (hp : 0 < p) (hf : AnalyticOnNhd ℂ f (closedBall c R)) : + ‖f c‖ ^ p ≤ Real.circleAverage (fun z => ‖f z‖ ^ p) c R := by + by_cases hc : f c = 0 + · simpa [hc, Real.zero_rpow hp.ne'] using + Real.circleAverage_nonneg_of_nonneg (c := c) (R := R) + (fun z _ => Real.rpow_nonneg (norm_nonneg (f z)) p) + have hn : 0 < ‖f c‖ := norm_pos_iff.mpr hc + have hlog : CircleIntegrable (fun z => Real.log ‖f z‖) c R := by + apply MeromorphicOn.circleIntegrable_log_norm + simpa [abs_of_pos hR] using (hf.mono sphere_subset_closedBall).meromorphicOn + have hpow : CircleIntegrable (fun z => ‖f z‖ ^ p) c R := by + apply ContinuousOn.circleIntegrable hR.le + exact (hf.continuousOn.mono sphere_subset_closedBall).norm.rpow_const + (fun z _ => Or.inr hp.le) + have hne : ∀ᶠ z in codiscreteWithin (sphere c |R|), f z ≠ 0 := by + apply codiscreteWithin_mono (by simpa [abs_of_pos hR] using + (sphere_subset_closedBall : sphere c R ⊆ closedBall c R)) + exact (hf.eqOn_zero_or_eventually_ne_zero_of_preconnected + (convex_closedBall c R).isPreconnected).resolve_left + (fun h => hc (h (mem_closedBall_self hR.le))) + have htan : CircleIntegrable + (fun z => ‖f c‖ ^ p * (1 + p * (Real.log ‖f z‖ - Real.log ‖f c‖))) c R := by + exact ((circleIntegrable_const 1 c R).add + ((hlog.sub (circleIntegrable_const _ c R)).const_smul (a := p))).const_smul + have hbound := circleAverage_le_of_eventually_le hR.ne' htan hpow + (hne.mono fun z hz => rpow_log_tangent_le hn (norm_pos_iff.mpr hz) p) + have hsub : CircleIntegrable (fun z => Real.log ‖f z‖ - Real.log ‖f c‖) c R := + hlog.sub (circleIntegrable_const _ c R) + have hmul : CircleIntegrable (fun z => p • (Real.log ‖f z‖ - Real.log ‖f c‖)) c R := + hsub.const_smul + have hmean : Real.circleAverage + (fun z => ‖f c‖ ^ p * (1 + p * (Real.log ‖f z‖ - Real.log ‖f c‖))) c R = + ‖f c‖ ^ p * (1 + p * + (Real.circleAverage (fun z => Real.log ‖f z‖) c R - Real.log ‖f c‖)) := by + simp only [← smul_eq_mul, Real.circleAverage_fun_smul] + rw [Real.circleAverage_fun_add (circleIntegrable_const 1 c R) hmul, Real.circleAverage_const, + Real.circleAverage_fun_smul, + Real.circleAverage_fun_sub hlog (circleIntegrable_const _ c R), Real.circleAverage_const] + rw [hmean] at hbound + have hlogbound := log_norm_le_circleAverage hR hf hc + refine le_trans ?_ hbound + calc + ‖f c‖ ^ p = ‖f c‖ ^ p * 1 := (mul_one _).symm + _ ≤ _ := mul_le_mul_of_nonneg_left + (by nlinarith) (Real.rpow_nonneg (norm_nonneg _) _) + +/-- The submean inequality for positive powers of a holomorphic norm also holds for complex normed +targets, by applying a norming linear functional at the center. -/ +theorem norm_rpow_le_circleAverage {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + {f : ℂ → F} {c : ℂ} {R p : ℝ} (hR : 0 < R) (hp : 0 < p) + (hf : AnalyticOnNhd ℂ f (closedBall c R)) : + ‖f c‖ ^ p ≤ Real.circleAverage (fun z => ‖f z‖ ^ p) c R := by + obtain ⟨L, hL, hLc⟩ := exists_dual_vector'' ℂ (f c) + have hLf : AnalyticOnNhd ℂ (fun z => L (f z)) (closedBall c R) := + fun z hz => (L.analyticAt (f z)).comp_of_eq (hf z hz) rfl + have hcenter : ‖L (f c)‖ = ‖f c‖ := by simp [hLc] + rw [← hcenter] + refine (norm_rpow_le_circleAverage_scalar hR hp hLf).trans ?_ + apply Real.circleAverage_mono + · exact (hLf.continuousOn.mono sphere_subset_closedBall).norm.rpow_const + (fun z _ => Or.inr hp.le) |>.circleIntegrable hR.le + · exact (hf.continuousOn.mono sphere_subset_closedBall).norm.rpow_const + (fun z _ => Or.inr hp.le) |>.circleIntegrable hR.le + · intro z _ + exact Real.rpow_le_rpow (norm_nonneg _) ((L.le_opNorm (f z)).trans + (by simpa using mul_le_mul_of_nonneg_right hL (norm_nonneg (f z)))) hp.le + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SphericalShell.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SphericalShell.lean new file mode 100644 index 0000000000..e364a59936 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SphericalShell.lean @@ -0,0 +1,109 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.LinearAlgebra.Complex.FiniteDimensional +public import Mathlib.LinearAlgebra.Dimension.Finrank +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension + +/-! +# Punctured polydiscs, spherical shells, and exteriors of balls + +Punctured product polydiscs extend by the proved Hartogs continuity theorem, without boundedness +assumptions. A radial argument proves connectedness of norm shells; spherical shell extension is +then a corollary of the general compact-hole theorem. For Euclidean spheres instantiate the +source with `EuclideanSpace ℂ ι`, not the supremum norm on `ι → ℂ`. References: +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Applications 2.6.2 and 2.8.3. + +## Main results + +* `exists_extension_sphericalShell`: **Spherical-shell extension.** This works for any norm in + finite complex dimension at least two. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public section + +open Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- An isolated puncture in a product polydisc is removable in complex dimension at least two. The +nonempty base index type makes the dimension restriction explicit. -/ +theorem exists_extension_punctured_polydisc {ι : Type*} [Fintype ι] [Nonempty ι] + {r R : ℝ} (hr : 0 < r) (hR : 0 < R) + {f : ((ι → ℂ) × ℂ) → F} + (hf : AnalyticOnNhd ℂ f ((ball 0 r ×ˢ ball 0 R) \ {0})) : + ∃ g, AnalyticOnNhd ℂ g (ball 0 r ×ˢ ball 0 R) ∧ + EqOn g f ((ball 0 r ×ˢ ball 0 R) \ {0}) := by + classical + have he : hartogsCylinder (ball (0 : ι → ℂ) r) (ball 0 r \ {0}) 0 R = + (ball 0 r ×ˢ ball 0 R) \ {0} := by + ext ⟨z, w⟩ + simp only [hartogsCylinder, mem_union, mem_prod, mem_sdiff, closedBall_zero, + mem_singleton_iff, Prod.zero_eq_mk, Prod.mk.injEq] + tauto + have hn : (ball (0 : ι → ℂ) r \ {0}).Nonempty := by + refine ⟨fun _ => (r / 2 : ℂ), ?_, ?_⟩ + · rw [mem_ball, dist_pi_lt_iff hr] + intro i + simpa [abs_of_pos hr] using half_lt_self hr + · intro hz + have heq := congrFun hz (Classical.arbitrary ι) + change (r / 2 : ℂ) = 0 at heq + have : (r / 2 : ℝ) = 0 := by exact_mod_cast heq + linarith + obtain ⟨g, hg, heq⟩ := exists_extension_hartogsCylinder isOpen_ball isPreconnected_ball + (isOpen_ball.sdiff isClosed_singleton) hn sdiff_subset (le_refl 0) hR (he ▸ hf) + exact ⟨g, hg, he ▸ heq⟩ + +/-- **Spherical-shell extension.** This works for any norm in finite complex dimension at +least two. The proof applies the general compact-hole theorem. -/ +theorem exists_extension_sphericalShell {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] (hdim : 2 ≤ Module.finrank ℂ E) + {ρ R : ℝ} (hρ : 0 ≤ ρ) (hρR : ρ < R) {f : E → F} + (hf : AnalyticOnNhd ℂ f (ball 0 R \ closedBall 0 ρ)) : + ∃ g, AnalyticOnNhd ℂ g (ball 0 R) ∧ EqOn g f (ball 0 R \ closedBall 0 ρ) := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + have hdimR : 1 < Module.finrank ℝ E := by + rw [← Module.finrank_mul_finrank ℝ ℂ E, Complex.finrank_real_complex] + omega + have hrank : 1 < Module.rank ℝ E := by + rw [← Module.finrank_eq_rank] + exact_mod_cast hdimR + exact exists_analyticOnNhd_extension_of_isCompact hdim isOpen_ball + (isCompact_closedBall 0 ρ) (closedBall_subset_ball hρR) + (isPreconnected_ball_diff_closedBall_zero hrank hρ) hf + +/-- The infinite-outer-radius case of shell extension: a function outside a closed ball extends to +the whole space. This follows from the compact-hole theorem and imposes no boundedness at +infinity or near the inner sphere. -/ +theorem exists_extension_exterior_closedBall {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [FiniteDimensional ℂ E] (hdim : 2 ≤ Module.finrank ℂ E) {ρ : ℝ} (hρ : 0 ≤ ρ) + {f : E → F} (hf : AnalyticOnNhd ℂ f (closedBall (0 : E) ρ)ᶜ) : + ∃ g, AnalyticOnNhd ℂ g univ ∧ EqOn g f (closedBall (0 : E) ρ)ᶜ := by + let : ProperSpace E := FiniteDimensional.proper ℂ E + have hdimR : 1 < Module.finrank ℝ E := by + rw [← Module.finrank_mul_finrank ℝ ℂ E, Complex.finrank_real_complex] + omega + have hrank : 1 < Module.rank ℝ E := by + rw [← Module.finrank_eq_rank] + exact_mod_cast hdimR + simpa only [← compl_eq_univ_sdiff] using exists_analyticOnNhd_extension_of_isCompact hdim + isOpen_univ (isCompact_closedBall 0 ρ) (subset_univ _) + (by simpa only [← compl_eq_univ_sdiff] using isPreconnected_compl_closedBall_zero hrank hρ) + (by simpa only [← compl_eq_univ_sdiff] using hf) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean new file mode 100644 index 0000000000..597505cf8a --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean @@ -0,0 +1,390 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.MeanValue +public import Mathlib.MeasureTheory.Integral.CircleAverage +public import Mathlib.Topology.Semicontinuity.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous + +/-! +# Subharmonic functions of one complex variable + +A real-valued function on an open subset of `ℂ` is subharmonic if it is upper semicontinuous and +satisfies the local submean inequality: at every point, for all sufficiently small radii the +function is integrable on the circle and its value at the center is at most its circle average. +This is the definition of [Ransford][Ransford1995], *Potential Theory in the Complex Plane*, +Definition 2.2.1, and of [Fritzsche–Grauert][FritzscheGrauert2002], Chapter II, Section 2, with +the harmonic-majorant condition replaced by the submean inequality. Locality is then immediate. +The submean inequality on every closed disc in the domain and the plurisubharmonic theory are +developed in later files. + +Only real-valued functions are considered; the value `-∞` is not admitted. + +This file proves closure under sums, nonnegative multiples and maxima, gives the holomorphic +examples (real parts, positive powers of norms, logarithms of nonvanishing moduli), and proves +the maximum principle: a subharmonic function on a preconnected open set that attains its +supremum is constant. On a disc, if it is upper semicontinuous on the closed disc, it is +bounded by its supremum on the boundary circle. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 2; +[Range][Range1986] (1986), Chapter II, Section 5; [Ransford][Ransford1995] (1995), Chapter 2. + +## Main definitions + +* `HasSubmeanAt`: The local submean property at a point: for every sufficiently small radius, the + function is integrable on the circle and its value at the center is bounded by its circle average. +* `SubharmonicOn`: A real function is subharmonic on a set if it is upper semicontinuous there and + has the local submean property at each of its points. + +## Main results + +* `SubharmonicOn.eqOn_const_of_isMaxOn`: **Maximum principle.** A subharmonic function on a + preconnected open set that attains its supremum at a point is constant. +* `SubharmonicOn.le_of_le_sphere`: **Maximum principle on a disc.** A function subharmonic on an + open disc and upper semicontinuous on the closed disc is bounded by any bound valid on the + boundary circle. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [R. M. Range, *Holomorphic Functions and Integral Representations in Several Complex + Variables*][Range1986] +* [T. Ransford, *Potential Theory in the Complex Plane*][Ransford1995] +-/ + +public section + +open Filter MeasureTheory Metric Set Real +open scoped Interval Topology + +namespace SeveralComplexVariables + +/-- The local submean property at a point: for every sufficiently small radius, the function is +integrable on the circle and its value at the center is bounded by its circle average. -/ +@[expose] def HasSubmeanAt (u : ℂ → ℝ) (a : ℂ) : Prop := + ∀ᶠ r in 𝓝[>] (0 : ℝ), CircleIntegrable u a r ∧ u a ≤ circleAverage u a r + +/-- A real function is subharmonic on a set if it is upper semicontinuous there and has the local +submean property at each of its points. The set is intended to be open. -/ +@[expose] def SubharmonicOn (u : ℂ → ℝ) (U : Set ℂ) : Prop := + UpperSemicontinuousOn u U ∧ ∀ a ∈ U, HasSubmeanAt u a + +variable {u v : ℂ → ℝ} {U V : Set ℂ} {a : ℂ} + +/-- A subharmonic function is upper semicontinuous. -/ +theorem SubharmonicOn.upperSemicontinuousOn (h : SubharmonicOn u U) : + UpperSemicontinuousOn u U := h.1 + +/-- A subharmonic function has the local submean property at each point of its domain. -/ +theorem SubharmonicOn.hasSubmeanAt (h : SubharmonicOn u U) (ha : a ∈ U) : HasSubmeanAt u a := + h.2 a ha + +/-- Subharmonicity restricts to subsets. -/ +theorem SubharmonicOn.mono (h : SubharmonicOn u U) (hV : V ⊆ U) : SubharmonicOn u V := + ⟨h.1.mono hV, fun a ha => h.2 a (hV ha)⟩ + +/-- The local submean property provides a radius below which the inequality holds. -/ +theorem HasSubmeanAt.exists_forall_lt (h : HasSubmeanAt u a) : + ∃ ρ > 0, ∀ r, 0 < r → r < ρ → CircleIntegrable u a r ∧ u a ≤ circleAverage u a r := by + obtain ⟨ρ, hρ, hsub⟩ := mem_nhdsGT_iff_exists_Ioo_subset.mp h + exact ⟨ρ, hρ, fun r h0 hr => hsub ⟨h0, hr⟩⟩ + +/-- Conversely, a radius bound gives the local submean property. -/ +theorem hasSubmeanAt_of_forall_lt {ρ : ℝ} (hρ : 0 < ρ) + (h : ∀ r, 0 < r → r < ρ → CircleIntegrable u a r ∧ u a ≤ circleAverage u a r) : + HasSubmeanAt u a := + mem_nhdsGT_iff_exists_Ioo_subset.mpr ⟨ρ, hρ, fun r hr => h r hr.1 hr.2⟩ + +/-- Subharmonicity is a local property. -/ +theorem subharmonicOn_of_locally (h : ∀ a ∈ U, ∃ V ∈ 𝓝 a, SubharmonicOn u (V ∩ U)) : + SubharmonicOn u U := by + refine ⟨fun a ha => ?_, fun a ha => ?_⟩ + · obtain ⟨V, hV, hu⟩ := h a ha + intro y hy + have := hu.1 a ⟨mem_of_mem_nhds hV, ha⟩ y hy + rwa [nhdsWithin_inter_of_mem (mem_nhdsWithin_of_mem_nhds hV)] at this + · obtain ⟨V, hV, hu⟩ := h a ha + exact hu.2 a ⟨mem_of_mem_nhds hV, ha⟩ + +section Algebra + +/-- Constants have the local submean property. -/ +theorem hasSubmeanAt_const (c : ℝ) (a : ℂ) : HasSubmeanAt (fun _ => c) a := + Filter.Eventually.of_forall fun _ => ⟨circleIntegrable_const c a _, by rw [circleAverage_const]⟩ + +/-- Constants are subharmonic. -/ +theorem subharmonicOn_const (c : ℝ) (U : Set ℂ) : SubharmonicOn (fun _ => c) U := + ⟨continuousOn_const.upperSemicontinuousOn, fun a _ => hasSubmeanAt_const c a⟩ + +/-- The local submean property is additive. -/ +theorem HasSubmeanAt.add (hu : HasSubmeanAt u a) (hv : HasSubmeanAt v a) : + HasSubmeanAt (fun z => u z + v z) a := by + filter_upwards [hu, hv] with r ⟨hui, hu'⟩ ⟨hvi, hv'⟩ + refine ⟨hui.add hvi, ?_⟩ + rw [circleAverage_fun_add hui hvi] + exact add_le_add hu' hv' + +/-- Sums of subharmonic functions are subharmonic. -/ +theorem SubharmonicOn.add (hu : SubharmonicOn u U) (hv : SubharmonicOn v U) : + SubharmonicOn (fun z => u z + v z) U := + ⟨hu.1.add hv.1, fun a ha => (hu.2 a ha).add (hv.2 a ha)⟩ + +/-- Nonnegative multiples preserve the local submean property. -/ +theorem HasSubmeanAt.const_mul {c : ℝ} (hc : 0 ≤ c) (hu : HasSubmeanAt u a) : + HasSubmeanAt (fun z => c * u z) a := by + filter_upwards [hu] with r ⟨hui, hu'⟩ + refine ⟨(circleIntegrable_def _ a r).mpr (((circleIntegrable_def u a r).mp hui).const_mul c), ?_⟩ + simp only [← smul_eq_mul, circleAverage_fun_smul] + exact smul_le_smul_of_nonneg_left hu' hc + +/-- Nonnegative multiples of subharmonic functions are subharmonic. -/ +theorem SubharmonicOn.const_mul {c : ℝ} (hc : 0 ≤ c) (hu : SubharmonicOn u U) : + SubharmonicOn (fun z => c * u z) U := + ⟨hu.1.const_mul hc, fun a ha => (hu.2 a ha).const_mul hc⟩ + +/-- The pointwise maximum preserves the local submean property. -/ +theorem HasSubmeanAt.sup (hu : HasSubmeanAt u a) (hv : HasSubmeanAt v a) : + HasSubmeanAt (fun z => max (u z) (v z)) a := by + filter_upwards [hu, hv] with r ⟨hui, hu'⟩ ⟨hvi, hv'⟩ + have hm := CircleIntegrable.max hui hvi + refine ⟨hm, max_le ?_ ?_⟩ + · exact hu'.trans (circleAverage_mono hui hm fun z _ => le_max_left _ _) + · exact hv'.trans (circleAverage_mono hvi hm fun z _ => le_max_right _ _) + +/-- The pointwise maximum of two subharmonic functions is subharmonic. -/ +theorem SubharmonicOn.sup (hu : SubharmonicOn u U) (hv : SubharmonicOn v U) : + SubharmonicOn (fun z => max (u z) (v z)) U := + ⟨hu.1.sup hv.1, fun a ha => (hu.2 a ha).sup (hv.2 a ha)⟩ + +end Algebra + +section Holomorphic + +variable {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- A continuous function whose circle averages over all small circles equal its value at the center +has the local submean property; this applies to harmonic functions. -/ +theorem hasSubmeanAt_of_circleAverage_eq {ρ : ℝ} (hρ : 0 < ρ) (hc : ContinuousOn u (ball a ρ)) + (h : ∀ r, 0 < r → r < ρ → circleAverage u a r = u a) : HasSubmeanAt u a := + hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => + ⟨(hc.mono (sphere_subset_closedBall.trans (closedBall_subset_ball hrρ))).circleIntegrable + hr.le, (h r hr hrρ).ge⟩ + +/-- Real parts of holomorphic functions have the local submean property, with equality. -/ +theorem circleAverage_re_eq_of_analyticAt {f : ℂ → ℂ} (hf : AnalyticAt ℂ f a) : + ∃ ρ > 0, ∀ r, 0 < r → r < ρ → circleAverage (fun z => (f z).re) a r = (f a).re := by + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp hf.eventually_analyticAt + have han : AnalyticOnNhd ℂ f (ball a ρ) := fun z hz => hball hz + refine ⟨ρ, hρ, fun r hr hrρ => ?_⟩ + have hd : DiffContOnCl ℂ f (ball a |r|) := by + rw [abs_of_pos hr] + refine DifferentiableOn.diffContOnCl ?_ + rw [closure_ball a hr.ne'] + exact fun z hz => (han z (closedBall_subset_ball hrρ + hz)).differentiableAt.differentiableWithinAt + have hint : CircleIntegrable f a r := + ((han.mono (sphere_subset_closedBall.trans (closedBall_subset_ball + hrρ))).continuousOn).circleIntegrable hr.le + have := Complex.reCLM.circleAverage_comp_comm (f := f) (c := a) (R := r) + simp only [Function.comp_def, Complex.reCLM_apply] at this + rw [this hint, hd.circleAverage] + +/-- The real part of a holomorphic function is subharmonic. -/ +theorem _root_.AnalyticOnNhd.subharmonicOn_re {f : ℂ → ℂ} (hf : AnalyticOnNhd ℂ f U) : + SubharmonicOn (fun z => (f z).re) U := by + refine ⟨(Complex.continuous_re.comp_continuousOn hf.continuousOn).upperSemicontinuousOn, + fun a ha => ?_⟩ + obtain ⟨ρ, hρ, h⟩ := circleAverage_re_eq_of_analyticAt (hf a ha) + obtain ⟨ρ', hρ', hball⟩ := Metric.mem_nhds_iff.mp (hf a ha).eventually_analyticAt + refine hasSubmeanAt_of_circleAverage_eq (lt_min hρ hρ') ?_ fun r hr hrρ => h r hr (hrρ.trans_le + (min_le_left _ _)) + exact Complex.continuous_re.comp_continuousOn + ((AnalyticOnNhd.continuousOn fun z hz => hball (ball_subset_ball (min_le_right _ _) hz))) + +/-- Minus the real part of a holomorphic function is subharmonic. -/ +theorem _root_.AnalyticOnNhd.subharmonicOn_neg_re {f : ℂ → ℂ} (hf : AnalyticOnNhd ℂ f U) : + SubharmonicOn (fun z => -(f z).re) U := by + have := AnalyticOnNhd.subharmonicOn_re (U := U) (f := fun z => -f z) (hf.neg) + simpa using this + +/-- Positive powers of the norm of a holomorphic function are subharmonic. -/ +theorem _root_.AnalyticOnNhd.subharmonicOn_norm_rpow (hU : IsOpen U) {f : ℂ → F} {p : ℝ} + (hp : 0 < p) + (hf : AnalyticOnNhd ℂ f U) : SubharmonicOn (fun z => ‖f z‖ ^ p) U := by + refine ⟨(hf.continuousOn.norm.rpow_const fun _ _ => Or.inr hp.le).upperSemicontinuousOn, + fun a ha => ?_⟩ + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ + have hsub : closedBall a r ⊆ U := (closedBall_subset_ball hrρ).trans hball + refine ⟨((hf.mono hsub).continuousOn.norm.rpow_const fun _ _ => Or.inr hp.le).mono + sphere_subset_closedBall |>.circleIntegrable hr.le, ?_⟩ + exact norm_rpow_le_circleAverage hr hp (hf.mono hsub) + +/-- The logarithm of the modulus of a nonvanishing holomorphic function is subharmonic. -/ +theorem _root_.AnalyticOnNhd.subharmonicOn_log_norm (hU : IsOpen U) {f : ℂ → ℂ} + (hf : AnalyticOnNhd ℂ f U) (hne : ∀ z ∈ U, f z ≠ 0) : + SubharmonicOn (fun z => Real.log ‖f z‖) U := by + have hcont : ContinuousOn (fun z => Real.log ‖f z‖) U := by + refine ContinuousOn.log hf.continuousOn.norm fun z hz => norm_ne_zero_iff.mpr (hne z hz) + refine ⟨hcont.upperSemicontinuousOn, fun a ha => ?_⟩ + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ + have hsub : closedBall a r ⊆ U := (closedBall_subset_ball hrρ).trans hball + refine ⟨(hcont.mono (sphere_subset_closedBall.trans hsub)).circleIntegrable hr.le, ?_⟩ + exact log_norm_le_circleAverage hr (hf.mono hsub) (hne a ha) + +end Holomorphic + +section MaximumPrinciple + +/-- A circle-integrable function bounded by `M` on a circle, upper semicontinuous there and strictly +below `M` at one point, has circle average strictly below `M`. -/ +theorem circleAverage_lt_of_lt {r M : ℝ} (hr : 0 < r) (hint : CircleIntegrable u a r) + (hle : ∀ z ∈ sphere a r, u z ≤ M) (husc : UpperSemicontinuousOn u (sphere a r)) + {z : ℂ} (hz : z ∈ sphere a r) (hlt : u z < M) : circleAverage u a r < M := by + -- a parameter in `[0, 2π)` for the point `z` + obtain ⟨θ, hθ⟩ : ∃ θ, circleMap a r θ = z := by + have : z ∈ range (circleMap a r) := by rw [range_circleMap, abs_of_pos hr]; exact hz + exact this + set θ₀ := toIcoMod two_pi_pos 0 θ with hθ₀ + have hθ₀mem : θ₀ ∈ Ico 0 (2 * π) := by simpa using toIcoMod_mem_Ico two_pi_pos 0 θ + have hθ₀z : circleMap a r θ₀ = z := by + rw [hθ₀, ← self_sub_toIcoDiv_zsmul two_pi_pos 0 θ, (periodic_circleMap a r).sub_zsmul_eq, hθ] + -- upper semicontinuity gives a small arc on which `u < M - ε` + set ε := (M - u z) / 2 with hε + have hε0 : 0 < ε := by rw [hε]; linarith + have husc' := husc z hz (u z + ε) (by linarith) + obtain ⟨δ, hδ, hδsub⟩ := Metric.mem_nhdsWithin_iff.mp husc' + have hballnhds : ball z δ ∈ 𝓝 (circleMap a r θ₀) := by + rw [hθ₀z] + exact ball_mem_nhds z hδ + obtain ⟨η, hη, hηsub⟩ := Metric.mem_nhds_iff.mp + ((continuous_circleMap a r).continuousAt.preimage_mem_nhds hballnhds) + set θ₁ := min (θ₀ + η / 2) (2 * π) with hθ₁ + have hθ₀₁ : θ₀ < θ₁ := lt_min (by linarith) hθ₀mem.2 + have hθ₁le : θ₁ ≤ 2 * π := min_le_right _ _ + have harc : ∀ x ∈ Icc θ₀ θ₁, u (circleMap a r x) ≤ M - ε := by + intro x hx + have hxη : x ∈ ball θ₀ η := by + rw [mem_ball, Real.dist_eq, abs_lt] + constructor <;> linarith [hx.1, hx.2, min_le_left (θ₀ + η / 2) (2 * π)] + have hmem : circleMap a r x ∈ ball z δ := hηsub hxη + have : u (circleMap a r x) < u z + ε := + hδsub ⟨hmem, circleMap_mem_sphere a hr.le x⟩ + linarith + -- compare integrals of the nonnegative function `M - u` + set g : ℝ → ℝ := fun x => M - u (circleMap a r x) with hg + have hgint : IntervalIntegrable g volume 0 (2 * π) := + (intervalIntegrable_const).sub ((circleIntegrable_def u a r).mp hint) + have hgnn : 0 ≤ᵐ[volume.restrict (Ioc 0 (2 * π))] g := by + refine (ae_restrict_iff' measurableSet_Ioc).mpr (Filter.Eventually.of_forall fun x _ => ?_) + exact sub_nonneg.mpr (hle _ (circleMap_mem_sphere a hr.le x)) + have hsmall : (θ₁ - θ₀) * ε ≤ ∫ x in θ₀..θ₁, g x := by + have hsub : [[θ₀, θ₁]] ⊆ [[0, 2 * π]] := by + rw [uIcc_of_le hθ₀₁.le, uIcc_of_le Real.two_pi_pos.le] + exact Icc_subset_Icc hθ₀mem.1 hθ₁le + have := intervalIntegral.integral_mono_on hθ₀₁.le intervalIntegrable_const + (hgint.mono_set hsub) fun x hx => (by linarith [harc x hx] : ε ≤ g x) + simpa using this + have hbig : ∫ x in θ₀..θ₁, g x ≤ ∫ x in (0:ℝ)..2 * π, g x := + intervalIntegral.integral_mono_interval hθ₀mem.1 hθ₀₁.le hθ₁le hgnn hgint + have hpos : 0 < ∫ x in (0:ℝ)..2 * π, g x := + (mul_pos (sub_pos.mpr hθ₀₁) hε0).trans_le (hsmall.trans hbig) + have hcalc : ∫ x in (0:ℝ)..2 * π, g x = 2 * π * (M - circleAverage u a r) := by + rw [hg, intervalIntegral.integral_sub intervalIntegrable_const + ((circleIntegrable_def u a r).mp hint), intervalIntegral.integral_const, + circleAverage_def, smul_eq_mul, smul_eq_mul, sub_zero] + field_simp + rw [hcalc] at hpos + nlinarith [Real.two_pi_pos] + +/-- A subharmonic function attaining its supremum at a point is constant near that point. -/ +theorem SubharmonicOn.eventually_eq_of_isMaxOn (hU : IsOpen U) (hu : SubharmonicOn u U) + (ha : a ∈ U) (hmax : ∀ z ∈ U, u z ≤ u a) : ∀ᶠ z in 𝓝 a, u z = u a := by + obtain ⟨ρ₁, hρ₁, hsub⟩ := (hu.hasSubmeanAt ha).exists_forall_lt + obtain ⟨ρ₂, hρ₂, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + filter_upwards [ball_mem_nhds a (lt_min hρ₁ hρ₂)] with z hz + by_cases hza : z = a + · rw [hza] + · have hr0 : 0 < dist z a := dist_pos.mpr hza + have hrρ₁ : dist z a < ρ₁ := (mem_ball.mp hz).trans_le (min_le_left _ _) + have hsph : sphere a (dist z a) ⊆ U := fun w hw => hball (by + rw [mem_ball, mem_sphere.mp hw] + exact (mem_ball.mp hz).trans_le (min_le_right _ _)) + obtain ⟨hint, havg⟩ := hsub _ hr0 hrρ₁ + by_contra hne + have hzs : z ∈ sphere a (dist z a) := mem_sphere.mpr rfl + have hlt : u z < u a := lt_of_le_of_ne (hmax z (hsph hzs)) hne + have := circleAverage_lt_of_lt hr0 hint (fun w hw => hmax w (hsph hw)) (hu.1.mono hsph) hzs hlt + linarith + +/-- **Maximum principle.** A subharmonic function on a preconnected open set that attains +its supremum at a point is constant. -/ +theorem SubharmonicOn.eqOn_const_of_isMaxOn (hU : IsOpen U) (hc : IsPreconnected U) + (hu : SubharmonicOn u U) (ha : a ∈ U) (hmax : ∀ z ∈ U, u z ≤ u a) : + ∀ z ∈ U, u z = u a := by + let W := U ∩ {z | ∀ᶠ w in 𝓝 z, u w = u a} + have hWo : IsOpen W := hU.inter isOpen_setOfPred_eventually_nhds + have hWne : (U ∩ W).Nonempty := ⟨a, ha, ha, hu.eventually_eq_of_isMaxOn hU ha hmax⟩ + have hWval : ∀ w ∈ W, u w = u a := fun w hw => (mem_ofPred.mp hw.2).self_of_nhds + have hcl : closure W ∩ U ⊆ W := by + rintro z ⟨hz, hzU⟩ + have hle : u a ≤ u z := by + by_contra hlt + push Not at hlt + have hne : NeBot (𝓝[W] z) := mem_closure_iff_nhdsWithin_neBot.mp hz + have h1 : ∀ᶠ w in 𝓝[W] z, u w < u a := + nhdsWithin_mono z inter_subset_left (hu.1 z hzU (u a) hlt) + have h2 : ∀ᶠ w in 𝓝[W] z, u w = u a := eventually_nhdsWithin_of_forall hWval + obtain ⟨w, hw1, hw2⟩ := (h1.and h2).exists + linarith + have heq : u z = u a := le_antisymm (hmax z hzU) hle + refine ⟨hzU, ?_⟩ + have := hu.eventually_eq_of_isMaxOn hU hzU (fun w hw => (hmax w hw).trans heq.ge) + show ∀ᶠ w in 𝓝 z, u w = u a + simpa only [heq] using this + intro z hz + exact hWval z (hc.subset_of_closure_inter_subset hWo hWne hcl hz) + +/-- **Maximum principle on a disc.** A function subharmonic on an open disc and upper +semicontinuous on the closed disc is bounded by any bound valid on the boundary circle. -/ +theorem SubharmonicOn.le_of_le_sphere {r M : ℝ} (hr : 0 < r) (hu : SubharmonicOn u (ball a r)) + (husc : UpperSemicontinuousOn u (closedBall a r)) (hM : ∀ z ∈ sphere a r, u z ≤ M) : + ∀ z ∈ closedBall a r, u z ≤ M := by + obtain ⟨z₀, hz₀, hmax⟩ := + husc.exists_isMaxOn (nonempty_closedBall.mpr hr.le) (isCompact_closedBall a r) + suffices h : u z₀ ≤ M from fun z hz => (hmax hz).trans h + by_cases hs : z₀ ∈ sphere a r + · exact hM z₀ hs + · have hz₀b : z₀ ∈ ball a r := by + rw [mem_closedBall] at hz₀ + exact mem_ball.mpr (lt_of_le_of_ne hz₀ fun h => hs (mem_sphere.mpr h)) + have hconst := hu.eqOn_const_of_isMaxOn isOpen_ball isPreconnected_ball hz₀b + fun z hz => hmax (ball_subset_closedBall hz) + obtain ⟨p, hp⟩ : (sphere a r).Nonempty := NormedSpace.sphere_nonempty.mpr hr.le + have hpcl : p ∈ closedBall a r := sphere_subset_closedBall hp + have hle : u z₀ ≤ u p := by + by_contra hlt + push Not at hlt + have hne : NeBot (𝓝[ball a r] p) := mem_closure_iff_nhdsWithin_neBot.mp (by + rw [closure_ball a hr.ne'] + exact hpcl) + have h1 : ∀ᶠ w in 𝓝[ball a r] p, u w < u z₀ := + nhdsWithin_mono p ball_subset_closedBall (husc p hpcl (u z₀) hlt) + have h2 : ∀ᶠ w in 𝓝[ball a r] p, u w = u z₀ := eventually_nhdsWithin_of_forall hconst + obtain ⟨w, hw1, hw2⟩ := (h1.and h2).exists + linarith + exact hle.trans (hM p hp) + +end MaximumPrinciple + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/Majorant.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/Majorant.lean new file mode 100644 index 0000000000..dd67146e95 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/Majorant.lean @@ -0,0 +1,206 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.Deriv.Polynomial +public import Mathlib.Analysis.Fourier.AddCircle +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic + +/-! +# Harmonic polynomial majorants and the submean inequality + +Real parts of complex polynomials in `(z - a) / r` are harmonic and approximate every continuous +function on the circle of radius `r` about `a` uniformly, by density of trigonometric +polynomials. Consequently a continuous function satisfies the submean inequality on a closed +disc as soon as it lies below the center value of every such harmonic polynomial that dominates +it on the boundary circle. + +Combined with the maximum principle on discs, this gives the submean inequality on every closed +disc in the domain for continuous subharmonic functions, whose definition only asks for the +inequality on small circles. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Section 2; +[Ransford][Ransford1995] (1995), Chapter 2. + +## Main results + +* `le_circleAverage_of_forall_polynomial_majorant`: **Harmonic-majorant criterion.** A function + continuous on a circle whose center value is dominated by the center value of every harmonic + polynomial majorant on the circle satisfies the submean inequality. +* `SubharmonicOn.le_circleAverage_of_continuousOn`: **Submean inequality on closed discs.** A + continuous subharmonic function satisfies the submean inequality on every closed disc contained in + its domain. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [T. Ransford, *Potential Theory in the Complex Plane*][Ransford1995] +-/ + +public section + +open Filter Metric Set Real +open scoped Topology + +namespace SeveralComplexVariables + +/-- Every trigonometric polynomial is the sum of a polynomial and a conjugated polynomial in the +circle variable. -/ +theorem exists_polynomial_of_mem_span_fourier (ψ : C(AddCircle (2 * π), ℂ)) + (hψ : ψ ∈ Submodule.span ℂ (Set.range (fourier (T := 2 * π)))) : + ∃ Q₁ Q₂ : Polynomial ℂ, ∀ x : AddCircle (2 * π), + ψ x = Q₁.eval ((AddCircle.toCircle x : Circle) : ℂ) + + (starRingEnd ℂ) (Q₂.eval ((AddCircle.toCircle x : Circle) : ℂ)) := by + induction hψ using Submodule.span_induction with + | mem ψ hψ => + obtain ⟨n, rfl⟩ := hψ + rcases le_or_gt 0 n with hn | hn + · refine ⟨Polynomial.X ^ n.toNat, 0, fun x => ?_⟩ + simp only [fourier_apply, AddCircle.toCircle_zsmul, Circle.coe_zpow, Polynomial.eval_pow, + Polynomial.eval_X, Polynomial.eval_zero, map_zero, add_zero] + rw [← zpow_natCast, Int.toNat_of_nonneg hn] + · set m := (-n).toNat with hmdef + refine ⟨0, Polynomial.X ^ m, fun x => ?_⟩ + simp only [fourier_apply, AddCircle.toCircle_zsmul, Polynomial.eval_pow, Polynomial.eval_X, + Polynomial.eval_zero, zero_add] + have hm : (n : ℤ) = -(m : ℤ) := by + rw [hmdef, Int.toNat_of_nonneg (neg_nonneg.mpr hn.le), neg_neg] + rw [hm, zpow_neg, zpow_natCast, Circle.coe_inv_eq_conj, Circle.coe_pow] + | zero => exact ⟨0, 0, fun x => by simp⟩ + | add ψ₁ ψ₂ _ _ ih₁ ih₂ => + obtain ⟨Q₁, Q₂, h₁⟩ := ih₁ + obtain ⟨Q₃, Q₄, h₂⟩ := ih₂ + refine ⟨Q₁ + Q₃, Q₂ + Q₄, fun x => ?_⟩ + simp only [ContinuousMap.add_apply, h₁, h₂, Polynomial.eval_add, map_add] + ring + | smul c ψ _ ih => + obtain ⟨Q₁, Q₂, h⟩ := ih + refine ⟨Polynomial.C c * Q₁, Polynomial.C ((starRingEnd ℂ) c) * Q₂, fun x => ?_⟩ + simp only [ContinuousMap.smul_apply, smul_eq_mul, h, Polynomial.eval_mul, Polynomial.eval_C, + map_mul, Complex.conj_conj] + ring + +/-- Continuous functions on a circle are uniformly approximated by real parts of polynomials in the +normalized circle variable. -/ +theorem exists_polynomial_re_approx {v : ℂ → ℝ} {a : ℂ} {r : ℝ} (hr : 0 < r) + (hv : ContinuousOn v (sphere a r)) {ε : ℝ} (hε : 0 < ε) : + ∃ Q : Polynomial ℂ, ∀ z ∈ sphere a r, |v z - (Q.eval ((z - a) / r)).re| < ε := by + have hpos : (0 : ℝ) < 2 * π := Real.two_pi_pos + have : Fact (0 < 2 * π) := ⟨hpos⟩ + let e : AddCircle (2 * π) → ℂ := fun x => a + r * (AddCircle.toCircle x : ℂ) + have he_cont : Continuous e := by + have := continuous_subtype_val.comp (AddCircle.continuous_toCircle (T := 2 * π)) + fun_prop + have he_mem : ∀ x, e x ∈ sphere a r := fun x => by + simp [e, abs_of_pos hr] + let φ : C(AddCircle (2 * π), ℂ) := + ⟨fun x => (v (e x) : ℂ), Complex.continuous_ofReal.comp (hv.comp_continuous he_cont he_mem)⟩ + have hφ : φ ∈ closure ((Submodule.span ℂ (Set.range (fourier (T := 2 * π)))) : Set _) := by + rw [← Submodule.topologicalClosure_coe, span_fourier_closure_eq_top] + trivial + obtain ⟨ψ, hψ, hdist⟩ := Metric.mem_closure_iff.mp hφ ε hε + obtain ⟨Q₁, Q₂, hQ⟩ := exists_polynomial_of_mem_span_fourier ψ hψ + refine ⟨Q₁ + Q₂, fun z hz => ?_⟩ + -- a parameter for the point `z` + obtain ⟨θ, hθ⟩ : ∃ θ : ℝ, circleMap a r θ = z := by + have : z ∈ Set.range (circleMap a r) := by rw [range_circleMap, abs_of_pos hr]; exact hz + exact this + set x : AddCircle (2 * π) := (θ : AddCircle (2 * π)) with hx + have hex : e x = z := by + rw [← hθ] + simp only [e, hx, AddCircle.toCircle_apply_mk, Circle.coe_exp, circleMap] + congr 3 + field_simp + have hr' : (r : ℂ) ≠ 0 := by exact_mod_cast hr.ne' + have hz' : (z - a) / r = (AddCircle.toCircle x : ℂ) := by + rw [← hex] + simp only [e] + rw [add_sub_cancel_left, mul_div_cancel_left₀ _ hr'] + have hre : (ψ x).re = ((Q₁ + Q₂).eval ((z - a) / r)).re := by + rw [hQ x, hz', Polynomial.eval_add, Complex.add_re, Complex.add_re, Complex.conj_re] + have h1 : v z = (φ x).re := by simp [φ, hex] + rw [h1, ← hre] + have := (ContinuousMap.dist_lt_iff hε).mp hdist x + rw [dist_eq_norm] at this + calc |(φ x).re - (ψ x).re| = |(φ x - ψ x).re| := by rw [Complex.sub_re] + _ ≤ ‖φ x - ψ x‖ := Complex.abs_re_le_norm _ + _ < ε := this + +/-- The real part of a polynomial in the normalized circle variable has circle average equal to its +value at the center. -/ +theorem circleAverage_re_polynomial (Q : Polynomial ℂ) (a : ℂ) {r : ℝ} (hr : 0 < r) : + circleAverage (fun z => (Q.eval ((z - a) / r)).re) a r = (Q.eval 0).re := by + have hd : Differentiable ℂ fun z : ℂ => Q.eval ((z - a) / r) := + Q.differentiable.comp (by fun_prop) + have hcl : DiffContOnCl ℂ (fun z : ℂ => Q.eval ((z - a) / r)) (ball a |r|) := + hd.diffContOnCl + have hint : CircleIntegrable (fun z : ℂ => Q.eval ((z - a) / r)) a r := + hd.continuous.continuousOn.circleIntegrable hr.le + have := Complex.reCLM.circleAverage_comp_comm (f := fun z : ℂ => Q.eval ((z - a) / r)) + (c := a) (R := r) hint + simp only [Function.comp_def, Complex.reCLM_apply] at this + rw [this, hcl.circleAverage] + simp + +/-- **Harmonic-majorant criterion.** A function continuous on a circle whose center value is +dominated by the center value of every harmonic polynomial majorant on the circle satisfies +the submean inequality. -/ +theorem le_circleAverage_of_forall_polynomial_majorant {v : ℂ → ℝ} {a : ℂ} {r : ℝ} (hr : 0 < r) + (hv : ContinuousOn v (sphere a r)) + (h : ∀ Q : Polynomial ℂ, (∀ z ∈ sphere a r, v z ≤ (Q.eval ((z - a) / r)).re) → + v a ≤ (Q.eval 0).re) : + v a ≤ circleAverage v a r := by + have hint : CircleIntegrable v a r := hv.circleIntegrable hr.le + refine le_of_forall_pos_le_add fun ε hε => ?_ + obtain ⟨Q, hQ⟩ := exists_polynomial_re_approx hr hv (half_pos hε) + have hQre : ∀ z, ((Q + Polynomial.C (ε / 2 : ℂ)).eval ((z - a) / r)).re = + (Q.eval ((z - a) / r)).re + ε / 2 := fun z => by + simp [Polynomial.eval_add] + have hmaj : ∀ z ∈ sphere a r, v z ≤ ((Q + Polynomial.C (ε / 2 : ℂ)).eval ((z - a) / r)).re := by + intro z hz + rw [hQre] + linarith [(abs_lt.mp (hQ z hz)).2] + have h1 := h _ hmaj + rw [Polynomial.eval_add, Polynomial.eval_C, Complex.add_re] at h1 + have hcont : ContinuousOn (fun z => (Q.eval ((z - a) / r)).re) (sphere a r) := + (Complex.continuous_re.comp (Q.differentiable.comp (by fun_prop)).continuous).continuousOn + have h2 : circleAverage (fun z => (Q.eval ((z - a) / r)).re) a r ≤ + circleAverage (fun z => v z + ε / 2) a r := by + refine circleAverage_mono (hcont.circleIntegrable hr.le) + (hint.add (circleIntegrable_const _ a r)) fun z hz => ?_ + have := (abs_lt.mp (hQ z (by simpa [abs_of_pos hr] using hz))).1 + linarith + rw [circleAverage_re_polynomial Q a hr] at h2 + rw [circleAverage_fun_add hint (circleIntegrable_const _ a r), circleAverage_const] at h2 + have h3 : ((ε / 2 : ℂ)).re = ε / 2 := by simp + linarith + +/-- **Submean inequality on closed discs.** A continuous subharmonic function satisfies the +submean inequality on every closed disc contained in its domain. -/ +theorem SubharmonicOn.le_circleAverage_of_continuousOn {u : ℂ → ℝ} {U : Set ℂ} + (hu : SubharmonicOn u U) (hc : ContinuousOn u U) {a : ℂ} {r : ℝ} (hr : 0 < r) + (hsub : closedBall a r ⊆ U) : u a ≤ circleAverage u a r := by + refine le_circleAverage_of_forall_polynomial_majorant hr + (hc.mono (sphere_subset_closedBall.trans hsub)) fun Q hQ => ?_ + have hQan : AnalyticOnNhd ℂ (fun z : ℂ => Q.eval ((z - a) / r)) (ball a r) := + fun z _ => (Q.differentiable.comp (by fun_prop)).analyticAt z + have hw : SubharmonicOn (fun z => u z + -(Q.eval ((z - a) / r)).re) (ball a r) := + (hu.mono (ball_subset_closedBall.trans hsub)).add + (AnalyticOnNhd.subharmonicOn_neg_re hQan) + have husc : UpperSemicontinuousOn (fun z => u z + -(Q.eval ((z - a) / r)).re) + (closedBall a r) := + ((hc.mono hsub).add (Complex.continuous_re.comp + (Q.differentiable.comp (by fun_prop)).continuous).continuousOn.neg).upperSemicontinuousOn + have := hw.le_of_le_sphere hr husc (M := 0) (fun z hz => by linarith [hQ z hz]) a + (mem_closedBall_self hr.le) + have h0 : ((a - a) / r) = 0 := by simp + rw [h0] at this + linarith + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/SmoothCriterion.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/SmoothCriterion.lean new file mode 100644 index 0000000000..65e4989615 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic/SmoothCriterion.lean @@ -0,0 +1,407 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Calculus.FDeriv.Symmetric +public import Mathlib.Analysis.InnerProductSpace.Laplacian +public import Mathlib.Analysis.SpecialFunctions.Integrals.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant + +/-! +# The Laplacian criterion for subharmonicity + +A `C²` function of one complex variable is subharmonic exactly when its Laplacian is +nonnegative. The proof expands the circle average of a `C²` function to second order: the +difference between the circle average of radius `r` and the center value is `r ^ 2 / 4` times +the Laplacian, up to `o(r ^ 2)`. A positive Laplacian therefore gives the strict submean +inequality on small circles and a negative one the reverse inequality. The nonstrict direction +adds a small multiple of `‖z - t₀‖ ^ 2`, whose Laplacian is `4`, and uses the submean inequality +on closed discs for continuous subharmonic functions. + +The Laplacian is Mathlib's `InnerProductSpace` Laplacian on `ℂ`, written in terms of the second +Fréchet derivative in the directions `1` and `I`. + +References: [Fritzsche–Grauert][FritzscheGrauert2002] (2002), Chapter II, Theorem 2.8; +[Hörmander][Hormander1973] (1973), Section 1.6 and Theorem 2.6.2. + +## Main results + +* `exists_taylor_bound`: **Uniform second-order Taylor bound.** For a `C²` function on a real normed + space, the second-order Taylor remainder at a point is bounded by `ε ‖h‖ ^ 2` for all small + increments `h`. +* `exists_circleAverage_sub_le`: **Second-order expansion of circle averages.** For a `C²` function, + the circle average of radius `r` differs from the center value by `r ^ 2 / 4` times the Laplacian, + up to `ε r ^ 2` for all small `r`. +* `HasSubmeanAt.laplacian_nonneg`: **Necessity.** A `C²` subharmonic function has nonnegative + Laplacian. +* `subharmonicOn_of_laplacian_nonneg`: **Sufficiency.** A `C²` function with nonnegative Laplacian + on an open set is subharmonic. + +## References + +* [K. Fritzsche and H. Grauert, *From Holomorphic Functions to Complex + Manifolds*][FritzscheGrauert2002] +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +-/ + +public section + +open Complex Filter MeasureTheory Metric Set Real +open scoped Topology InnerProductSpace Laplacian + +namespace SeveralComplexVariables + +variable {g : ℂ → ℝ} {t₀ : ℂ} + +/-- The Laplacian on `ℂ` in terms of the iterated Fréchet derivative. -/ +theorem laplacian_eq_fderiv_fderiv (g : ℂ → ℝ) (t : ℂ) : + Δ g t = fderiv ℝ (fderiv ℝ g) t 1 1 + fderiv ℝ (fderiv ℝ g) t I I := by + rw [InnerProductSpace.laplacian_eq_iteratedFDeriv_complexPlane] + simp [iteratedFDeriv_two_apply] + +/-- A point on the circle of radius `r` about `0`, as a real combination of `1` and `I`. -/ +theorem circleMap_zero_eq_smul (r θ : ℝ) : + circleMap 0 r θ = (r * Real.cos θ) • (1 : ℂ) + (r * Real.sin θ) • I := by + simp only [circleMap, zero_add, Complex.exp_mul_I, Complex.real_smul] + push_cast + ring + +/-- **Uniform second-order Taylor bound.** For a `C²` function on a real normed space, the +second-order Taylor remainder at a point is bounded by `ε ‖h‖ ^ 2` for all small increments +`h`. The bound is uniform in the direction of `h`. -/ +theorem exists_taylor_bound {G : Type*} [NormedAddCommGroup G] [NormedSpace ℝ G] {g : G → ℝ} + {t₀ : G} (hg : ContDiffAt ℝ 2 g t₀) {ε : ℝ} (hε : 0 < ε) : + ∃ δ > 0, ∀ h : G, ‖h‖ < δ → + |g (t₀ + h) - g t₀ - fderiv ℝ g t₀ h - (1 / 2) * fderiv ℝ (fderiv ℝ g) t₀ h h| + ≤ ε * ‖h‖ ^ 2 := by + set D := fderiv ℝ g with hDdef + set B := fderiv ℝ (fderiv ℝ g) t₀ with hBdef + have hD : HasFDerivAt D B t₀ := + ((hg.fderiv_right (m := 1) (by norm_num)).differentiableAt (by norm_num)).hasFDerivAt + have hev : ∀ᶠ y in 𝓝 t₀, HasFDerivAt g (D y) y := by + filter_upwards [hg.eventually (by simp)] with y hy + exact (hy.differentiableAt (by norm_num)).hasFDerivAt + have hsymm : ∀ v w, B v w = B w v := second_derivative_symmetric_of_eventually hev hD + have hlo : ∀ᶠ h in 𝓝 (0 : G), ‖D (t₀ + h) - D t₀ - B h‖ ≤ ε * ‖h‖ := + (hasFDerivAt_iff_isLittleO_nhds_zero.mp hD).def hε + obtain ⟨δ₁, hδ₁, hball₁⟩ := Metric.mem_nhds_iff.mp hlo + obtain ⟨δ₂, hδ₂, hball₂⟩ := Metric.mem_nhds_iff.mp hev + refine ⟨min δ₁ δ₂, lt_min hδ₁ hδ₂, fun h hh => ?_⟩ + set φ : G → ℝ := fun k => g (t₀ + k) - g t₀ - D t₀ k - (1 / 2) * B k k with hφdef + have hφ' : ∀ k : G, ‖k‖ < min δ₁ δ₂ → HasFDerivAt φ (D (t₀ + k) - D t₀ - B k) k := by + intro k hk + have hk₂ : t₀ + k ∈ ball t₀ δ₂ := by + simpa [dist_eq_norm] using hk.trans_le (min_le_right _ _) + have h1 : HasFDerivAt (fun k => g (t₀ + k)) (D (t₀ + k)) k := + ((hball₂ hk₂).comp k ((hasFDerivAt_id k).const_add t₀)).congr_fderiv + (ContinuousLinearMap.comp_id _) + have h2 : HasFDerivAt (fun k => D t₀ k) (D t₀) k := (D t₀).hasFDerivAt + have h3 : HasFDerivAt (fun k => (1 / 2 : ℝ) * B k k) (B k) k := by + have hb := (B.hasFDerivAt (x := k)).clm_apply (hasFDerivAt_id k) + have := hb.const_mul (1 / 2 : ℝ) + refine this.congr_fderiv ?_ + ext s + simp + linarith [hsymm s k] + have := (h1.sub_const (g t₀)).sub h2 |>.sub h3 + convert this using 1 + have hbound : ∀ k ∈ closedBall (0 : G) ‖h‖, ‖D (t₀ + k) - D t₀ - B k‖ ≤ ε * ‖h‖ := by + intro k hk + have hk' : ‖k‖ ≤ ‖h‖ := by simpa using hk + have hk₁ : k ∈ ball (0 : G) δ₁ := by + simpa using hk'.trans_lt (hh.trans_le (min_le_left _ _)) + exact (hball₁ hk₁).trans (mul_le_mul_of_nonneg_left hk' hε.le) + have hmvt := Convex.norm_image_sub_le_of_norm_hasFDerivWithin_le + (f := φ) (f' := fun k => D (t₀ + k) - D t₀ - B k) (s := closedBall (0 : G) ‖h‖) + (fun k hk => (hφ' k (by + have hk' : ‖k‖ ≤ ‖h‖ := by simpa using hk + exact hk'.trans_lt hh)).hasFDerivWithinAt) + hbound (convex_closedBall _ _) (mem_closedBall_self (norm_nonneg h)) + (mem_closedBall_zero_iff.mpr le_rfl) + have hφ0 : φ 0 = 0 := by simp [hφdef] + rw [hφ0, sub_zero, sub_zero, Real.norm_eq_abs] at hmvt + calc |g (t₀ + h) - g t₀ - fderiv ℝ g t₀ h - (1 / 2) * fderiv ℝ (fderiv ℝ g) t₀ h h| + = |φ h| := rfl + _ ≤ ε * ‖h‖ * ‖h‖ := hmvt + _ = ε * ‖h‖ ^ 2 := by ring + +/-- The integral of the cosine over a period vanishes. -/ +private theorem integral_cos_two_pi : ∫ θ in (0 : ℝ)..2 * π, Real.cos θ = 0 := by + simp [integral_cos] + +/-- The integral of the sine over a period vanishes. -/ +private theorem integral_sin_two_pi : ∫ θ in (0 : ℝ)..2 * π, Real.sin θ = 0 := by + simp [integral_sin] + +/-- The integral of the squared cosine over a period is `π`. -/ +private theorem integral_cos_sq_two_pi : ∫ θ in (0 : ℝ)..2 * π, Real.cos θ ^ 2 = π := by + rw [integral_cos_sq] + simp + +/-- The integral of the squared sine over a period is `π`. -/ +private theorem integral_sin_sq_two_pi : ∫ θ in (0 : ℝ)..2 * π, Real.sin θ ^ 2 = π := by + rw [integral_sin_sq] + simp + +/-- The integral of `sin θ cos θ` over a period vanishes. -/ +private theorem integral_sin_mul_cos_two_pi : + ∫ θ in (0 : ℝ)..2 * π, Real.sin θ * Real.cos θ = 0 := by + rw [integral_sin_mul_cos₁] + simp + +/-- The circle integral of a real-linear form vanishes. -/ +theorem integral_clm_circleMap_zero (L : ℂ →L[ℝ] ℝ) (r : ℝ) : + ∫ θ in (0 : ℝ)..2 * π, L (circleMap 0 r θ) = 0 := by + have : (fun θ => L (circleMap 0 r θ)) = + fun θ => (r * L 1) * Real.cos θ + (r * L I) * Real.sin θ := by + funext θ + rw [circleMap_zero_eq_smul, map_add, map_smul, map_smul, smul_eq_mul, smul_eq_mul] + ring + rw [this, intervalIntegral.integral_add, intervalIntegral.integral_const_mul, + intervalIntegral.integral_const_mul, integral_cos_two_pi, integral_sin_two_pi] + · ring + · exact (continuous_const.mul Real.continuous_cos).intervalIntegrable _ _ + · exact (continuous_const.mul Real.continuous_sin).intervalIntegrable _ _ + +/-- The circle integral of a real bilinear form on the diagonal is `π r ^ 2` times its trace in the +directions `1` and `I`. -/ +theorem integral_bilinear_circleMap (B : ℂ →L[ℝ] ℂ →L[ℝ] ℝ) (r : ℝ) : + ∫ θ in (0 : ℝ)..2 * π, B (circleMap 0 r θ) (circleMap 0 r θ) = + π * r ^ 2 * (B 1 1 + B I I) := by + have : (fun θ => B (circleMap 0 r θ) (circleMap 0 r θ)) = + fun θ => (r ^ 2 * B 1 1) * Real.cos θ ^ 2 + (r ^ 2 * (B 1 I + B I 1)) * + (Real.sin θ * Real.cos θ) + (r ^ 2 * B I I) * Real.sin θ ^ 2 := by + funext θ + rw [circleMap_zero_eq_smul] + simp only [map_add, map_smul, add_apply, smul_apply, smul_eq_mul] + ring + rw [this, intervalIntegral.integral_add, intervalIntegral.integral_add, + intervalIntegral.integral_const_mul, intervalIntegral.integral_const_mul, + intervalIntegral.integral_const_mul, integral_cos_sq_two_pi, integral_sin_mul_cos_two_pi, + integral_sin_sq_two_pi] + · ring + · exact (continuous_const.mul (Real.continuous_cos.pow 2)).intervalIntegrable _ _ + · exact (continuous_const.mul (Real.continuous_sin.mul Real.continuous_cos)).intervalIntegrable + _ _ + · exact ((continuous_const.mul (Real.continuous_cos.pow 2)).add + (continuous_const.mul (Real.continuous_sin.mul Real.continuous_cos))).intervalIntegrable _ _ + · exact (continuous_const.mul (Real.continuous_sin.pow 2)).intervalIntegrable _ _ + +/-- **Second-order expansion of circle averages.** For a `C²` function, the circle average +of radius `r` differs from the center value by `r ^ 2 / 4` times the Laplacian, up to +`ε r ^ 2` for all small `r`. -/ +theorem exists_circleAverage_sub_le (hg : ContDiffAt ℝ 2 g t₀) {ε : ℝ} (hε : 0 < ε) : + ∃ δ > 0, ∀ r, 0 < r → r < δ → CircleIntegrable g t₀ r ∧ + |circleAverage g t₀ r - g t₀ - r ^ 2 / 4 * Δ g t₀| ≤ ε * r ^ 2 := by + obtain ⟨δ₁, hδ₁, htaylor⟩ := exists_taylor_bound hg hε + obtain ⟨δ₂, hδ₂, hcont⟩ := Metric.mem_nhds_iff.mp (hg.eventually (by simp)) + have hgc : ContinuousOn g (ball t₀ δ₂) := fun y hy => + (show ContDiffAt ℝ 2 g y from hcont hy).continuousAt.continuousWithinAt + refine ⟨min δ₁ δ₂, lt_min hδ₁ hδ₂, fun r hr hrδ => ?_⟩ + set D := fderiv ℝ g with hDdef + set B := fderiv ℝ (fderiv ℝ g) t₀ with hBdef + have hmap : ∀ θ : ℝ, circleMap t₀ r θ = t₀ + circleMap 0 r θ := fun θ => by + simp [circleMap] + have hnorm : ∀ θ : ℝ, ‖circleMap 0 r θ‖ = r := fun θ => by + simp [circleMap, abs_of_pos hr] + have hint : CircleIntegrable g t₀ r := by + refine ContinuousOn.circleIntegrable hr.le (hgc.mono fun z hz => ?_) + exact sphere_subset_closedBall.trans (closedBall_subset_ball (hrδ.trans_le (min_le_right _ + _))) hz + refine ⟨hint, ?_⟩ + -- the remainder as a function of the angle + set R : ℝ → ℝ := fun θ => g (t₀ + circleMap 0 r θ) - g t₀ - D t₀ (circleMap 0 r θ) - + (1 / 2) * B (circleMap 0 r θ) (circleMap 0 r θ) with hRdef + have hRle : ∀ θ, |R θ| ≤ ε * r ^ 2 := fun θ => by + have := htaylor (circleMap 0 r θ) (by rw [hnorm]; exact hrδ.trans_le (min_le_left _ _)) + rwa [hnorm] at this + have hRint : ‖∫ θ in (0 : ℝ)..2 * π, R θ‖ ≤ ε * r ^ 2 * |2 * π - 0| := + intervalIntegral.norm_integral_le_of_norm_le_const fun θ _ => by + rw [Real.norm_eq_abs]; exact hRle θ + rw [sub_zero, abs_of_pos Real.two_pi_pos, Real.norm_eq_abs] at hRint + -- integrability of the pieces + have hcm : Continuous fun θ : ℝ => circleMap 0 r θ := continuous_circleMap 0 r + have hi₁ : IntervalIntegrable (fun θ => g (t₀ + circleMap 0 r θ)) volume 0 (2 * π) := by + have := (circleIntegrable_def g t₀ r).mp hint + simpa only [hmap] using this + have hi₂ : IntervalIntegrable (fun θ => D t₀ (circleMap 0 r θ)) volume 0 (2 * π) := + ((D t₀).continuous.comp hcm).intervalIntegrable _ _ + have hi₃ : IntervalIntegrable (fun θ => (1 / 2 : ℝ) * B (circleMap 0 r θ) (circleMap 0 r θ)) + volume 0 (2 * π) := + (continuous_const.mul (B.continuous₂.comp (hcm.prodMk hcm))).intervalIntegrable _ _ + -- the integral identity + have hsplit : ∫ θ in (0 : ℝ)..2 * π, R θ = + (∫ θ in (0 : ℝ)..2 * π, g (t₀ + circleMap 0 r θ)) - 2 * π * g t₀ - + (∫ θ in (0 : ℝ)..2 * π, D t₀ (circleMap 0 r θ)) - + ∫ θ in (0 : ℝ)..2 * π, (1 / 2 : ℝ) * B (circleMap 0 r θ) (circleMap 0 r θ) := by + simp only [hRdef] + rw [intervalIntegral.integral_sub ((hi₁.sub intervalIntegrable_const).sub hi₂) hi₃, + intervalIntegral.integral_sub (hi₁.sub intervalIntegrable_const) hi₂, + intervalIntegral.integral_sub hi₁ intervalIntegrable_const, intervalIntegral.integral_const] + simp [smul_eq_mul] + rw [integral_clm_circleMap_zero, intervalIntegral.integral_const_mul, integral_bilinear_circleMap, + sub_zero] at hsplit + have havg : circleAverage g t₀ r = (2 * π)⁻¹ * ∫ θ in (0 : ℝ)..2 * π, g (t₀ + circleMap 0 r θ) + := by + rw [circleAverage_def, smul_eq_mul] + simp only [hmap] + have hlap : Δ g t₀ = B 1 1 + B I I := laplacian_eq_fderiv_fderiv g t₀ + have hkey : circleAverage g t₀ r - g t₀ - r ^ 2 / 4 * Δ g t₀ = + (2 * π)⁻¹ * ∫ θ in (0 : ℝ)..2 * π, R θ := by + rw [havg, hlap, hsplit] + field_simp + ring + rw [hkey, abs_mul, abs_of_pos (inv_pos.mpr Real.two_pi_pos)] + calc (2 * π)⁻¹ * |∫ θ in (0 : ℝ)..2 * π, R θ| ≤ (2 * π)⁻¹ * (ε * r ^ 2 * (2 * π)) := + mul_le_mul_of_nonneg_left hRint (inv_pos.mpr Real.two_pi_pos).le + _ = ε * r ^ 2 := by field_simp + +/-- A positive Laplacian gives the strict submean inequality on all small circles. -/ +theorem eventually_lt_circleAverage_of_laplacian_pos (hg : ContDiffAt ℝ 2 g t₀) + (hΔ : 0 < Δ g t₀) : + ∀ᶠ r in 𝓝[>] (0 : ℝ), CircleIntegrable g t₀ r ∧ g t₀ < circleAverage g t₀ r := by + obtain ⟨δ, hδ, h⟩ := exists_circleAverage_sub_le hg (ε := Δ g t₀ / 8) (by positivity) + refine mem_nhdsGT_iff_exists_Ioo_subset.mpr ⟨δ, hδ, fun r hr => ?_⟩ + obtain ⟨hint, hle⟩ := h r hr.1 hr.2 + refine ⟨hint, ?_⟩ + have := (abs_le.mp hle).1 + nlinarith [sq_pos_of_pos hr.1] + +/-- A negative Laplacian gives the strict reverse inequality on all small circles. -/ +theorem eventually_circleAverage_lt_of_laplacian_neg (hg : ContDiffAt ℝ 2 g t₀) + (hΔ : Δ g t₀ < 0) : + ∀ᶠ r in 𝓝[>] (0 : ℝ), CircleIntegrable g t₀ r ∧ circleAverage g t₀ r < g t₀ := by + obtain ⟨δ, hδ, h⟩ := exists_circleAverage_sub_le hg (ε := -Δ g t₀ / 8) (by linarith) + refine mem_nhdsGT_iff_exists_Ioo_subset.mpr ⟨δ, hδ, fun r hr => ?_⟩ + obtain ⟨hint, hle⟩ := h r hr.1 hr.2 + refine ⟨hint, ?_⟩ + have := (abs_le.mp hle).2 + nlinarith [sq_pos_of_pos hr.1] + +/-- A `C²` function with positive Laplacian has the local submean property. -/ +theorem hasSubmeanAt_of_laplacian_pos (hg : ContDiffAt ℝ 2 g t₀) (hΔ : 0 < Δ g t₀) : + HasSubmeanAt g t₀ := + (eventually_lt_circleAverage_of_laplacian_pos hg hΔ).mono fun _ h => ⟨h.1, h.2.le⟩ + +/-- **Necessity.** A `C²` subharmonic function has nonnegative Laplacian. -/ +theorem HasSubmeanAt.laplacian_nonneg (hg : ContDiffAt ℝ 2 g t₀) (hs : HasSubmeanAt g t₀) : + 0 ≤ Δ g t₀ := by + by_contra hlt + push Not at hlt + obtain ⟨r, ⟨_, h₁⟩, ⟨_, h₂⟩⟩ := + ((eventually_circleAverage_lt_of_laplacian_neg hg hlt).and hs).exists + linarith + +/-- The Laplacian of the squared distance to a point is `4`. -/ +theorem laplacian_normSq_sub (t₀ t : ℂ) : Δ (fun z : ℂ => ‖z - t₀‖ ^ 2) t = 4 := by + have hq : (fun z : ℂ => ‖z - t₀‖ ^ 2) = fun z => (Complex.reCLM (z - t₀)) ^ 2 + + (Complex.imCLM (z - t₀)) ^ 2 := by + funext z + simp only [Complex.reCLM_apply, Complex.imCLM_apply, Complex.sq_norm, Complex.normSq_apply] + ring + have hD : ∀ z, HasFDerivAt (fun z : ℂ => ‖z - t₀‖ ^ 2) + ((2 * (z - t₀).re) • Complex.reCLM + (2 * (z - t₀).im) • Complex.imCLM) z := by + intro z + rw [hq] + have h1 : HasFDerivAt (fun z : ℂ => Complex.reCLM (z - t₀)) Complex.reCLM z := + Complex.reCLM.hasFDerivAt.comp z ((hasFDerivAt_id z).sub_const t₀) |>.congr_fderiv (by simp) + have h2 : HasFDerivAt (fun z : ℂ => Complex.imCLM (z - t₀)) Complex.imCLM z := + Complex.imCLM.hasFDerivAt.comp z ((hasFDerivAt_id z).sub_const t₀) |>.congr_fderiv (by simp) + have := (h1.pow 2).add (h2.pow 2) + convert this using 1 + ext s + simp [Complex.reCLM_apply, Complex.imCLM_apply] + have hfd : fderiv ℝ (fun z : ℂ => ‖z - t₀‖ ^ 2) = + fun z => (2 * (z - t₀).re) • Complex.reCLM + (2 * (z - t₀).im) • Complex.imCLM := + funext fun z => (hD z).fderiv + -- second derivative: differentiate the coefficient functions + have h1 : HasFDerivAt (fun z : ℂ => 2 * (z - t₀).re) ((2 : ℝ) • Complex.reCLM) t := by + have h := Complex.reCLM.hasFDerivAt.comp t ((hasFDerivAt_id t).sub_const t₀) + have := h.const_mul (2 : ℝ) + refine this.congr_fderiv ?_ + ext s + simp + have h2 : HasFDerivAt (fun z : ℂ => 2 * (z - t₀).im) ((2 : ℝ) • Complex.imCLM) t := by + have h := Complex.imCLM.hasFDerivAt.comp t ((hasFDerivAt_id t).sub_const t₀) + have := h.const_mul (2 : ℝ) + refine this.congr_fderiv ?_ + ext s + simp + have hD2 : HasFDerivAt (fun z : ℂ => (2 * (z - t₀).re) • Complex.reCLM + + (2 * (z - t₀).im) • Complex.imCLM) _ t := + (h1.smul_const Complex.reCLM).add (h2.smul_const Complex.imCLM) + rw [laplacian_eq_fderiv_fderiv, hfd, hD2.fderiv] + simp + norm_num + +/-- **Sufficiency.** A `C²` function with nonnegative Laplacian on an open set is subharmonic. -/ +theorem subharmonicOn_of_laplacian_nonneg {U : Set ℂ} (hU : IsOpen U) (hg : ContDiffOn ℝ 2 g U) + (hΔ : ∀ t ∈ U, 0 ≤ Δ g t) : SubharmonicOn g U := by + refine ⟨hg.continuousOn.upperSemicontinuousOn, fun a ha => ?_⟩ + obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) + refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ + have hsub : closedBall a r ⊆ U := (closedBall_subset_ball hrρ).trans hball + have hint : CircleIntegrable g a r := + (hg.continuousOn.mono (sphere_subset_closedBall.trans hsub)).circleIntegrable hr.le + refine ⟨hint, le_of_forall_pos_le_add fun ε hε => ?_⟩ + set η : ℝ := ε / r ^ 2 with hη + have hη0 : 0 < η := div_pos hε (by positivity) + -- the perturbed function + set q : ℂ → ℝ := fun z => ‖z - a‖ ^ 2 with hqdef + have hqc : ContDiff ℝ 2 q := by + have : q = fun z : ℂ => (Complex.reCLM (z - a)) ^ 2 + (Complex.imCLM (z - a)) ^ 2 := by + funext z + simp only [hqdef, Complex.reCLM_apply, Complex.imCLM_apply, Complex.sq_norm, + Complex.normSq_apply] + ring + rw [this] + fun_prop + set gε : ℂ → ℝ := fun z => g z + η * q z with hgεdef + have hgε : ContDiffOn ℝ 2 gε U := hg.add (hqc.contDiffOn.const_smul η |>.congr fun z _ => rfl) + have hΔε : ∀ t ∈ U, 0 < Δ gε t := by + intro t ht + have h1 : ContDiffAt ℝ 2 g t := hg.contDiffAt (hU.mem_nhds ht) + have h2 : ContDiffAt ℝ 2 (fun z => η * q z) t := by + have := hqc.contDiffAt (x := t) + exact this.const_smul η |>.congr_of_eventuallyEq (Filter.Eventually.of_forall fun z => rfl) + have hadd := ContDiffAt.laplacian_add h1 h2 + have hsm : Δ (fun z => η * q z) t = η * Δ q t := by + have := InnerProductSpace.laplacian_smul (𝕜 := ℝ) η (hqc.contDiffAt (x := t)) + simpa [Pi.smul_def, smul_eq_mul] using this + have hq4 : Δ q t = 4 := laplacian_normSq_sub a t + have : Δ gε t = Δ g t + η * 4 := by + rw [hgεdef] + change Δ (g + fun z => η * q z) t = _ + rw [hadd, hsm, hq4] + rw [this] + linarith [hΔ t ht] + have hsub_ε : SubharmonicOn gε U := + ⟨hgε.continuousOn.upperSemicontinuousOn, fun t ht => + hasSubmeanAt_of_laplacian_pos (hgε.contDiffAt (hU.mem_nhds ht)) (hΔε t ht)⟩ + have hmean := hsub_ε.le_circleAverage_of_continuousOn hgε.continuousOn hr hsub + have hqint : CircleIntegrable (fun z => η * q z) a r := + (continuous_const.mul (hqc.continuous)).continuousOn.circleIntegrable hr.le + have hqavg : circleAverage (fun z => η * q z) a r = η * r ^ 2 := by + rw [circleAverage_congr_sphere (f₂ := fun _ => η * r ^ 2), circleAverage_const] + intro z hz + simp only [hqdef] + rw [abs_of_pos hr] at hz + rw [mem_sphere, dist_eq_norm] at hz + rw [hz] + have havg : circleAverage gε a r = circleAverage g a r + η * r ^ 2 := by + rw [hgεdef, circleAverage_fun_add hint hqint, hqavg] + have hga : gε a = g a := by simp [hgεdef, hqdef] + rw [havg, hga] at hmean + have hηr : η * r ^ 2 = ε := by + rw [hη] + field_simp + rw [hηr] at hmean + exact hmean + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean new file mode 100644 index 0000000000..0e4fa616c9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean @@ -0,0 +1,13 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ + +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous + +/-! Supporting modules for Classical several complex variables. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/CompactExhaustion.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/CompactExhaustion.lean new file mode 100644 index 0000000000..254f7a0d4b --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/CompactExhaustion.lean @@ -0,0 +1,49 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Compactness.SigmaCompact + +/-! +# Compact exhaustions of open subsets + +## Main results + +* `IsOpen.exists_compact_exhaustion`: An open subset of a locally compact, second-countable + topological space has an increasing sequence of compact subsets containing every compact + subset of the open set in some term. The construction uses `CompactExhaustion.choice` on + the open subtype and maps its terms into the ambient space. + +In particular, the result applies to open subsets of proper metric spaces. No norm, group +structure, or nonemptiness assumption is needed. +-/ + +public section + +open Set + +/-- An open subset of a locally compact, second-countable space has an increasing compact +exhaustion containing each compact subset in some term. -/ +theorem IsOpen.exists_compact_exhaustion {E : Type*} [TopologicalSpace E] + [LocallyCompactSpace E] [SecondCountableTopology E] {U : Set E} (hU : IsOpen U) : + ∃ L : ℕ → Set E, (∀ k, IsCompact (L k)) ∧ (∀ k, L k ⊆ U) ∧ (∀ k, L k ⊆ L (k + 1)) ∧ + ∀ K, IsCompact K → K ⊆ U → ∃ k, K ⊆ L k := by + let : LocallyCompactSpace U := hU.locallyCompactSpace + let B := CompactExhaustion.choice U + refine ⟨fun k => Subtype.val '' B k, + fun k => (B.isCompact k).image continuous_subtype_val, + fun k z hz => ?_, fun k => image_mono (B.subset_succ k), fun K hK hKU => ?_⟩ + · obtain ⟨z, _, rfl⟩ := hz + exact z.property + · have hpre : IsCompact ((Subtype.val : U → E) ⁻¹' K) := by + apply Topology.IsEmbedding.subtypeVal.isCompact_iff.mpr + rwa [image_preimage_eq_of_subset (by simpa using hKU)] + obtain ⟨k, hk⟩ := B.exists_superset_of_isCompact hpre + exact ⟨k, fun z hz => ⟨⟨z, hKU hz⟩, hk hz, rfl⟩⟩ + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Frontier.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Frontier.lean new file mode 100644 index 0000000000..19631245f6 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Frontier.lean @@ -0,0 +1,28 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Closure + +/-! +# Frontier points of open sets + +## Main results + +* `IsOpen.notMem_of_mem_frontier`: A frontier point of an open set does not belong to the set. +-/ + +public section + +/-- A frontier point of an open set does not belong to the set. -/ +theorem IsOpen.notMem_of_mem_frontier {X : Type*} [TopologicalSpace X] {s : Set X} + (hs : IsOpen s) {x : X} (hx : x ∈ frontier s) : x ∉ s := by + rw [hs.frontier_eq] at hx + exact hx.2 + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Graph.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Graph.lean new file mode 100644 index 0000000000..650f635743 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Graph.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Constructions +public import Mathlib.Topology.ContinuousOn +public import Mathlib.Topology.Homeomorph.Defs + +/-! +# Graphs characterized by equations + +An equation determining a unique fiber value gives uniqueness of solution maps. For a continuous +solution, projection from the zero set is a homeomorphism onto its parameter domain. Neither +result requires differentiability. + +## Main definitions + +* `Homeomorph.implicitGraph`: A continuous graph characterization makes projection a homeomorphism. + +## Main results + +* `Set.eqOn_of_forall_mem_eq_iff`: A graph characterization gives uniqueness among all solution maps + staying in the specified fiber neighborhood; no regularity assumption on the competing solution is + needed. +-/ + +public section +open Set +variable {P Q R : Type*} + +/-- A graph characterization gives uniqueness among all solution maps staying in the specified fiber +neighborhood; no regularity assumption on the competing solution is needed. -/ +theorem Set.eqOn_of_forall_mem_eq_iff {U : Set P} {V : Set Q} {f : P × Q → R} {c : R} + {g h : P → Q} (hgraph : ∀ x ∈ U, ∀ y ∈ V, f (x, y) = c ↔ y = g x) + (hh : MapsTo h U V) (hsol : ∀ x ∈ U, f (x, h x) = c) : EqOn h g U := + fun x hx => (hgraph x hx (h x) (hh hx)).mp (hsol x hx) + +variable [TopologicalSpace P] [TopologicalSpace Q] [Zero R] + +/-- A continuous graph characterization makes projection a homeomorphism. -/ +@[expose] def Homeomorph.implicitGraph {U : Set P} {V : Set Q} {f : P × Q → R} {g : P → Q} + (hg : ContinuousOn g U) (hm : MapsTo g U V) + (hgraph : ∀ x ∈ U, ∀ y ∈ V, f (x, y) = 0 ↔ y = g x) : + {p : P × Q // p ∈ U ×ˢ V ∧ f p = 0} ≃ₜ U where + toFun p := ⟨p.val.1, p.property.1.1⟩ + invFun x := ⟨(x.val, g x), ⟨⟨x.property, hm x.property⟩, + (hgraph x x.property (g x) (hm x.property)).mpr rfl⟩⟩ + left_inv p := by + apply Subtype.ext + change (p.val.1, g p.val.1) = p.val + apply Prod.ext + · rfl + · exact ((hgraph p.val.1 p.property.1.1 p.val.2 p.property.1.2).mp p.property.2).symm + right_inv x := rfl + continuous_toFun := (continuous_fst.comp continuous_subtype_val).subtype_mk _ + continuous_invFun := (continuous_subtype_val.prodMk hg.domRestrict).subtype_mk _ + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Path.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Path.lean new file mode 100644 index 0000000000..426e71627c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/Path.lean @@ -0,0 +1,46 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Order.Basic +public import Mathlib.Topology.Path + +/-! +# First exit of a path from an open set + +A path starting inside an open set and ending outside it has a positive first exit time. The +path is extended to real parameters using Mathlib’s `Path.extend`. + +## Main results + +* `Path.extend_exists_first_notMem`: First time a path starting in an open set leaves that set. +-/ + +public section + +open Set + +/-- First time a path starting in an open set leaves that set. -/ +theorem Path.extend_exists_first_notMem {X : Type*} [TopologicalSpace X] {x y : X} + (γ : Path x y) {A : Set X} (hA : IsOpen A) + (hx : γ.extend 0 ∈ A) (hy : γ.extend 1 ∉ A) : + ∃ t, t ∈ Icc (0 : ℝ) 1 ∧ γ.extend t ∉ A ∧ 0 < t ∧ + ∀ s, 0 ≤ s → s < t → γ.extend s ∈ A := by + set S : Set ℝ := Icc (0 : ℝ) 1 ∩ γ.extend ⁻¹' Aᶜ + have hSc : IsClosed S := isClosed_Icc.inter (hA.isClosed_compl.preimage γ.continuous_extend) + have hSne : S.Nonempty := ⟨1, ⟨zero_le_one, le_rfl⟩, hy⟩ + have hSbdd : BddBelow S := ⟨0, fun t ht => ht.1.1⟩ + have hsS : sInf S ∈ S := hSc.csInf_mem hSne hSbdd + have hs01 : sInf S ∈ Icc (0 : ℝ) 1 := hsS.1 + have h0S : (0 : ℝ) ∉ S := fun h => h.2 hx + have hs0 : 0 < sInf S := lt_of_le_of_ne hs01.1 fun h => h0S (h ▸ hsS) + refine ⟨sInf S, hs01, hsS.2, hs0, fun s hs0' hst => ?_⟩ + by_contra h + exact notMem_of_lt_csInf hst hSbdd ⟨⟨hs0', hst.le.trans hs01.2⟩, h⟩ + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/UpperSemicontinuous.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/UpperSemicontinuous.lean new file mode 100644 index 0000000000..499eca7be7 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology/UpperSemicontinuous.lean @@ -0,0 +1,35 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Algebra.Order.Field +public import Mathlib.Topology.Semicontinuity.Basic + +/-! +# Nonnegative multiples of upper semicontinuous functions + +Multiplication by a nonnegative real constant preserves upper semicontinuity on a set. + +## Main results + +* `UpperSemicontinuousOn.const_mul`: Nonnegative multiples of upper semicontinuous functions are + upper semicontinuous. +-/ + +public section + +open Set + +/-- Nonnegative multiples of upper semicontinuous functions are upper semicontinuous. -/ +theorem UpperSemicontinuousOn.const_mul {X : Type*} [TopologicalSpace X] {f : X → ℝ} {s : Set X} + {c : ℝ} (hf : UpperSemicontinuousOn f s) (hc : 0 ≤ c) : + UpperSemicontinuousOn (fun x => c * f x) s := fun z hz => + (continuous_const.mul continuous_id).continuousAt.comp_upperSemicontinuousWithinAt + (hf z hz) (fun _ _ hxy => mul_le_mul_of_nonneg_left hxy hc) + +end + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean new file mode 100644 index 0000000000..8cefb0bdcc --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Convex.Topology +public import Mathlib.Analysis.Normed.Module.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner + +/-! +# Tube domains and Bochner's tube theorem + +The tube over a real base consists of complex points whose real parts belong to that base. The +tube theorem extends functions to the tube over the real convex hull, inside the same complex +coordinate space. No abstract envelope is constructed. Connectedness of the base is essential to +the extension theorem. Banach-valued targets and empty coordinate types are retained. A +preconnected empty base is handled separately. + +Bochner extension is proved by [Hörmander][Hormander1973]'s argument: the maximal star-convex +extension tube is convex by the parabolic disc hull lemma and Thullen's continuation lemma, and +a path argument handles connected bases (`TubeDomain/Bochner`). The statement for a general +finite index type is obtained by reindexing. Uniqueness of extensions and the convex-base +characterization of tube domains of holomorphy follow. + +References: [Scheidemann][Scheidemann2005] §6.3; [Hörmander][Hormander1973] §2.5, Theorem +2.5.10. + +## Main results + +* `exists_extension_tubeDomain_convexHull`: **Bochner's tube theorem.** Every Banach-valued + holomorphic function on a tube with preconnected open base extends to the tube over its real + convex hull. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} + +variable [Fintype ι] + +/-- Bochner extension for a nonempty connected base, obtained by reindexing the coordinate +proof. This is the prerequisite for the empty-inclusive public theorem below. -/ +private theorem exists_extension_tubeDomain_convexHull_nonempty {F : Type*} [NormedAddCommGroup F] + [NormedSpace ℂ F] [CompleteSpace F] {Ω : Set (ι → ℝ)} + (ho : IsOpen Ω) (hc : IsConnected Ω) {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f (tubeDomain Ω)) : + ∃ g : (ι → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω)) ∧ + EqOn g f (tubeDomain Ω) := by + set e := Fintype.equivFin ι with he + set L : (ι → ℝ) →ₗ[ℝ] (Fin (Fintype.card ι) → ℝ) := LinearMap.funLeft ℝ ℝ e.symm with hL + have hLapply : ∀ x : ι → ℝ, L x = x ∘ e.symm := fun x => rfl + have himg : L '' Ω = (fun x' : Fin (Fintype.card ι) → ℝ => x' ∘ e) ⁻¹' Ω := by + ext x' + constructor + · rintro ⟨x, hx, rfl⟩ + simpa [hLapply, Function.comp_assoc] using hx + · intro hx' + refine ⟨x' ∘ e, hx', ?_⟩ + rw [hLapply, Function.comp_assoc, e.self_comp_symm, Function.comp_id] + have hΩ'o : IsOpen (L '' Ω) := by + rw [himg] + exact ho.preimage (continuous_pi fun i => continuous_apply (e i)) + have hΩ'c : IsConnected (L '' Ω) := + hc.image L (continuous_pi fun j => continuous_apply (e.symm j)).continuousOn + have hre : ∀ (z : ι → ℂ), rePi (z ∘ e.symm) = L (rePi z) := fun z => rfl + have hre' : ∀ (z' : Fin (Fintype.card ι) → ℂ), rePi (z' ∘ e) = rePi z' ∘ e := fun z' => rfl + -- the reindexing maps are analytic + have hM : AnalyticOnNhd ℂ (fun z' : Fin (Fintype.card ι) → ℂ => z' ∘ e) univ := + (LinearMap.toContinuousLinearMap (LinearMap.funLeft ℂ ℂ e)).analyticOnNhd univ + have hM' : AnalyticOnNhd ℂ (fun z : ι → ℂ => z ∘ e.symm) univ := + (LinearMap.toContinuousLinearMap (LinearMap.funLeft ℂ ℂ e.symm)).analyticOnNhd univ + have hmaps : MapsTo (fun z' : Fin (Fintype.card ι) → ℂ => z' ∘ e) (tubeDomain (L '' Ω)) + (tubeDomain Ω) := by + intro z' hz' + rw [mem_tubeDomain, himg] at hz' + rw [mem_tubeDomain, hre'] + exact hz' + have hf' : AnalyticOnNhd ℂ (fun z' => f (z' ∘ e)) (tubeDomain (L '' Ω)) := + hf.comp (hM.mono (subset_univ _)) hmaps + obtain ⟨g', hg', hg'f⟩ := exists_extension_tubeDomain_convexHull_fin hΩ'o hΩ'c hf' + have hconv : L '' convexHull ℝ Ω = convexHull ℝ (L '' Ω) := LinearMap.image_convexHull L Ω + have hmaps' : MapsTo (fun z : ι → ℂ => z ∘ e.symm) (tubeDomain (convexHull ℝ Ω)) + (tubeDomain (convexHull ℝ (L '' Ω))) := by + intro z hz + rw [mem_tubeDomain, hre, ← hconv] + exact mem_image_of_mem L hz + refine ⟨fun z => g' (z ∘ e.symm), hg'.comp (hM'.mono (subset_univ _)) hmaps', fun z hz => ?_⟩ + have hz' : z ∘ e.symm ∈ tubeDomain (L '' Ω) := by + rw [mem_tubeDomain, hre] + exact mem_image_of_mem L hz + show g' (z ∘ e.symm) = f z + rw [hg'f hz'] + simp only [Function.comp_assoc, e.symm_comp_self, Function.comp_id] + +/-- **Bochner's tube theorem.** Every Banach-valued holomorphic function on a tube with +preconnected open base extends to the tube over its real convex hull. -/ +theorem exists_extension_tubeDomain_convexHull {F : Type*} [NormedAddCommGroup F] + [NormedSpace ℂ F] [CompleteSpace F] {Ω : Set (ι → ℝ)} + (ho : IsOpen Ω) (hc : IsPreconnected Ω) {f : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f (tubeDomain Ω)) : + ∃ g : (ι → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω)) ∧ + EqOn g f (tubeDomain Ω) := by + by_cases hn : Ω.Nonempty + · exact exists_extension_tubeDomain_convexHull_nonempty ho ⟨hn, hc⟩ hf + · have hΩ : Ω = ∅ := Set.not_nonempty_iff_eq_empty.mp hn + subst Ω + exact ⟨f, by simp [tubeDomain], by simp [tubeDomain]⟩ + +/-- Uniqueness of a tube extension to the convexified base, independently of Bochner's existence +theorem. Only a nonempty open original base is needed. -/ +theorem eqOn_of_tubeDomain_extension {F : Type*} [NormedAddCommGroup F] + [NormedSpace ℂ F] [CompleteSpace F] {Ω : Set (ι → ℝ)} + (ho : IsOpen Ω) (hn : Ω.Nonempty) {f g : (ι → ℂ) → F} + (hf : AnalyticOnNhd ℂ f (tubeDomain (convexHull ℝ Ω))) + (hg : AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω))) + (he : EqOn f g (tubeDomain Ω)) : EqOn f g (tubeDomain (convexHull ℝ Ω)) := by + obtain ⟨a, ha⟩ := nonempty_tubeDomain hn + apply hf.eqOn_of_preconnected_of_eventuallyEq hg + (convex_tubeDomain (convex_convexHull ℝ Ω)).isPreconnected + (tubeDomain_subset_convexHull_base Ω ha) + filter_upwards [(isOpen_tubeDomain ho).mem_nhds ha] with z hz + exact he hz + +/-- The convexified tube is a common scalar extension domain, by Bochner's extension theorem, +without asserting a universal abstract envelope property. -/ +theorem isCommonAnalyticExtension_tubeDomain_convexHull {Ω : Set (ι → ℝ)} + (ho : IsOpen Ω) (hc : IsPreconnected Ω) : + IsCommonAnalyticExtension (tubeDomain Ω) (tubeDomain (convexHull ℝ Ω)) := + isCommonAnalyticExtension_of_forall (tubeDomain_subset_convexHull_base Ω) + (fun _ hf => exists_extension_tubeDomain_convexHull ho hc hf) + +/-- A tube with preconnected open base is a domain of holomorphy exactly when its base is convex. +The forward implication uses Bochner's extension theorem. -/ +theorem isDomainOfHolomorphy_tubeDomain_iff {Ω : Set (ι → ℝ)} + (ho : IsOpen Ω) (hc : IsPreconnected Ω) : + IsDomainOfHolomorphy (tubeDomain Ω) ↔ Convex ℝ Ω := by + by_cases hn : Ω.Nonempty + swap + · have hΩ : Ω = ∅ := Set.not_nonempty_iff_eq_empty.mp hn + subst Ω + exact ⟨fun _ => convex_empty, fun _ => + isDomainOfHolomorphy_of_convex (convex_tubeDomain convex_empty) (isOpen_tubeDomain ho)⟩ + constructor + · intro h + have he := h.eq_of_commonExtension (isOpen_tubeDomain ho) (nonempty_tubeDomain hn) + (isOpen_tubeDomain (ho.convexHull (𝕜 := ℝ))) + ⟨(nonempty_tubeDomain hn).mono (tubeDomain_subset_convexHull_base Ω), + (convex_tubeDomain (convex_convexHull ℝ Ω)).isPreconnected⟩ + (isCommonAnalyticExtension_tubeDomain_convexHull ho hc) + have heq : convexHull ℝ Ω = Ω := by + apply Subset.antisymm _ (_root_.subset_convexHull ℝ Ω) + intro x hx + apply ofReal_mem_tubeDomain.mp + rw [← he] + exact ofReal_mem_tubeDomain.mpr hx + rw [← heq] + exact convex_convexHull ℝ Ω + · intro h + exact isDomainOfHolomorphy_of_convex (convex_tubeDomain h) (isOpen_tubeDomain ho) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean new file mode 100644 index 0000000000..e8fd1645e9 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean @@ -0,0 +1,231 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.Convex.Topology +public import Mathlib.Analysis.Normed.Module.Connected +public import Mathlib.Topology.Connected.PathConnected + +/-! +# Tube domains: definition and elementary geometry + +The tube over a real base consists of complex points whose real parts belong to that base. This +file contains the definition, the real and imaginary coordinate projections, and elementary +facts: tubes over open, convex or preconnected bases are open, convex or preconnected, tubes are +invariant under imaginary translations, and sup-norm balls around a point of a tube lie in the +tube when the corresponding real ball lies in the base. + +References: [Scheidemann][Scheidemann2005] §6.1; [Hörmander][Hormander1973] §2.5, Definition +2.5.9. + +## Notation + +`tubeDomain Ω` is the set of points of `ι → ℂ` whose real parts lie in `Ω`. `rePi`, `imPi`, and +`ofRealPi` are the real-part, imaginary-part, and complexification maps. + +## Main results + +`isOpen_tubeDomain`, `convex_tubeDomain`, and `isPreconnected_tubeDomain` transport openness, +convexity, and preconnectedness from the base. `tubeDomain_union` and `tubeDomain_inter` commute +with unions and intersections. `ball_subset_tubeDomain` places a sup-norm ball in the tube when +the corresponding real ball lies in the base. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Complex +open scoped Topology + +namespace SeveralComplexVariables + +variable {ι : Type*} + +/-- The tube over a real coordinate set; imaginary coordinates are unrestricted. -/ +@[expose] def tubeDomain (Ω : Set (ι → ℝ)) : Set (ι → ℂ) := + {z | (fun i => (z i).re) ∈ Ω} + +/-- The real part of a complex coordinate vector. -/ +@[expose] def rePi (z : ι → ℂ) : ι → ℝ := fun i => (z i).re + +/-- The imaginary part of a complex coordinate vector. -/ +@[expose] def imPi (z : ι → ℂ) : ι → ℝ := fun i => (z i).im + +/-- A real coordinate vector as a complex coordinate vector. -/ +@[expose] def ofRealPi (x : ι → ℝ) : ι → ℂ := fun i => (x i : ℂ) + +/-- Membership in a tube is membership of the real part in the base. -/ +theorem mem_tubeDomain {Ω : Set (ι → ℝ)} {z : ι → ℂ} : z ∈ tubeDomain Ω ↔ rePi z ∈ Ω := Iff.rfl + +/-- The real part of a real vector is the vector. -/ +@[simp] theorem rePi_ofRealPi (x : ι → ℝ) : rePi (ofRealPi x) = x := by + funext i; simp [rePi, ofRealPi] + +/-- A real vector has zero imaginary part. -/ +@[simp] theorem imPi_ofRealPi (x : ι → ℝ) : imPi (ofRealPi x) = 0 := by + funext i; simp [imPi, ofRealPi] + +/-- The real part is additive. -/ +@[simp] theorem rePi_add (z w : ι → ℂ) : rePi (z + w) = rePi z + rePi w := by + funext i; simp [rePi] + +/-- The real part respects differences. -/ +@[simp] theorem rePi_sub (z w : ι → ℂ) : rePi (z - w) = rePi z - rePi w := by + funext i; simp [rePi] + +/-- A purely imaginary vector has zero real part. -/ +@[simp] theorem rePi_I_smul_ofRealPi (y : ι → ℝ) : rePi (I • ofRealPi y) = 0 := by + funext i; simp [rePi, ofRealPi] + +/-- The real part commutes with real scalars. -/ +@[simp] theorem rePi_real_smul (t : ℝ) (z : ι → ℂ) : rePi (t • z) = t • rePi z := by + funext i; simp [rePi, Complex.real_smul] + +/-- Complexification is additive. -/ +theorem ofRealPi_add (x y : ι → ℝ) : ofRealPi (x + y) = ofRealPi x + ofRealPi y := by + funext i; simp [ofRealPi] + +/-- Complexification respects differences. -/ +theorem ofRealPi_sub (x y : ι → ℝ) : ofRealPi (x - y) = ofRealPi x - ofRealPi y := by + funext i; simp [ofRealPi] + +/-- Complexification commutes with real scalars. -/ +theorem ofRealPi_smul (t : ℝ) (x : ι → ℝ) : ofRealPi (t • x) = t • ofRealPi x := by + funext i; simp [ofRealPi, Complex.real_smul] + +/-- The complexification of zero is zero. -/ +@[simp] theorem ofRealPi_zero : ofRealPi (0 : ι → ℝ) = 0 := by + funext i; simp [ofRealPi] + +/-- Real and imaginary parts recover a complex coordinate vector. -/ +theorem ofRealPi_rePi_add_I_smul_ofRealPi_imPi (z : ι → ℂ) : + ofRealPi (rePi z) + I • ofRealPi (imPi z) = z := by + funext i + simp only [Pi.add_apply, ofRealPi, rePi, imPi, Pi.smul_apply, smul_eq_mul] + rw [mul_comm] + exact Complex.re_add_im (z i) + +/-- A real point belongs to a tube exactly when it belongs to the base. -/ +@[simp] theorem ofReal_mem_tubeDomain {Ω : Set (ι → ℝ)} {x : ι → ℝ} : + (fun i => (x i : ℂ)) ∈ tubeDomain Ω ↔ x ∈ Ω := by simp [tubeDomain] + +/-- A real vector lies in a tube exactly when it lies in the base. -/ +@[simp] theorem ofRealPi_mem_tubeDomain {Ω : Set (ι → ℝ)} {x : ι → ℝ} : + ofRealPi x ∈ tubeDomain Ω ↔ x ∈ Ω := ofReal_mem_tubeDomain + +/-- Tubes are invariant under imaginary translations. -/ +theorem add_I_smul_ofRealPi_mem_tubeDomain {Ω : Set (ι → ℝ)} {z : ι → ℂ} (y : ι → ℝ) : + z + I • ofRealPi y ∈ tubeDomain Ω ↔ z ∈ tubeDomain Ω := by + simp [mem_tubeDomain] + +/-- Tubes are monotone in their real bases. -/ +theorem tubeDomain_mono {Ω Ξ : Set (ι → ℝ)} (h : Ω ⊆ Ξ) : tubeDomain Ω ⊆ tubeDomain Ξ := + fun _ hz => h hz + +/-- Tubes commute with intersections of bases. -/ +theorem tubeDomain_inter (Ω Ξ : Set (ι → ℝ)) : + tubeDomain (Ω ∩ Ξ) = tubeDomain Ω ∩ tubeDomain Ξ := rfl + +/-- Tubes commute with unions of bases. -/ +theorem tubeDomain_union (Ω Ξ : Set (ι → ℝ)) : + tubeDomain (Ω ∪ Ξ) = tubeDomain Ω ∪ tubeDomain Ξ := rfl + +/-- Tubes commute with unions of families of bases. -/ +theorem tubeDomain_sUnion (S : Set (Set (ι → ℝ))) : + tubeDomain (⋃₀ S) = ⋃ Ω ∈ S, tubeDomain Ω := by + ext z; simp [mem_tubeDomain] + +/-- The tube over the empty base is empty. -/ +@[simp] theorem tubeDomain_empty : tubeDomain (∅ : Set (ι → ℝ)) = ∅ := rfl + +/-- The tube over the whole real space is the whole complex space. -/ +@[simp] theorem tubeDomain_univ : tubeDomain (univ : Set (ι → ℝ)) = univ := rfl + +/-- A nonempty real base has a nonempty tube. -/ +theorem nonempty_tubeDomain {Ω : Set (ι → ℝ)} (h : Ω.Nonempty) : (tubeDomain Ω).Nonempty := by + obtain ⟨x, hx⟩ := h + exact ⟨fun i => (x i : ℂ), ofReal_mem_tubeDomain.mpr hx⟩ + +/-- The real-part projection is continuous. -/ +@[fun_prop] theorem continuous_rePi : Continuous (rePi : (ι → ℂ) → ι → ℝ) := by + unfold rePi; fun_prop + +/-- The imaginary-part projection is continuous. -/ +@[fun_prop] theorem continuous_imPi : Continuous (imPi : (ι → ℂ) → ι → ℝ) := by + unfold imPi; fun_prop + +/-- Complexification is continuous. -/ +@[fun_prop] theorem continuous_ofRealPi : Continuous (ofRealPi : (ι → ℝ) → ι → ℂ) := by + unfold ofRealPi; fun_prop + +/-- The tube over an open base is open. -/ +theorem isOpen_tubeDomain {Ω : Set (ι → ℝ)} (ho : IsOpen Ω) : IsOpen (tubeDomain Ω) := + ho.preimage (by fun_prop) + +/-- Real convexity of the base implies real convexity of its tube. -/ +theorem convex_tubeDomain {Ω : Set (ι → ℝ)} (hc : Convex ℝ Ω) : Convex ℝ (tubeDomain Ω) := by + intro x hx y hy a b ha hb hab + have h := hc hx hy ha hb hab + simpa [tubeDomain, Pi.smul_def, Pi.add_def, smul_eq_mul] using h + +/-- Every tube is contained in the tube over the convex hull of its base. -/ +theorem tubeDomain_subset_convexHull_base (Ω : Set (ι → ℝ)) : + tubeDomain Ω ⊆ tubeDomain (convexHull ℝ Ω) := tubeDomain_mono (_root_.subset_convexHull ℝ Ω) + +/-- A tube is the image of the product of its base with the imaginary coordinate space. -/ +theorem tubeDomain_eq_image (Ω : Set (ι → ℝ)) : + tubeDomain Ω = (fun p : (ι → ℝ) × (ι → ℝ) => ofRealPi p.1 + I • ofRealPi p.2) '' + (Ω ×ˢ univ) := by + ext z + constructor + · intro hz + refine ⟨(rePi z, imPi z), ⟨hz, mem_univ _⟩, ?_⟩ + exact ofRealPi_rePi_add_I_smul_ofRealPi_imPi z + · rintro ⟨⟨x, y⟩, ⟨hx, -⟩, rfl⟩ + simpa [mem_tubeDomain] using hx + +/-- The tube over a preconnected base is preconnected. -/ +theorem isPreconnected_tubeDomain {Ω : Set (ι → ℝ)} (h : IsPreconnected Ω) : + IsPreconnected (tubeDomain Ω) := by + rw [tubeDomain_eq_image] + exact (h.prod isPreconnected_univ).image _ (by fun_prop : Continuous fun p : (ι → ℝ) × (ι → ℝ) => + ofRealPi p.1 + I • ofRealPi p.2).continuousOn + +section Norms + +variable [Fintype ι] + +/-- Complexification preserves the supremum norm. -/ +theorem norm_ofRealPi (x : ι → ℝ) : ‖ofRealPi x‖ = ‖x‖ := by + simp [ofRealPi, Pi.norm_def] + +/-- The real part does not increase the supremum norm. -/ +theorem norm_rePi_le (z : ι → ℂ) : ‖rePi z‖ ≤ ‖z‖ := by + rw [pi_norm_le_iff_of_nonneg (norm_nonneg _)] + intro i + exact (Complex.abs_re_le_norm (z i)).trans (norm_le_pi_norm z i) + +/-- A sup-norm ball around a point of a tube lies in the tube when the real ball around its real +part lies in the base. -/ +theorem ball_subset_tubeDomain {Ω : Set (ι → ℝ)} {z : ι → ℂ} {r : ℝ} + (h : Metric.ball (rePi z) r ⊆ Ω) : Metric.ball z r ⊆ tubeDomain Ω := by + intro w hw + apply h + rw [Metric.mem_ball, dist_eq_norm] at hw ⊢ + show ‖rePi w - rePi z‖ < r + rw [← rePi_sub] + exact (norm_rePi_le _).trans_lt hw + +end Norms + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Bochner.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Bochner.lean new file mode 100644 index 0000000000..111989ea04 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Bochner.lean @@ -0,0 +1,170 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Topology.Connected.LocallyPathConnected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex + +/-! +# Bochner's tube theorem for connected bases in coordinates + +Let `Ω ⊆ ℝⁿ` be open and connected, `p ∈ Ω`, and let `Ã` be the maximal star-convex extension +base with respect to `p`, which is convex. If `Ω` were not contained in `Ã`, a path in `Ω` from +`p` would leave `Ã` at a first point `x₁ ∈ Ω ∩ ∂Ã`. Every extension agrees with the original +function near the path points before `x₁`, by propagation of local agreement along the path, +hence on the tube over the convex set `à ∩ B(x₁, r)`. The two functions therefore define a +holomorphic function on the tube over `à ∪ B(x₁, r)`, which is star-convex with respect to `x₁`; +the star-convex case of the theorem extends it to the tube over the convex hull, which belongs +to the family, contradicting maximality. Hence `Ω ⊆ Ã`, and the extension to the tube over the +convex hull of `Ω` follows. + +References: [Hörmander][Hormander1973] §2.5, Theorem 2.5.10 (b); [Scheidemann][Scheidemann2005] +§6.3, Theorem 6.3.1, Step 2. + +## Main results + +* `exists_extension_tubeDomain_convexHull_fin`: **Bochner's tube theorem in coordinates.** Every + Banach-valued holomorphic function on the tube over an open connected base in `ℝⁿ` extends to the + tube over the convex hull. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric Complex +open scoped Topology + +namespace SeveralComplexVariables + +open BochnerTube + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- The union of an open convex set with a ball around a point of its closure is star-convex with +respect to that point. -/ +theorem starConvex_union_ball_of_mem_closure {A : Set (Fin n → ℝ)} (hA : Convex ℝ A) + (hAo : IsOpen A) {x : Fin n → ℝ} (hx : x ∈ closure A) {r : ℝ} (hr : 0 < r) : + StarConvex ℝ x (A ∪ ball x r) := by + intro y hy a b ha hb hab + rcases hy with hyA | hyB + · rcases ha.lt_or_eq with ha' | ha' + · rcases hb.lt_or_eq with hb' | hb' + · left + have hmem : a • x + b • y ∈ openSegment ℝ x y := ⟨a, b, ha', hb', hab, rfl⟩ + have hint := hA.openSegment_closure_interior_subset_interior hx + (by rwa [hAo.interior_eq] : y ∈ interior A) hmem + rwa [hAo.interior_eq] at hint + · right + subst hb' + rw [add_zero] at hab + rw [zero_smul, add_zero, hab, one_smul] + exact mem_ball_self hr + · left + subst ha' + rw [zero_add] at hab + rw [zero_smul, zero_add, hab, one_smul] + exact hyA + · right + exact (convex_ball x r) (mem_ball_self hr) hyB ha hb hab + +/-- **Bochner's tube theorem in coordinates.** Every Banach-valued holomorphic function on the +tube over an open connected base in `ℝⁿ` extends to the tube over the convex hull. -/ +theorem exists_extension_tubeDomain_convexHull_fin {Ω : Set (Fin n → ℝ)} (hΩ : IsOpen Ω) + (hc : IsConnected Ω) {f : (Fin n → ℂ) → F} (hf : AnalyticOnNhd ℂ f (tubeDomain Ω)) : + ∃ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω)) ∧ + EqOn g f (tubeDomain Ω) := by + classical + obtain ⟨p, hp⟩ := hc.nonempty + obtain ⟨r, hr, hrΩ⟩ := Metric.isOpen_iff.mp hΩ p hp + have hpà : p ∈ maxStar F Ω p := mem_maxStar_of_ball hr hrΩ + have hÃo : IsOpen (maxStar F Ω p) := isOpen_maxStar + have hÃc : Convex ℝ (maxStar F Ω p) := convex_maxStar hpà + have hΩà : Ω ⊆ maxStar F Ω p := by + by_contra hnot + obtain ⟨x₀, hx₀Ω, hx₀⟩ := not_subset.mp hnot + obtain ⟨γ, hγ⟩ := (hΩ.isConnected_iff_isPathConnected.mp hc).joinedIn p hp x₀ hx₀Ω + have hγΩ : ∀ t, γ.extend t ∈ Ω := by + intro t + have hmem : γ.extend t ∈ range γ.extend := mem_range_self t + rw [Path.extend_range] at hmem + obtain ⟨u, hu⟩ := hmem + rw [← hu] + exact hγ u + obtain ⟨t₁, ht₁I, hx₁, hs0, hprefix⟩ := + Path.extend_exists_first_notMem γ hÃo (by rw [Path.extend_zero]; exact hpÃ) + (by rw [Path.extend_one]; exact hx₀) + have hx₁Ω : γ.extend t₁ ∈ Ω := hγΩ _ + have htend : Tendsto γ.extend (𝓝[<] t₁) (𝓝 (γ.extend t₁)) := + (γ.continuous_extend.tendsto _).mono_left nhdsWithin_le_nhds + have hx₁cl : γ.extend t₁ ∈ closure (maxStar F Ω p) := by + apply mem_closure_of_tendsto htend + filter_upwards [Ioo_mem_nhdsLT hs0] with t ht + exact hprefix t ht.1.le ht.2 + obtain ⟨r₁, hr₁, hr₁Ω⟩ := Metric.isOpen_iff.mp hΩ _ hx₁Ω + have hev : ∀ᶠ t in 𝓝[<] t₁, γ.extend t ∈ ball (γ.extend t₁) r₁ := + htend (isOpen_ball.mem_nhds (mem_ball_self hr₁)) + obtain ⟨t₀, ht₀, ht₀ball⟩ := Filter.nonempty_of_mem (Filter.inter_mem (Ioo_mem_nhdsLT hs0) hev) + have ht₀à : γ.extend t₀ ∈ maxStar F Ω p := hprefix t₀ ht₀.1.le ht₀.2 + have hA₁o : IsOpen (maxStar F Ω p ∪ ball (γ.extend t₁) r₁) := hÃo.union isOpen_ball + have hA₁s : StarConvex ℝ (γ.extend t₁) (maxStar F Ω p ∪ ball (γ.extend t₁) r₁) := + starConvex_union_ball_of_mem_closure hÃc hÃo hx₁cl hr₁ + have hx₁A₁ : γ.extend t₁ ∈ maxStar F Ω p ∪ ball (γ.extend t₁) r₁ := + Or.inr (mem_ball_self hr₁) + have hBmem : convexHull ℝ (maxStar F Ω p ∪ ball (γ.extend t₁) r₁) ∈ starFamily F Ω p := by + refine ⟨hA₁o.convexHull, (convex_convexHull ℝ _).starConvex + (subset_convexHull ℝ _ (Or.inl hpÃ)), ?_⟩ + intro f₀ hf₀ + obtain ⟨g₀, hg₀, hg₀f⟩ := tubeExtends_maxStar hpà f₀ hf₀ + have hK : IsPreconnected ((fun t => ofRealPi (γ.extend t)) '' Icc 0 t₀) := + isPreconnected_Icc.image _ + (by fun_prop : Continuous fun t => ofRealPi (γ.extend t)).continuousOn + have hKU : (fun t => ofRealPi (γ.extend t)) '' Icc 0 t₀ ⊆ tubeDomain (Ω ∩ maxStar F Ω p) := by + rintro _ ⟨t, ht, rfl⟩ + rw [ofRealPi_mem_tubeDomain] + exact ⟨hγΩ t, hprefix t ht.1 (ht.2.trans_lt ht₀.2)⟩ + have hnear : g₀ =ᶠ[𝓝 (ofRealPi (γ.extend t₀))] f₀ := by + refine eventuallyEq_of_isPreconnected (isOpen_tubeDomain (hΩ.inter hÃo)) + (hf₀.mono (tubeDomain_mono inter_subset_left)) + (hg₀.mono (tubeDomain_mono inter_subset_right)) hK hKU + ⟨0, ⟨le_rfl, ht₀.1.le⟩, ?_⟩ hg₀f ⟨t₀, ⟨ht₀.1.le, le_rfl⟩, rfl⟩ + simp + have hAB : EqOn g₀ f₀ (tubeDomain (maxStar F Ω p ∩ ball (γ.extend t₁) r₁)) := by + have hpt : γ.extend t₀ ∈ maxStar F Ω p ∩ ball (γ.extend t₁) r₁ := ⟨ht₀Ã, ht₀ball⟩ + exact (hg₀.mono (tubeDomain_mono inter_subset_left)).eqOn_of_preconnected_of_eventuallyEq + (hf₀.mono (tubeDomain_mono (inter_subset_right.trans hr₁Ω))) + (isPreconnected_tubeDomain (hÃc.inter (convex_ball _ r₁)).isPreconnected) + (ofRealPi_mem_tubeDomain.mpr hpt) hnear + set g₁ : (Fin n → ℂ) → F := fun z => if z ∈ tubeDomain (maxStar F Ω p) then g₀ z else f₀ z + have hg₁a : AnalyticOnNhd ℂ g₁ (tubeDomain (maxStar F Ω p ∪ ball (γ.extend t₁) r₁)) := + analyticOnNhd_ite_tubeDomain hÃo isOpen_ball hg₀ + (hf₀.mono (tubeDomain_mono hr₁Ω)) hAB + have hg₁f : g₁ =ᶠ[𝓝 (ofRealPi p)] f₀ := by + have : g₁ =ᶠ[𝓝 (ofRealPi p)] g₀ := + eventuallyEq_of_mem ((isOpen_tubeDomain hÃo).mem_nhds (ofRealPi_mem_tubeDomain.mpr hpÃ)) + fun w hw => by simp [g₁, hw] + exact this.trans hg₀f + obtain ⟨g₂, hg₂, hg₂g₁⟩ := + exists_extension_tubeDomain_convexHull_of_starConvex hA₁o hA₁s hx₁A₁ hg₁a + refine ⟨g₂, hg₂, ?_⟩ + have : g₂ =ᶠ[𝓝 (ofRealPi p)] g₁ := + eventuallyEq_of_mem ((isOpen_tubeDomain hA₁o).mem_nhds + (ofRealPi_mem_tubeDomain.mpr (Or.inl hpÃ))) hg₂g₁ + exact this.trans hg₁f + exact hx₁ (subset_maxStar_of_mem hBmem (subset_convexHull ℝ _ hx₁A₁)) + have hconv : convexHull ℝ Ω ⊆ maxStar F Ω p := convexHull_min hΩà hÃc + obtain ⟨g, hg, hgf⟩ := tubeExtends_maxStar hpà f hf + refine ⟨g, hg.mono (tubeDomain_mono hconv), ?_⟩ + exact (hg.mono (tubeDomain_mono hΩÃ)).eqOn_of_preconnected_of_eventuallyEq hf + (isPreconnected_tubeDomain hc.isPreconnected) (ofRealPi_mem_tubeDomain.mpr hp) hgf + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Disc.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Disc.lean new file mode 100644 index 0000000000..4cb6536bec --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Disc.lean @@ -0,0 +1,414 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.AbsMax +public import Mathlib.Analysis.Convex.Segment +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic + +/-! +# Parabolic analytic discs in tubes and the hull of two segments + +For a vertex `p` and two points `t₁, t₂` of the real base, the triangle with these vertices is +parametrized by `p + u • v₁ + v • v₂` with `|u| ≤ v ≤ 1`, where `v₁ = (t₁ - t₂)/2` and `v₂ = (t₁ ++ t₂)/2 - p`. The parabolic analytic disc `ζ ↦ p + ζ • v₁ + (c ζ² + 1 - c) • v₂`, restricted to +the planar region where its real part lies in the triangle, has boundary over the two sides `[p, +t₁]` and `[p, t₂]`. By the planar maximum principle, every point of the disc lies in the +holomorphic hull of the boundary, relative to any tube whose base contains the triangle. As `c` +varies, the discs cover all points of the triangle with `|u| < v < 1`. No coordinate +normalization is needed, and the two points may be linearly dependent. + +References: [Korevaar–Wiegerinck][KorevaarWiegerinck2017], Exercise 6.28; +[Hörmander][Hormander1973] §2.5, Lemma 2.5.11. + +## Main definitions + +* `triDir₁`: The half-difference direction of a triangle with vertex `p` and points `t₁, t₂`. +* `triDir₂`: The half-sum direction of a triangle with vertex `p` and points `t₁, t₂`. +* `triPt`: The point of the triangle with parameters `u, v`. +* `tri`: The triangle with vertex `p` and points `t₁, t₂`, scaled by `b` toward `p`. +* `parabolaHeight`: The real-quadratic function defining the parabolic disc region. +* `parabolaRegion`: The planar region over which the parabolic disc lies inside the triangle. +* `parabolaDisc`: The parabolic analytic disc with parameter `c`, translated by the imaginary vector + `η`. + +## Main results + +* `convex_tri`: Scaled triangles are convex. +* `segment_subset_tri`: The segment between `t₁` and `t₂` lies in the triangle of scale one. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +-/ + +public noncomputable section + +open Set Filter Metric Complex +open scoped Topology + +namespace SeveralComplexVariables.BochnerTube + +variable {ι : Type*} + +section Triangle + +/-- The half-difference direction of a triangle with vertex `p` and points `t₁, t₂`. -/ +@[expose] def triDir₁ (_p t₁ t₂ : ι → ℝ) : ι → ℝ := (1 / 2 : ℝ) • (t₁ - t₂) + +/-- The half-sum direction of a triangle with vertex `p` and points `t₁, t₂`. -/ +@[expose] def triDir₂ (p t₁ t₂ : ι → ℝ) : ι → ℝ := (1 / 2 : ℝ) • (t₁ + t₂) - p + +/-- The point of the triangle with parameters `u, v`. -/ +@[expose] def triPt (p t₁ t₂ : ι → ℝ) (u v : ℝ) : ι → ℝ := + p + u • triDir₁ p t₁ t₂ + v • triDir₂ p t₁ t₂ + +/-- The triangle with vertex `p` and points `t₁, t₂`, scaled by `b` toward `p`. -/ +@[expose] def tri (p t₁ t₂ : ι → ℝ) (b : ℝ) : Set (ι → ℝ) := + {x | ∃ u v : ℝ, |u| ≤ v ∧ v ≤ b ∧ x = triPt p t₁ t₂ u v} + +variable (p t₁ t₂ : ι → ℝ) + +/-- The triangle point as a combination of the vertex and the two points. -/ +theorem triPt_eq (u v : ℝ) : + triPt p t₁ t₂ u v = p + ((v + u) / 2) • (t₁ - p) + ((v - u) / 2) • (t₂ - p) := by + unfold triPt triDir₁ triDir₂ + module + +/-- The parameters `(0, 0)` give the vertex. -/ +@[simp] theorem triPt_zero : triPt p t₁ t₂ 0 0 = p := by simp [triPt] + +/-- The parameters `(1, 1)` give the first point. -/ +theorem triPt_one_one : triPt p t₁ t₂ 1 1 = t₁ := by rw [triPt_eq]; module + +/-- The parameters `(-1, 1)` give the second point. -/ +theorem triPt_neg_one_one : triPt p t₁ t₂ (-1) 1 = t₂ := by rw [triPt_eq]; module + +/-- Points with `|u| = v` lie on the two sides through the vertex. -/ +theorem triPt_mem_union_segment {u v : ℝ} (huv : |u| = v) (hv1 : v ≤ 1) : + triPt p t₁ t₂ u v ∈ segment ℝ p t₁ ∪ segment ℝ p t₂ := by + have hv0 : 0 ≤ v := huv ▸ abs_nonneg u + rcases le_or_gt 0 u with hu | hu + · rw [abs_of_nonneg hu] at huv + subst huv + left + rw [segment_eq_image'] + refine ⟨u, ⟨hu, hv1⟩, ?_⟩ + rw [triPt_eq] + simp only + module + · rw [abs_of_neg hu] at huv + subst huv + right + rw [segment_eq_image'] + refine ⟨-u, ⟨by linarith, hv1⟩, ?_⟩ + rw [triPt_eq] + simp only + module + +/-- The segment between `t₁` and `t₂` lies in the triangle of scale one. -/ +theorem segment_subset_tri : segment ℝ t₁ t₂ ⊆ tri p t₁ t₂ 1 := by + intro x hx + rw [segment_eq_image'] at hx + obtain ⟨θ, ⟨h0, h1⟩, rfl⟩ := hx + refine ⟨1 - 2 * θ, 1, ?_, le_rfl, ?_⟩ + · rw [abs_le]; constructor <;> linarith + · rw [triPt_eq] + simp only + module + +/-- Scaled triangles increase with the scale. -/ +theorem tri_mono {b b' : ℝ} (h : b ≤ b') : tri p t₁ t₂ b ⊆ tri p t₁ t₂ b' := by + rintro x ⟨u, v, huv, hv, rfl⟩ + exact ⟨u, v, huv, hv.trans h, rfl⟩ + +/-- The vertex lies in every scaled triangle of nonnegative scale. -/ +theorem mem_tri_self {b : ℝ} (hb : 0 ≤ b) : p ∈ tri p t₁ t₂ b := + ⟨0, 0, by simp, hb, by simp⟩ + +/-- The triangle of scale zero is the vertex. -/ +theorem tri_zero : tri p t₁ t₂ 0 = {p} := by + ext x + constructor + · rintro ⟨u, v, huv, hv, rfl⟩ + have hv0 : v = 0 := le_antisymm hv ((abs_nonneg u).trans huv) + have hu0 : u = 0 := abs_eq_zero.mp (le_antisymm (hv0 ▸ huv) (abs_nonneg u)) + simp [hu0, hv0] + · rintro rfl + exact mem_tri_self _ _ _ le_rfl + +/-- Scaled triangles are convex. -/ +theorem convex_tri (b : ℝ) : Convex ℝ (tri p t₁ t₂ b) := by + rintro x ⟨u, v, huv, hv, rfl⟩ y ⟨u', v', huv', hv', rfl⟩ a a' ha ha' haa + refine ⟨a * u + a' * u', a * v + a' * v', ?_, ?_, ?_⟩ + · calc |a * u + a' * u'| ≤ |a * u| + |a' * u'| := abs_add_le _ _ + _ = a * |u| + a' * |u'| := by rw [abs_mul, abs_mul, abs_of_nonneg ha, abs_of_nonneg ha'] + _ ≤ a * v + a' * v' := by gcongr + · calc a * v + a' * v' ≤ a * b + a' * b := + add_le_add (mul_le_mul_of_nonneg_left hv ha) (mul_le_mul_of_nonneg_left hv' ha') + _ = b := by rw [← add_mul, haa, one_mul] + · simp only [triPt] + linear_combination (norm := module) haa • p + +/-- Scaling the two points toward the vertex scales the first direction. -/ +theorem triDir₁_scale (b : ℝ) : + triDir₁ p (p + b • (t₁ - p)) (p + b • (t₂ - p)) = b • triDir₁ p t₁ t₂ := by + unfold triDir₁; module + +/-- Scaling the two points toward the vertex scales the second direction. -/ +theorem triDir₂_scale (b : ℝ) : + triDir₂ p (p + b • (t₁ - p)) (p + b • (t₂ - p)) = b • triDir₂ p t₁ t₂ := by + unfold triDir₂; module + +/-- Points of a scaled triangle in terms of the original parametrization. -/ +theorem triPt_scale {a : ℝ} (ha : a ≠ 0) (u v : ℝ) : + triPt p (p + a • (t₁ - p)) (p + a • (t₂ - p)) (u / a) (v / a) = triPt p t₁ t₂ u v := by + simp only [triPt, triDir₁_scale, triDir₂_scale, smul_smul, div_mul_cancel₀ _ ha] + +/-- Scaling the two points toward the vertex scales the triangle. -/ +theorem tri_scale {b : ℝ} (hb : 0 < b) : + tri p t₁ t₂ b = tri p (p + b • (t₁ - p)) (p + b • (t₂ - p)) 1 := by + have hd₁ := triDir₁_scale p t₁ t₂ b + have hd₂ := triDir₂_scale p t₁ t₂ b + ext x + constructor + · rintro ⟨u, v, huv, hv, rfl⟩ + refine ⟨u / b, v / b, ?_, ?_, ?_⟩ + · rw [abs_div, abs_of_pos hb]; exact div_le_div_of_nonneg_right huv hb.le + · exact (div_le_one hb).mpr hv + · simp only [triPt, hd₁, hd₂, smul_smul, div_mul_cancel₀ _ hb.ne'] + · rintro ⟨u, v, huv, hv, rfl⟩ + refine ⟨b * u, b * v, ?_, ?_, ?_⟩ + · rw [abs_mul, abs_of_pos hb]; exact mul_le_mul_of_nonneg_left huv hb.le + · calc b * v ≤ b * 1 := mul_le_mul_of_nonneg_left hv hb.le + _ = b := mul_one b + · simp only [triPt, hd₁, hd₂, smul_smul, mul_comm b] + +/-- For `0 ≤ b ≤ 1`, the segment from `p` toward `t` scaled by `b` lies on the original segment. -/ +theorem segment_scaled_subset {b : ℝ} (hb0 : 0 ≤ b) (hb1 : b ≤ 1) (t : ι → ℝ) : + segment ℝ p (p + b • (t - p)) ⊆ segment ℝ p t := by + intro x hx + rw [segment_eq_image'] at hx ⊢ + obtain ⟨θ, ⟨h0, h1⟩, rfl⟩ := hx + refine ⟨θ * b, ⟨by positivity, ?_⟩, ?_⟩ + · calc θ * b ≤ 1 * 1 := by gcongr + _ = 1 := one_mul 1 + · simp only [add_sub_cancel_left, smul_smul] + +end Triangle + +section Disc + +variable (p t₁ t₂ : ι → ℝ) + +/-- The real-quadratic function defining the parabolic disc region. -/ +def parabolaHeight (c : ℝ) (ζ : ℂ) : ℝ := c * (ζ.re ^ 2 - ζ.im ^ 2) + (1 - c) + +/-- The planar region over which the parabolic disc lies inside the triangle. -/ +@[expose] def parabolaRegion (c : ℝ) : Set ℂ := + {ζ | |ζ.re| < parabolaHeight c ζ ∧ parabolaHeight c ζ < 1} + +/-- The parabolic analytic disc with parameter `c`, translated by the imaginary vector `η`. -/ +@[expose] def parabolaDisc (c : ℝ) (η : ι → ℝ) (ζ : ℂ) : ι → ℂ := + ofRealPi p + ζ • ofRealPi (triDir₁ p t₁ t₂) + + (c * ζ ^ 2 + (1 - c)) • ofRealPi (triDir₂ p t₁ t₂) + I • ofRealPi η + +/-- The height function of the parabolic region is continuous. -/ +theorem continuous_parabolaHeight (c : ℝ) : Continuous (parabolaHeight c) := by + unfold parabolaHeight; fun_prop + +/-- The real part of a complex multiple of a real vector. -/ +theorem rePi_smul_ofRealPi (ζ : ℂ) (v : ι → ℝ) : rePi (ζ • ofRealPi v) = ζ.re • v := by + funext i + simp [rePi, ofRealPi, Complex.mul_re] + +/-- The imaginary part of a complex multiple of a real vector. -/ +theorem imPi_smul_ofRealPi (ζ : ℂ) (v : ι → ℝ) : imPi (ζ • ofRealPi v) = ζ.im • v := by + funext i + simp [imPi, ofRealPi, Complex.mul_im] + +/-- The real part of the parabolic coefficient is the height function. -/ +theorem re_parabolaCoeff (c : ℝ) (ζ : ℂ) : (c * ζ ^ 2 + (1 - c) : ℂ).re = parabolaHeight c ζ := by + simp [parabolaHeight, sq, Complex.mul_re] + +/-- The real part of a disc point is the triangle point with parameters given by the real part of +`ζ` and the height. -/ +theorem rePi_parabolaDisc (c : ℝ) (η : ι → ℝ) (ζ : ℂ) : + rePi (parabolaDisc p t₁ t₂ c η ζ) = triPt p t₁ t₂ ζ.re (parabolaHeight c ζ) := by + unfold parabolaDisc triPt + rw [rePi_add, rePi_add, rePi_add, rePi_ofRealPi, rePi_smul_ofRealPi, rePi_smul_ofRealPi, + rePi_I_smul_ofRealPi, re_parabolaCoeff, add_zero] + +/-- The imaginary part of a disc point expands in the triangle directions, shifted by `η`. -/ +theorem imPi_parabolaDisc (c : ℝ) (η : ι → ℝ) (ζ : ℂ) : + imPi (parabolaDisc p t₁ t₂ c η ζ) = + ζ.im • triDir₁ p t₁ t₂ + (c * ζ ^ 2 + (1 - c) : ℂ).im • triDir₂ p t₁ t₂ + η := by + unfold parabolaDisc + funext i + simp [imPi, ofRealPi, Complex.mul_im] + +/-- The disc map is continuous. -/ +theorem continuous_parabolaDisc (c : ℝ) (η : ι → ℝ) : Continuous (parabolaDisc p t₁ t₂ c η) := by + unfold parabolaDisc; fun_prop + +/-- The disc map is entire. -/ +theorem differentiable_parabolaDisc (c : ℝ) (η : ι → ℝ) : + Differentiable ℂ (parabolaDisc p t₁ t₂ c η) := by + rw [differentiable_pi] + intro i + simp only [parabolaDisc, Pi.add_apply, Pi.smul_apply, smul_eq_mul, ofRealPi] + fun_prop + +/-- The parabolic region is open. -/ +theorem isOpen_parabolaRegion (c : ℝ) : IsOpen (parabolaRegion c) := + (isOpen_lt (by fun_prop) (continuous_parabolaHeight c)).inter + (isOpen_lt (continuous_parabolaHeight c) continuous_const) + +/-- The closure of the parabolic region is contained in the corresponding closed sublevel set. -/ +theorem closure_parabolaRegion_subset (c : ℝ) : + closure (parabolaRegion c) ⊆ {ζ | |ζ.re| ≤ parabolaHeight c ζ ∧ parabolaHeight c ζ ≤ 1} := + closure_minimal (fun ζ hζ => ⟨hζ.1.le, hζ.2.le⟩) + ((isClosed_le (by fun_prop) (continuous_parabolaHeight c)).inter + (isClosed_le (continuous_parabolaHeight c) continuous_const)) + +/-- If the height equals one and `|Re ζ| ≤ 1`, then `|Re ζ| = 1`. -/ +theorem abs_re_eq_one_of_parabolaHeight_eq_one {c : ℝ} (hc : 0 < c) {ζ : ℂ} + (hre : |ζ.re| ≤ 1) (h : parabolaHeight c ζ = 1) : |ζ.re| = 1 := by + unfold parabolaHeight at h + have h1 : ζ.re ^ 2 - ζ.im ^ 2 = 1 := by + have : c * (ζ.re ^ 2 - ζ.im ^ 2) = c := by linarith + exact mul_left_cancel₀ hc.ne' (this.trans (mul_one c).symm) + have h2 : 1 ≤ ζ.re ^ 2 := by nlinarith [sq_nonneg ζ.im] + have h3 : 1 ≤ |ζ.re| := by + rw [← sq_le_sq₀ zero_le_one (abs_nonneg _), one_pow, sq_abs] + exact h2 + exact le_antisymm hre h3 + +/-- Frontier points of the region have `|Re ζ| = parabolaHeight c ζ ≤ 1`. -/ +theorem frontier_parabolaRegion_subset {c : ℝ} (hc : 0 < c) : + frontier (parabolaRegion c) ⊆ {ζ | |ζ.re| = parabolaHeight c ζ ∧ parabolaHeight c ζ ≤ 1} := by + intro ζ hζ + have hcl := closure_parabolaRegion_subset c hζ.1 + have hnot : ζ ∉ parabolaRegion c := fun h => hζ.2 (by rwa [(isOpen_parabolaRegion c).interior_eq]) + refine ⟨?_, hcl.2⟩ + rcases hcl.1.lt_or_eq with hlt | heq + · exfalso + apply hnot + refine ⟨hlt, ?_⟩ + rcases hcl.2.lt_or_eq with hlt2 | heq2 + · exact hlt2 + · exfalso + have := abs_re_eq_one_of_parabolaHeight_eq_one hc (hcl.1.trans hcl.2) heq2 + linarith + · exact heq + +/-- The region is bounded. -/ +theorem isBounded_parabolaRegion {c : ℝ} (hc : 0 < c) : + Bornology.IsBounded (parabolaRegion c) := by + rw [Metric.isBounded_iff_subset_closedBall 0] + refine ⟨2 + 1 / c, fun ζ hζ => ?_⟩ + obtain ⟨h1, h2⟩ := hζ + have hre : |ζ.re| ≤ 1 := h1.le.trans h2.le + have hre2 : ζ.re ^ 2 ≤ 1 := by + rw [← sq_abs] + exact pow_le_one₀ (abs_nonneg _) hre + have him : c * ζ.im ^ 2 ≤ 1 := by + unfold parabolaHeight at h1 + nlinarith [abs_nonneg ζ.re] + have him2 : ζ.im ^ 2 ≤ 1 / c := by + rw [le_div_iff₀ hc]; linarith + have him3 : |ζ.im| ≤ 1 + 1 / c := by + have : |ζ.im| ≤ ζ.im ^ 2 + 1 := by + rcases le_or_gt |ζ.im| 1 with h | h + · linarith [sq_nonneg ζ.im] + · have : |ζ.im| ≤ |ζ.im| ^ 2 := by nlinarith [abs_nonneg ζ.im] + rw [sq_abs] at this + linarith + linarith + rw [mem_closedBall, dist_zero_right] + calc ‖ζ‖ ≤ |ζ.re| + |ζ.im| := Complex.norm_le_abs_re_add_abs_im ζ + _ ≤ 1 + (1 + 1 / c) := add_le_add hre him3 + _ = 2 + 1 / c := by ring + +/-- The image of the frontier of the region under the disc map is compact. -/ +theorem isCompact_image_frontier_parabolaRegion {c : ℝ} (hc : 0 < c) (η : ι → ℝ) : + IsCompact (parabolaDisc p t₁ t₂ c η '' frontier (parabolaRegion c)) := + (((isBounded_parabolaRegion hc).isCompact_closure).of_isClosed_subset isClosed_frontier + frontier_subset_closure).image (continuous_parabolaDisc p t₁ t₂ c η) + +/-- The disc over the closed region lies in the tube over the triangle. -/ +theorem parabolaDisc_mem_tubeDomain_tri (c : ℝ) (η : ι → ℝ) {ζ : ℂ} + (hζ : ζ ∈ closure (parabolaRegion c)) : + parabolaDisc p t₁ t₂ c η ζ ∈ tubeDomain (tri p t₁ t₂ 1) := by + have h := closure_parabolaRegion_subset c hζ + rw [mem_tubeDomain, rePi_parabolaDisc] + exact ⟨ζ.re, parabolaHeight c ζ, h.1, h.2, rfl⟩ + +/-- The disc boundary lies in the tube over the two sides through the vertex. -/ +theorem parabolaDisc_frontier_subset {c : ℝ} (hc : 0 < c) (η : ι → ℝ) : + parabolaDisc p t₁ t₂ c η '' frontier (parabolaRegion c) ⊆ + tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂) := by + rintro _ ⟨ζ, hζ, rfl⟩ + have h := frontier_parabolaRegion_subset hc hζ + rw [mem_tubeDomain, rePi_parabolaDisc] + exact triPt_mem_union_segment p t₁ t₂ h.1 h.2 + +/-- **Disc points lie in the hull of the disc boundary.** For any open base containing the +triangle, every point of the parabolic disc over the closed region lies in the holomorphic hull, +relative to the tube, of the image of the frontier of the region. -/ +theorem parabolaDisc_mem_holomorphicHull [Fintype ι] {A : Set (ι → ℝ)} + (hT : tri p t₁ t₂ 1 ⊆ A) {c : ℝ} (hc : 0 < c) (η : ι → ℝ) {ζ₀ : ℂ} + (hζ₀ : ζ₀ ∈ closure (parabolaRegion c)) : + parabolaDisc p t₁ t₂ c η ζ₀ ∈ + holomorphicHull (tubeDomain A) (parabolaDisc p t₁ t₂ c η '' frontier (parabolaRegion c)) := by + refine ⟨tubeDomain_mono hT (parabolaDisc_mem_tubeDomain_tri p t₁ t₂ c η hζ₀), ?_⟩ + intro g hg M hM + have hmaps : MapsTo (parabolaDisc p t₁ t₂ c η) (closure (parabolaRegion c)) (tubeDomain A) := + fun ζ hζ => tubeDomain_mono hT (parabolaDisc_mem_tubeDomain_tri p t₁ t₂ c η hζ) + have hd : DiffContOnCl ℂ (g ∘ parabolaDisc p t₁ t₂ c η) (parabolaRegion c) := by + apply DifferentiableOn.diffContOnCl + exact hg.differentiableOn.comp (differentiable_parabolaDisc p t₁ t₂ c η).differentiableOn hmaps + exact Complex.norm_le_of_forall_mem_frontier_norm_le (isBounded_parabolaRegion hc) hd + (fun ζ hζ => hM _ (mem_image_of_mem _ hζ)) hζ₀ + +/-- Every point of the triangle with `|u| < v < 1` lies on a parabolic disc. -/ +theorem exists_parabolaDisc_of_lt {u v : ℝ} (huv : |u| < v) (hv1 : v < 1) (η : ι → ℝ) : + ∃ c : ℝ, 0 < c ∧ c < 1 ∧ (u : ℂ) ∈ parabolaRegion c ∧ + parabolaDisc p t₁ t₂ c η u = ofRealPi (triPt p t₁ t₂ u v) + I • ofRealPi η := by + have hu1 : |u| < 1 := huv.trans hv1 + have hu2 : u ^ 2 < 1 := by + rw [← sq_abs] + exact pow_lt_one₀ (abs_nonneg _) hu1 two_ne_zero + have hu2v : u ^ 2 < v := by + calc u ^ 2 = |u| ^ 2 := (sq_abs u).symm + _ ≤ |u| := by nlinarith [abs_nonneg u] + _ < v := huv + set c : ℝ := (1 - v) / (1 - u ^ 2) with hc + have hden : 0 < 1 - u ^ 2 := by linarith + have hc0 : 0 < c := div_pos (by linarith) hden + have hc1 : c < 1 := by rw [hc, div_lt_one hden]; linarith + have hheight : parabolaHeight c u = v := by + unfold parabolaHeight + simp only [Complex.ofReal_re, Complex.ofReal_im] + rw [hc] + field_simp + ring + refine ⟨c, hc0, hc1, ⟨?_, ?_⟩, ?_⟩ + · rw [hheight]; simpa using huv + · rw [hheight]; exact hv1 + · have him : (c * (u : ℂ) ^ 2 + (1 - c) : ℂ).im = 0 := by simp [sq, Complex.mul_im] + have := ofRealPi_rePi_add_I_smul_ofRealPi_imPi (parabolaDisc p t₁ t₂ c η u) + rw [rePi_parabolaDisc, hheight, imPi_parabolaDisc, him] at this + rw [← this] + simp + +end Disc + +end SeveralComplexVariables.BochnerTube + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Gluing.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Gluing.lean new file mode 100644 index 0000000000..b8eea0c5cb --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Gluing.lean @@ -0,0 +1,156 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Uniqueness +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.Convex.Segment +public import Mathlib.Analysis.Normed.Affine.AddTorsor +public import Mathlib.Analysis.Normed.Module.Connected +public import Mathlib.Analysis.Normed.Module.Convex + +/-! +# Gluing local analytic continuations along a convex set + +Let `g` be holomorphic on an open set `U` of a complex normed space and let `L ⊆ U` be convex. +Suppose that at every point `ζ` of `L` there is a holomorphic function on the ball of radius `δ` +around `ζ` agreeing with `g` near `ζ`. Then these local continuations agree on overlaps and +define a holomorphic function on the `δ`-neighborhood of `L` agreeing with `g` near every point +of `L`. The overlap argument passes through the midpoint of two centers, which lies in `L` and +in both balls, and uses the identity theorem on a thickened segment. + +References: [Scheidemann][Scheidemann2005] §6.3, proof of Theorem 6.3.1; +[Hörmander][Hormander1973] §2.5, proof of Theorem 2.5.10. + +## Main results + +* `eventuallyEq_of_isPreconnected`: **Propagation of local agreement along a preconnected set.** Two + holomorphic functions on an open set that agree near one point of a preconnected subset agree near + every point of that subset. +* `exists_glue_of_local_continuations`: **Gluing lemma.** Local holomorphic continuations of `g` on + balls of a fixed radius around the points of a convex set `L ⊆ U` glue to a holomorphic function + on the `δ`-neighborhood of `L` agreeing with `g` near every point of `L`. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- **Propagation of local agreement along a preconnected set.** Two holomorphic functions +on an open set that agree near one point of a preconnected subset agree near every point of +that subset. -/ +theorem eventuallyEq_of_isPreconnected {U K : Set E} (hU : IsOpen U) {g h : E → F} + (hg : AnalyticOnNhd ℂ g U) (hh : AnalyticOnNhd ℂ h U) (hK : IsPreconnected K) (hKU : K ⊆ U) + {a : E} (ha : a ∈ K) (hab : h =ᶠ[𝓝 a] g) {b : E} (hb : b ∈ K) : h =ᶠ[𝓝 b] g := by + set u : Set E := {x | h =ᶠ[𝓝 x] g} with hu + set v : Set E := {x | x ∈ U ∧ ¬ h =ᶠ[𝓝 x] g} with hv + have huo : IsOpen u := by + rw [isOpen_iff_mem_nhds] + intro x hx + exact hx.eventually_nhds + have hvo : IsOpen v := by + rw [isOpen_iff_forall_mem_open] + intro x ⟨hxU, hx⟩ + obtain ⟨r, hr, hrU⟩ := Metric.isOpen_iff.mp hU x hxU + refine ⟨ball x r, fun y hy => ⟨hrU hy, fun hy' => hx ?_⟩, isOpen_ball, mem_ball_self hr⟩ + have heq : EqOn h g (ball x r) := + (hh.mono hrU).eqOn_of_preconnected_of_eventuallyEq (hg.mono hrU) + (convex_ball x r).isPreconnected hy hy' + exact eventuallyEq_of_mem (isOpen_ball.mem_nhds (mem_ball_self hr)) heq + have hcover : K ⊆ u ∪ v := fun x hx => by + by_cases h : h =ᶠ[𝓝 x] g + · exact Or.inl h + · exact Or.inr ⟨hKU hx, h⟩ + have hdisj : K ∩ (u ∩ v) = ∅ := by + ext x + simp only [mem_inter_iff, mem_empty_iff_false, iff_false, not_and] + intro _ hxu hxv + exact hxv.2 hxu + rcases isPreconnected_iff_subset_of_disjoint.mp hK u v huo hvo hcover hdisj with h | h + · exact h hb + · exact absurd hab (h ha).2 + +/-- Agreement of two holomorphic functions near a point propagates along a segment inside their +common domain: if they agree near one endpoint, they agree near the other. -/ +theorem eventuallyEq_of_segment_subset {U : Set E} (hU : IsOpen U) {g h : E → F} + (hg : AnalyticOnNhd ℂ g U) (hh : AnalyticOnNhd ℂ h U) {a b : E} + (hseg : segment ℝ a b ⊆ U) (hab : h =ᶠ[𝓝 a] g) : h =ᶠ[𝓝 b] g := + eventuallyEq_of_isPreconnected hU hg hh (convex_segment a b).isPreconnected hseg + (left_mem_segment ℝ a b) hab (right_mem_segment ℝ a b) + +/-- **Gluing lemma.** Local holomorphic continuations of `g` on balls of a fixed radius +around the points of a convex set `L ⊆ U` glue to a holomorphic function on the +`δ`-neighborhood of `L` agreeing with `g` near every point of `L`. -/ +theorem exists_glue_of_local_continuations {U L : Set E} (hU : IsOpen U) (hL : Convex ℝ L) + (hLU : L ⊆ U) {g : E → F} (hg : AnalyticOnNhd ℂ g U) {δ : ℝ} (hδ : 0 < δ) + (h : ∀ ζ ∈ L, ∃ k : E → F, AnalyticOnNhd ℂ k (ball ζ δ) ∧ k =ᶠ[𝓝 ζ] g) : + ∃ H : E → F, AnalyticOnNhd ℂ H (⋃ ζ ∈ L, ball ζ δ) ∧ ∀ ζ ∈ L, H =ᶠ[𝓝 ζ] g := by + classical + choose! k hka hkg using h + -- each local continuation agrees with `g` near every point of `L` inside its ball + have hkL : ∀ ζ ∈ L, ∀ m ∈ L, m ∈ ball ζ δ → k ζ =ᶠ[𝓝 m] g := by + intro ζ hζ m hm hmζ + have hseg : segment ℝ ζ m ⊆ ball ζ δ ∩ U := + subset_inter ((convex_ball ζ δ).segment_subset (mem_ball_self hδ) hmζ) + ((hL.segment_subset hζ hm).trans hLU) + exact eventuallyEq_of_segment_subset (isOpen_ball.inter hU) + (hg.mono inter_subset_right) ((hka ζ hζ).mono inter_subset_left) hseg (hkg ζ hζ) + -- two local continuations agree on the intersection of their balls + have hconsist : ∀ ζ ∈ L, ∀ ζ' ∈ L, EqOn (k ζ) (k ζ') (ball ζ δ ∩ ball ζ' δ) := by + intro ζ hζ ζ' hζ' + rcases (ball ζ δ ∩ ball ζ' δ).eq_empty_or_nonempty with hemp | ⟨z, hz⟩ + · rw [hemp]; exact fun _ h => h.elim + set m : E := midpoint ℝ ζ ζ' with hm + have hmL : m ∈ L := hL.segment_subset hζ hζ' (midpoint_mem_segment ζ ζ') + have hdist : dist ζ ζ' < 2 * δ := by + calc dist ζ ζ' ≤ dist ζ z + dist z ζ' := dist_triangle _ _ _ + _ < δ + δ := add_lt_add (by simpa [dist_comm] using hz.1) (mem_ball.mp hz.2) + _ = 2 * δ := by ring + have hmζ : m ∈ ball ζ δ := by + rw [mem_ball, hm, dist_comm, dist_left_midpoint, Real.norm_eq_abs, abs_of_pos two_pos, + inv_mul_lt_iff₀ two_pos] + exact hdist + have hmζ' : m ∈ ball ζ' δ := by + rw [mem_ball, hm, dist_comm, dist_right_midpoint, Real.norm_eq_abs, abs_of_pos two_pos, + inv_mul_lt_iff₀ two_pos] + exact hdist + have h1 : k ζ =ᶠ[𝓝 m] k ζ' := + (hkL ζ hζ m hmL hmζ).trans (hkL ζ' hζ' m hmL hmζ').symm + exact ((hka ζ hζ).mono inter_subset_left).eqOn_of_preconnected_of_eventuallyEq + ((hka ζ' hζ').mono inter_subset_right) + ((convex_ball ζ δ).inter (convex_ball ζ' δ)).isPreconnected ⟨hmζ, hmζ'⟩ h1 + let H : E → F := fun z => + if hz : ∃ ζ ∈ L, z ∈ ball ζ δ then k (Classical.choose hz) z else 0 + have hH : ∀ ζ ∈ L, ∀ z ∈ ball ζ δ, H z = k ζ z := by + intro ζ hζ z hz + have hex : ∃ ζ ∈ L, z ∈ ball ζ δ := ⟨ζ, hζ, hz⟩ + simp only [H] + split_ifs + obtain ⟨hζ', hz'⟩ := Classical.choose_spec hex + exact hconsist _ hζ' ζ hζ ⟨hz', hz⟩ + refine ⟨H, ?_, fun ζ hζ => ?_⟩ + · intro z hz + obtain ⟨ζ, hζ, hzζ⟩ := mem_iUnion₂.mp hz + have : H =ᶠ[𝓝 z] k ζ := eventuallyEq_of_mem (isOpen_ball.mem_nhds hzζ) fun w hw => hH ζ hζ w hw + exact ((hka ζ hζ) z hzζ).congr this.symm + · have : H =ᶠ[𝓝 ζ] k ζ := + eventuallyEq_of_mem (isOpen_ball.mem_nhds (mem_ball_self hδ)) fun w hw => hH ζ hζ w hw + exact this.trans (hkg ζ hζ) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/StarConvex.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/StarConvex.lean new file mode 100644 index 0000000000..e49c8fe54c --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/StarConvex.lean @@ -0,0 +1,495 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing + +/-! +# The maximal star-convex extension tube and Bochner's theorem for star-convex bases + +Fix a Banach space `F`, a base `Ω ⊆ ℝⁿ` and a point `p`. The star-convex open sets `A` with +respect to `p` such that every `F`-valued holomorphic function on the tube over `Ω` extends +holomorphically to the tube over `A`, agreeing with it near the real point `p`, form a family +closed under unions: the union `maxStar` again has the extension property, because two members +meet in a star-convex set whose tube is connected. The maximal tube is convex. Indeed, for two +points `t₁, t₂` of `maxStar`, the scaled triangles with vertex `p` lie in `maxStar` by an +induction on the scale: on a slightly smaller triangle every point lies on a parabolic analytic +disc with boundary over the two sides through `p`, so by the disc hull lemma and Thullen's +continuation lemma every function continues to a ball of a uniform radius, these local +continuations glue along the convex triangle, and maximality absorbs the enlarged tube. + +Consequently, for an open star-convex base, every holomorphic function on the tube extends to +the tube over the convex hull. This is part (a) of [Hörmander][Hormander1973]'s proof of +Bochner's theorem. + +References: [Hörmander][Hormander1973] §2.5, Theorem 2.5.10 (a); [Scheidemann][Scheidemann2005] +§6.3, Theorem 6.3.1, Step 1. + +## Main definitions + +* `TubeExtends`: Every `F`-valued holomorphic function on the tube over `Ω` extends holomorphically + to the tube over `A`, agreeing with the original near the real point `p`. +* `starFamily`: The family of open star-convex extension bases. +* `maxStar`: The maximal star-convex extension base. + +## Main results + +* `maxStar_maximal`: **Maximality.** An open star-convex base to which every function on the maximal + tube extends is contained in the maximal base. +* `exists_local_continuation_tri`: **Local continuation on a shrunken triangle.** If the tube over + the triangle of scale `a` lies in the tube over `A` and balls of radius `δ` around the two sides + through `p` lie in the tube over `A`, then every function holomorphic on the tube over `A` + continues to the ball of radius `δ` around each point of the tube over the triangle of a smaller + scale `b`. +* `thickening_tri_subset_of_maximal`: **One step of the triangle induction.** Under maximality, the + `δ`-thickening of the tube over the triangle of a smaller scale is absorbed into `A`. +* `tri_subset_of_maximal`: **The triangle lemma.** Under maximality, the full triangle with vertex + `p` and two points of `A` lies in `A`. +* `convex_maxStar`: **The maximal star-convex extension base is convex.** +* `exists_extension_tubeDomain_convexHull_of_starConvex`: **Bochner's tube theorem for star-convex + bases.** Every Banach-valued holomorphic function on the tube over an open star-convex base + extends to the tube over the convex hull. + +## References + +* [L. Hörmander, *An Introduction to Complex Analysis in Several Variables*][Hormander1973] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public noncomputable section + +open Set Filter Metric Complex +open scoped Topology + +namespace SeveralComplexVariables + +namespace BochnerTube + +variable {n : ℕ} (F : Type*) [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + +/-- Every `F`-valued holomorphic function on the tube over `Ω` extends holomorphically to the tube +over `A`, agreeing with the original near the real point `p`. -/ +@[expose] def TubeExtends (Ω A : Set (Fin n → ℝ)) (p : Fin n → ℝ) : Prop := + ∀ f : (Fin n → ℂ) → F, AnalyticOnNhd ℂ f (tubeDomain Ω) → + ∃ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain A) ∧ g =ᶠ[𝓝 (ofRealPi p)] f + +/-- The family of open star-convex extension bases. -/ +@[expose] def starFamily (Ω : Set (Fin n → ℝ)) (p : Fin n → ℝ) : Set (Set (Fin n → ℝ)) := + {A | IsOpen A ∧ StarConvex ℝ p A ∧ TubeExtends F Ω A p} + +/-- The maximal star-convex extension base. -/ +@[expose] def maxStar (Ω : Set (Fin n → ℝ)) (p : Fin n → ℝ) : Set (Fin n → ℝ) := + ⋃₀ starFamily F Ω p + +variable {F} + +section Family + +variable {Ω : Set (Fin n → ℝ)} {p : Fin n → ℝ} + +omit [CompleteSpace F] in +/-- The maximal base is open. -/ +theorem isOpen_maxStar : IsOpen (maxStar F Ω p) := isOpen_sUnion fun _ hA => hA.1 + +omit [CompleteSpace F] in +/-- The maximal base is star-convex with respect to `p`. -/ +theorem starConvex_maxStar : StarConvex ℝ p (maxStar F Ω p) := + starConvex_sUnion fun _ hA => hA.2.1 + +omit [CompleteSpace F] in +/-- Members of the family lie in the maximal base. -/ +theorem subset_maxStar_of_mem {A : Set (Fin n → ℝ)} (hA : A ∈ starFamily F Ω p) : + A ⊆ maxStar F Ω p := subset_sUnion_of_mem hA + +omit [CompleteSpace F] in +/-- A ball around `p` inside `Ω` belongs to the family. -/ +theorem ball_mem_starFamily {r : ℝ} (hr0 : 0 < r) (hr : ball p r ⊆ Ω) : + ball p r ∈ starFamily F Ω p := + ⟨isOpen_ball, (convex_ball p r).starConvex (mem_ball_self hr0), + fun f hf => ⟨f, hf.mono (tubeDomain_mono hr), EventuallyEq.rfl⟩⟩ + +omit [CompleteSpace F] in +/-- The center lies in the maximal base when a ball around it lies in `Ω`. -/ +theorem mem_maxStar_of_ball {r : ℝ} (hr0 : 0 < r) (hr : ball p r ⊆ Ω) : p ∈ maxStar F Ω p := + subset_maxStar_of_mem (ball_mem_starFamily hr0 hr) (mem_ball_self hr0) + +/-- The tube over a star-convex set containing its center is preconnected. -/ +theorem isPreconnected_tubeDomain_of_starConvex {A : Set (Fin n → ℝ)} (hA : StarConvex ℝ p A) + (hp : p ∈ A) : IsPreconnected (tubeDomain A) := + isPreconnected_tubeDomain (hA.isPathConnected hp).isConnected.isPreconnected + +omit [CompleteSpace F] in +/-- Two extensions agreeing with a function near `p` agree on the tube over the intersection of +star-convex bases. -/ +theorem eqOn_of_starConvex {A B : Set (Fin n → ℝ)} (hA : StarConvex ℝ p A) + (hB : StarConvex ℝ p B) {f g₁ g₂ : (Fin n → ℂ) → F} + (hg₁ : AnalyticOnNhd ℂ g₁ (tubeDomain A)) (hg₂ : AnalyticOnNhd ℂ g₂ (tubeDomain B)) + (h₁ : g₁ =ᶠ[𝓝 (ofRealPi p)] f) (h₂ : g₂ =ᶠ[𝓝 (ofRealPi p)] f) : + EqOn g₁ g₂ (tubeDomain (A ∩ B)) := by + rcases (A ∩ B).eq_empty_or_nonempty with he | hne + · rw [he, tubeDomain_empty] + exact fun _ h => h.elim + have hp : p ∈ A ∩ B := (hA.inter hB).mem hne + exact (hg₁.mono (tubeDomain_mono inter_subset_left)).eqOn_of_preconnected_of_eventuallyEq + (hg₂.mono (tubeDomain_mono inter_subset_right)) + (isPreconnected_tubeDomain_of_starConvex (hA.inter hB) hp) + (ofRealPi_mem_tubeDomain.mpr hp) (h₁.trans h₂.symm) + +omit [CompleteSpace F] in +/-- The maximal base has the extension property. -/ +theorem tubeExtends_maxStar (hp : p ∈ maxStar F Ω p) : TubeExtends F Ω (maxStar F Ω p) p := by + classical + intro f hf + have hchoice : ∀ A : Set (Fin n → ℝ), A ∈ starFamily F Ω p → + ∃ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain A) ∧ g =ᶠ[𝓝 (ofRealPi p)] f := + fun A hA => hA.2.2 f hf + choose! g hga hgf using hchoice + let G : (Fin n → ℂ) → F := fun z => + if hz : ∃ A ∈ starFamily F Ω p, z ∈ tubeDomain A then g (Classical.choose hz) z else 0 + have hG : ∀ A ∈ starFamily F Ω p, ∀ z ∈ tubeDomain A, G z = g A z := by + intro A hA z hz + have hex : ∃ A ∈ starFamily F Ω p, z ∈ tubeDomain A := ⟨A, hA, hz⟩ + simp only [G] + split_ifs + obtain ⟨hA', hz'⟩ := Classical.choose_spec hex + exact eqOn_of_starConvex hA'.2.1 hA.2.1 (hga _ hA') (hga A hA) (hgf _ hA') (hgf A hA) + ⟨hz', hz⟩ + obtain ⟨A₀, hA₀, hpA₀⟩ := mem_sUnion.mp hp + refine ⟨G, ?_, ?_⟩ + · intro z hz + obtain ⟨A, hA, hzA⟩ := mem_sUnion.mp hz + have : G =ᶠ[𝓝 z] g A := + eventuallyEq_of_mem ((isOpen_tubeDomain hA.1).mem_nhds hzA) fun w hw => hG A hA w hw + exact (hga A hA z hzA).congr this.symm + · have : G =ᶠ[𝓝 (ofRealPi p)] g A₀ := + eventuallyEq_of_mem ((isOpen_tubeDomain hA₀.1).mem_nhds (ofRealPi_mem_tubeDomain.mpr hpA₀)) + fun w hw => hG A₀ hA₀ w hw + exact this.trans (hgf A₀ hA₀) + +omit [CompleteSpace F] in +/-- **Maximality.** An open star-convex base to which every function on the maximal tube +extends is contained in the maximal base. -/ +theorem maxStar_maximal (hp : p ∈ maxStar F Ω p) {B : Set (Fin n → ℝ)} (hB : IsOpen B) + (hBs : StarConvex ℝ p B) + (hext : ∀ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain (maxStar F Ω p)) → + ∃ G : (Fin n → ℂ) → F, AnalyticOnNhd ℂ G (tubeDomain B) ∧ + EqOn G g (tubeDomain (maxStar F Ω p))) : + B ⊆ maxStar F Ω p := by + apply subset_maxStar_of_mem + refine ⟨hB, hBs, fun f hf => ?_⟩ + obtain ⟨g, hg, hgf⟩ := tubeExtends_maxStar hp f hf + obtain ⟨G, hG, hGg⟩ := hext g hg + refine ⟨G, hG, ?_⟩ + have : G =ᶠ[𝓝 (ofRealPi p)] g := + eventuallyEq_of_mem ((isOpen_tubeDomain isOpen_maxStar).mem_nhds + (ofRealPi_mem_tubeDomain.mpr hp)) hGg + exact this.trans hgf + +omit [CompleteSpace F] in +open scoped Classical in +/-- Piecewise gluing of holomorphic functions on tubes over an open union, agreeing on the +intersection. -/ +theorem analyticOnNhd_ite_tubeDomain {A B : Set (Fin n → ℝ)} (hA : IsOpen A) (hB : IsOpen B) + {g h : (Fin n → ℂ) → F} + (hg : AnalyticOnNhd ℂ g (tubeDomain A)) (hh : AnalyticOnNhd ℂ h (tubeDomain B)) + (heq : EqOn g h (tubeDomain (A ∩ B))) : + AnalyticOnNhd ℂ (fun z => if z ∈ tubeDomain A then g z else h z) (tubeDomain (A ∪ B)) := by + classical + intro z hz + rw [tubeDomain_union] at hz + rcases hz with hzA | hzB + · have : (fun z => if z ∈ tubeDomain A then g z else h z) =ᶠ[𝓝 z] g := + eventuallyEq_of_mem ((isOpen_tubeDomain hA).mem_nhds hzA) fun w hw => by simp [hw] + exact (hg z hzA).congr this.symm + · have : (fun z => if z ∈ tubeDomain A then g z else h z) =ᶠ[𝓝 z] h := by + refine eventuallyEq_of_mem ((isOpen_tubeDomain hB).mem_nhds hzB) fun w hw => ?_ + by_cases hwA : w ∈ tubeDomain A + · simp only [hwA, ite_true] + exact heq ⟨hwA, hw⟩ + · simp only [hwA, ite_false] + exact (hh z hzB).congr this.symm + +end Family + +section Triangle + +variable {A : Set (Fin n → ℝ)} {p t₁ t₂ : Fin n → ℝ} + +/-- **Local continuation on a shrunken triangle.** If the tube over the triangle of scale `a` +lies in the tube over `A` and balls of radius `δ` around the two sides through `p` lie in the +tube over `A`, then every function holomorphic on the tube over `A` continues to the ball of +radius `δ` around each point of the tube over the triangle of a smaller scale `b`. -/ +theorem exists_local_continuation_tri (hA : IsOpen A) {a : ℝ} (ha1 : a ≤ 1) + (htri : tri p t₁ t₂ a ⊆ A) {δ : ℝ} (hδ : 0 < δ) + (hS : ∀ w ∈ tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂), ball w δ ⊆ tubeDomain A) + {b : ℝ} (hba : b ≤ a) (hlt : b = 0 ∨ b < a) + {g : (Fin n → ℂ) → F} (hg : AnalyticOnNhd ℂ g (tubeDomain A)) : + ∀ ζ ∈ tubeDomain (tri p t₁ t₂ b), ∃ k : (Fin n → ℂ) → F, + AnalyticOnNhd ℂ k (ball ζ δ) ∧ k =ᶠ[𝓝 ζ] g := by + intro ζ hζ + obtain ⟨u, v, huv, hvb, hre⟩ := mem_tubeDomain.mp hζ + rcases huv.lt_or_eq with hlt' | heq + · have hv0 : 0 < v := (abs_nonneg u).trans_lt hlt' + have hbpos : 0 < b := hv0.trans_le hvb + have hba' : b < a := by + rcases hlt with h | h + · exact absurd h hbpos.ne' + · exact h + have ha : 0 < a := hbpos.trans hba' + set s₁ : Fin n → ℝ := p + a • (t₁ - p) with hs₁ + set s₂ : Fin n → ℝ := p + a • (t₂ - p) with hs₂ + have htri' : tri p s₁ s₂ 1 ⊆ A := by rw [← tri_scale p t₁ t₂ ha]; exact htri + have huv' : |u / a| < v / a := by + rw [abs_div, abs_of_pos ha] + exact div_lt_div_of_pos_right hlt' ha + have hv1 : v / a < 1 := (div_lt_one ha).mpr (hvb.trans_lt hba') + obtain ⟨c, hc0, -, hreg, hdisc⟩ := exists_parabolaDisc_of_lt p s₁ s₂ huv' hv1 (imPi ζ) + have hζeq : parabolaDisc p s₁ s₂ c (imPi ζ) ((u / a : ℝ) : ℂ) = ζ := by + rw [hdisc, hs₁, hs₂, triPt_scale p t₁ t₂ ha.ne', ← hre] + exact ofRealPi_rePi_add_I_smul_ofRealPi_imPi ζ + have hhull := parabolaDisc_mem_holomorphicHull p s₁ s₂ htri' hc0 (imPi ζ) (subset_closure hreg) + rw [hζeq] at hhull + have hK : IsCompact (parabolaDisc p s₁ s₂ c (imPi ζ) '' frontier (parabolaRegion c)) := + isCompact_image_frontier_parabolaRegion p s₁ s₂ hc0 _ + have hKS : parabolaDisc p s₁ s₂ c (imPi ζ) '' frontier (parabolaRegion c) ⊆ + tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂) := by + refine (parabolaDisc_frontier_subset p s₁ s₂ hc0 _).trans (tubeDomain_mono ?_) + exact union_subset_union (segment_scaled_subset p ha.le ha1 t₁) + (segment_scaled_subset p ha.le ha1 t₂) + have hball : ∀ w ∈ parabolaDisc p s₁ s₂ c (imPi ζ) '' frontier (parabolaRegion c), + ball w δ ⊆ tubeDomain A := fun w hw => hS w (hKS hw) + exact exists_continuation_ball_of_mem_holomorphicHull (isOpen_tubeDomain hA) hK + (fun w hw => hball w hw (mem_ball_self hδ)) hδ hball hhull hg + · have hmem : ζ ∈ tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂) := by + rw [mem_tubeDomain, hre] + exact triPt_mem_union_segment p t₁ t₂ heq (hvb.trans (hba.trans ha1)) + exact ⟨g, hg.mono (hS ζ hmem), EventuallyEq.rfl⟩ + +/-- **One step of the triangle induction.** Under maximality, the `δ`-thickening of the tube +over the triangle of a smaller scale is absorbed into `A`. -/ +theorem thickening_tri_subset_of_maximal (hA : IsOpen A) (hAs : StarConvex ℝ p A) (hp : p ∈ A) + (hmax : ∀ B : Set (Fin n → ℝ), IsOpen B → StarConvex ℝ p B → + (∀ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain A) → + ∃ G : (Fin n → ℂ) → F, AnalyticOnNhd ℂ G (tubeDomain B) ∧ EqOn G g (tubeDomain A)) → + B ⊆ A) + {δ : ℝ} (hδ : 0 < δ) + (hS : ∀ w ∈ tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂), ball w δ ⊆ tubeDomain A) + {a b : ℝ} (ha1 : a ≤ 1) (hb0 : 0 ≤ b) (hba : b ≤ a) (hlt : b = 0 ∨ b < a) + (htri : tri p t₁ t₂ a ⊆ A) : thickening δ (tri p t₁ t₂ b) ⊆ A := by + classical + set L := tri p t₁ t₂ b with hL + set N := thickening δ L with hN + have hLconv : Convex ℝ L := convex_tri p t₁ t₂ b + have hpL : p ∈ L := mem_tri_self p t₁ t₂ hb0 + have hLA : L ⊆ A := (tri_mono p t₁ t₂ hba).trans htri + have hNo : IsOpen N := isOpen_thickening + have hNc : Convex ℝ N := hLconv.thickening δ + have hpN : p ∈ N := self_subset_thickening hδ L hpL + have hNs : StarConvex ℝ p N := hNc.starConvex hpN + have hTN : tubeDomain N ⊆ ⋃ ζ ∈ tubeDomain L, ball ζ δ := by + intro z hz + rw [mem_tubeDomain, hN, Metric.mem_thickening_iff] at hz + obtain ⟨y, hy, hdist⟩ := hz + refine mem_iUnion₂.mpr ⟨ofRealPi y + I • ofRealPi (imPi z), ?_, ?_⟩ + · rw [mem_tubeDomain, rePi_add, rePi_ofRealPi, rePi_I_smul_ofRealPi, add_zero] + exact hy + · rw [mem_ball, dist_eq_norm] + have hz := ofRealPi_rePi_add_I_smul_ofRealPi_imPi z + have : z - (ofRealPi y + I • ofRealPi (imPi z)) = ofRealPi (rePi z - y) := by + rw [ofRealPi_sub] + nth_rewrite 1 [← hz] + abel + rw [this, norm_ofRealPi, ← dist_eq_norm] + exact hdist + have hsub : A ∪ N ⊆ A := by + refine hmax (A ∪ N) (hA.union hNo) (hAs.union hNs) fun g hg => ?_ + have hloc := exists_local_continuation_tri hA ha1 htri hδ hS hba hlt hg + obtain ⟨H, hHa, hHg⟩ := exists_glue_of_local_continuations (isOpen_tubeDomain hA) + (convex_tubeDomain hLconv) (tubeDomain_mono hLA) hg hδ hloc + have hHN : AnalyticOnNhd ℂ H (tubeDomain N) := hHa.mono hTN + have hAN : EqOn H g (tubeDomain (A ∩ N)) := by + have hpAN : p ∈ A ∩ N := ⟨hp, hpN⟩ + exact (hHN.mono (tubeDomain_mono inter_subset_right)).eqOn_of_preconnected_of_eventuallyEq + (hg.mono (tubeDomain_mono inter_subset_left)) + (isPreconnected_tubeDomain_of_starConvex (hAs.inter hNs) hpAN) + (ofRealPi_mem_tubeDomain.mpr hpAN) (hHg _ (ofRealPi_mem_tubeDomain.mpr hpL)) + refine ⟨fun z => if z ∈ tubeDomain A then g z else H z, ?_, fun z hz => by simp [hz]⟩ + exact analyticOnNhd_ite_tubeDomain hA hNo hg hHN (fun z hz => (hAN hz).symm) + exact subset_union_right.trans hsub + +/-- A triangle with vanishing direction vectors is the vertex. -/ +theorem tri_subset_of_dirs_zero {b : ℝ} {B : Set (Fin n → ℝ)} + (h1 : triDir₁ p t₁ t₂ = 0) (h2 : triDir₂ p t₁ t₂ = 0) (hpB : p ∈ B) : + tri p t₁ t₂ b ⊆ B := by + rintro x ⟨u, v, -, -, rfl⟩ + simpa [triPt, h1, h2] using hpB + +/-- One scale step in the triangle lemma: a slightly larger scaled triangle still lies in `A`. -/ +theorem tri_subset_scale_step_of_maximal (hA : IsOpen A) (hAs : StarConvex ℝ p A) (hp : p ∈ A) + (hmax : ∀ B : Set (Fin n → ℝ), IsOpen B → StarConvex ℝ p B → + (∀ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain A) → + ∃ G : (Fin n → ℂ) → F, AnalyticOnNhd ℂ G (tubeDomain B) ∧ EqOn G g (tubeDomain A)) → + B ⊆ A) + {δ D ε δ₁ a a' : ℝ} (hδ : 0 < δ) (hDpos : 0 < D) + (hD : D = ‖triDir₁ p t₁ t₂‖ + ‖triDir₂ p t₁ t₂‖) + (hS : ∀ w ∈ tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂), ball w δ ⊆ tubeDomain A) + (hδ₁ : δ₁ = δ / (4 * D)) (hε : ε = min (1 / 2) (δ / (4 * D))) + (ha0 : 0 ≤ a) (ha1 : a ≤ 1) (htri : tri p t₁ t₂ a ⊆ A) + (ha'δ : a' ≤ a + δ₁) : + tri p t₁ t₂ a' ⊆ A := by + set b : ℝ := (1 - ε) * a + have hεle : ε ≤ 1 / 2 := by rw [hε]; exact min_le_left _ _ + have hεpos : 0 < ε := by rw [hε]; positivity + have hε1 : 0 ≤ 1 - ε := sub_nonneg.mpr (hεle.trans (by norm_num)) + have hb0 : 0 ≤ b := mul_nonneg hε1 ha0 + have hba : b ≤ a := mul_le_of_le_one_left ha0 (by linarith) + have hlt : b = 0 ∨ b < a := by + rcases ha0.lt_or_eq with h | h + · right; exact mul_lt_of_lt_one_left h (by linarith) + · left; dsimp [b]; rw [← h, mul_zero] + have hthick := thickening_tri_subset_of_maximal hA hAs hp hmax hδ hS ha1 hb0 hba hlt htri + rintro x ⟨u, v, huv, hva', rfl⟩ + by_cases hvb : v ≤ b + · exact hthick (self_subset_thickening hδ _ ⟨u, v, huv, hvb, rfl⟩) + · push Not at hvb + have hv0 : 0 < v := hb0.trans_lt hvb + set μ : ℝ := b / v + have hμ0 : 0 ≤ μ := div_nonneg hb0 hv0.le + have hμ1 : μ ≤ 1 := (div_le_one hv0).mpr hvb.le + have hμv : μ * v = b := div_mul_cancel₀ b hv0.ne' + apply hthick + rw [Metric.mem_thickening_iff] + refine ⟨triPt p t₁ t₂ (μ * u) (μ * v), ⟨μ * u, μ * v, ?_, ?_, rfl⟩, ?_⟩ + · rw [abs_mul, abs_of_nonneg hμ0] + exact mul_le_mul_of_nonneg_left huv hμ0 + · rw [hμv] + · rw [dist_eq_norm] + have hdiff : triPt p t₁ t₂ u v - triPt p t₁ t₂ (μ * u) (μ * v) = + ((1 - μ) * u) • triDir₁ p t₁ t₂ + ((1 - μ) * v) • triDir₂ p t₁ t₂ := by + simp only [triPt] + module + have h1 : v - b ≤ (a' - a) + ε * a := by + dsimp [b] + nlinarith [hva'] + have h2 : (a' - a) + ε * a ≤ δ₁ + ε := by nlinarith + have hεD : ε ≤ δ / (4 * D) := by rw [hε]; exact min_le_right _ _ + calc ‖triPt p t₁ t₂ u v - triPt p t₁ t₂ (μ * u) (μ * v)‖ + = ‖((1 - μ) * u) • triDir₁ p t₁ t₂ + ((1 - μ) * v) • triDir₂ p t₁ t₂‖ := by rw [hdiff] + _ ≤ ‖((1 - μ) * u) • triDir₁ p t₁ t₂‖ + ‖((1 - μ) * v) • triDir₂ p t₁ t₂‖ := + norm_add_le _ _ + _ = (1 - μ) * |u| * ‖triDir₁ p t₁ t₂‖ + (1 - μ) * v * ‖triDir₂ p t₁ t₂‖ := by + rw [norm_smul, norm_smul, Real.norm_eq_abs, Real.norm_eq_abs, abs_mul, abs_mul, + abs_of_nonneg (by linarith : (0 : ℝ) ≤ 1 - μ), abs_of_pos hv0] + _ ≤ (1 - μ) * v * ‖triDir₁ p t₁ t₂‖ + (1 - μ) * v * ‖triDir₂ p t₁ t₂‖ := by + gcongr + _ = (v - b) * D := by rw [hD, ← hμv]; ring + _ ≤ (δ₁ + ε) * D := mul_le_mul_of_nonneg_right (h1.trans h2) hDpos.le + _ ≤ (δ / (4 * D) + δ / (4 * D)) * D := + mul_le_mul_of_nonneg_right (add_le_add (le_of_eq hδ₁) hεD) hDpos.le + _ = δ / 2 := by field_simp; ring + _ < δ := half_lt_self hδ + +/-- **The triangle lemma.** Under maximality, the full triangle with vertex `p` and two +points of `A` lies in `A`. -/ +theorem tri_subset_of_maximal (hA : IsOpen A) (hAs : StarConvex ℝ p A) (hp : p ∈ A) + (hmax : ∀ B : Set (Fin n → ℝ), IsOpen B → StarConvex ℝ p B → + (∀ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain A) → + ∃ G : (Fin n → ℂ) → F, AnalyticOnNhd ℂ G (tubeDomain B) ∧ EqOn G g (tubeDomain A)) → + B ⊆ A) + (ht₁ : t₁ ∈ A) (ht₂ : t₂ ∈ A) : tri p t₁ t₂ 1 ⊆ A := by + have hS_sub : segment ℝ p t₁ ∪ segment ℝ p t₂ ⊆ A := + union_subset (hAs.segment_subset ht₁) (hAs.segment_subset ht₂) + have hS_cpt : IsCompact (segment ℝ p t₁ ∪ segment ℝ p t₂) := by + refine IsCompact.union ?_ ?_ <;> + · rw [segment_eq_image'] + exact isCompact_Icc.image (by fun_prop) + obtain ⟨δ, hδ, hδA⟩ := hS_cpt.exists_thickening_subset_open hA hS_sub + have hS : ∀ w ∈ tubeDomain (segment ℝ p t₁ ∪ segment ℝ p t₂), ball w δ ⊆ tubeDomain A := + fun w hw => ball_subset_tubeDomain + ((ball_subset_thickening (E := segment ℝ p t₁ ∪ segment ℝ p t₂) (x := rePi w) hw δ).trans hδA) + set D : ℝ := ‖triDir₁ p t₁ t₂‖ + ‖triDir₂ p t₁ t₂‖ with hD + have hD0 : 0 ≤ D := by positivity + rcases hD0.lt_or_eq with hDpos | hDzero + swap + · have h1 : triDir₁ p t₁ t₂ = 0 := + norm_eq_zero.mp (by linarith [norm_nonneg (triDir₁ p t₁ t₂), norm_nonneg (triDir₂ p t₁ t₂)]) + have h2 : triDir₂ p t₁ t₂ = 0 := + norm_eq_zero.mp (by linarith [norm_nonneg (triDir₁ p t₁ t₂), norm_nonneg (triDir₂ p t₁ t₂)]) + exact tri_subset_of_dirs_zero h1 h2 hp + set δ₁ : ℝ := δ / (4 * D) + set ε : ℝ := min (1 / 2) (δ / (4 * D)) + have hδ₁ : 0 < δ₁ := by positivity + have hind : ∀ k : ℕ, tri p t₁ t₂ (min 1 (k * δ₁)) ⊆ A := by + intro k + induction k with + | zero => + rw [Nat.cast_zero, zero_mul, min_eq_right zero_le_one, tri_zero] + simpa using hp + | succ k ih => + have hk0 : (0 : ℝ) ≤ k * δ₁ := by positivity + refine tri_subset_scale_step_of_maximal hA hAs hp hmax hδ hDpos hD hS rfl rfl + (le_min zero_le_one hk0) (min_le_left _ _) ih ?_ + rcases le_or_gt 1 (k * δ₁) with h | h + · rw [min_eq_left h] + exact le_add_of_le_of_nonneg (min_le_left _ _) hδ₁.le + · rw [min_eq_right h.le] + push_cast + refine (min_le_right _ _).trans ?_ + rw [add_mul, one_mul] + obtain ⟨k, hk⟩ := exists_nat_ge (1 / δ₁) + have hk1 : 1 ≤ k * δ₁ := by + rw [div_le_iff₀ hδ₁] at hk + linarith + have := hind k + rwa [min_eq_left hk1] at this + +end Triangle + +section Convex + +variable {Ω : Set (Fin n → ℝ)} {p : Fin n → ℝ} + +/-- **The maximal star-convex extension base is convex.** -/ +theorem convex_maxStar (hp : p ∈ maxStar F Ω p) : Convex ℝ (maxStar F Ω p) := by + rw [convex_iff_segment_subset] + intro t₁ ht₁ t₂ ht₂ + exact (segment_subset_tri p t₁ t₂).trans (tri_subset_of_maximal isOpen_maxStar starConvex_maxStar + hp (fun _ hB hBs hext => maxStar_maximal hp hB hBs hext) ht₁ ht₂) + +end Convex + +end BochnerTube + +open BochnerTube + +section Convex + +variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {Ω : Set (Fin n → ℝ)} {p : Fin n → ℝ} + +/-- **Bochner's tube theorem for star-convex bases.** Every Banach-valued holomorphic function +on the tube over an open star-convex base extends to the tube over the convex hull. -/ +theorem exists_extension_tubeDomain_convexHull_of_starConvex (hΩ : IsOpen Ω) + (hs : StarConvex ℝ p Ω) (hp : p ∈ Ω) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f (tubeDomain Ω)) : + ∃ g : (Fin n → ℂ) → F, AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω)) ∧ + EqOn g f (tubeDomain Ω) := by + have hΩmem : Ω ∈ starFamily F Ω p := ⟨hΩ, hs, fun f hf => ⟨f, hf, EventuallyEq.rfl⟩⟩ + have hΩsub : Ω ⊆ maxStar F Ω p := subset_maxStar_of_mem hΩmem + have hpm : p ∈ maxStar F Ω p := hΩsub hp + have hconv : convexHull ℝ Ω ⊆ maxStar F Ω p := convexHull_min hΩsub (convex_maxStar hpm) + obtain ⟨g, hg, hgf⟩ := tubeExtends_maxStar hpm f hf + refine ⟨g, hg.mono (tubeDomain_mono hconv), ?_⟩ + exact (hg.mono (tubeDomain_mono hΩsub)).eqOn_of_preconnected_of_eventuallyEq hf + (isPreconnected_tubeDomain_of_starConvex hs hp) (ofRealPi_mem_tubeDomain.mpr hp) hgf + +end Convex + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean new file mode 100644 index 0000000000..0aacc92b9e --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean @@ -0,0 +1,655 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard + +/-! +# Analytic Weierstrass division + +A divisor of finite order in the distinguished scalar coordinate admits a unique quotient and a +polynomial remainder. We normalize the divisor by a nonvanishing leading factor, make the +remaining perturbation small, and apply the Picard iteration. Uniqueness holds on smaller +neighborhoods and hence for germs. The uniform statement applies to bounded numerators on a +common polydisc; the local statement applies to arbitrary analytic numerators. + +This module also exports the supporting theory: + +* `WeierstrassDivision.Basic`: division predicates and elementary properties; +* `WeierstrassDivision.CoordinatePower`: Cauchy division by a coordinate power; +* `WeierstrassDivision.Picard`: contraction estimates, limits, and uniqueness. + +Reference: [Jakóbczak–Jarnicki][JakobczakJarnicki2021], §1.7, Theorem 1.7.3. These analytic +statements do not follow just from Mathlib's formal, adic division theorem. + +## Main results + +* `exists_coordinatePower_leadingFactor_ne_zero`: **Coordinate-power normalization with a + nonvanishing leading factor.** A holomorphic function of finite order `d` in the distinguished + coordinate decomposes, on some initial polydisc-ball, as `f1 * z.2 ^ d` plus a Weierstrass + remainder whose coefficients vanish at the parameter origin; moreover `f1` itself is nonzero + throughout a (possibly smaller) polydisc-ball. +* `exists_perturbation_bound_of_coordinatePower_leadingFactor`: **A uniformly small perturbation of + the coordinate power.** Given a coordinate-power decomposition `f = f1 * z.2 ^ d + + weierstrassRemainder c` with `f1` nonvanishing on a polydisc-ball of radius `ε₁`, the perturbation + `weierstrassRemainder c / f1` is analytic there and, on a smaller polydisc-ball, uniformly bounded + by `R₂ ^ d / (2 * (d + 1))`: small enough for the Picard iteration against the divisor `z ^ d` to + contract in `exists_isWeierstrassDivisionOn_of_bounded`. +* `exists_isWeierstrassDivisionOn_of_bounded`: **Weierstrass division + ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.3).** A divisor whose central scalar slice has + finite order `d` admits division of every bounded holomorphic numerator on a fixed polydisc. +* `exists_isWeierstrassDivisionAt_of_finiteDimensional`: **Weierstrass division for analytic germs + on any finite-dimensional parameter space.** Obtained by transporting the coordinate version along + a basis; no choice of coordinates occurs in the statement. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex Filter Finset Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +open WeierstrassDivision + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +variable {ι : Type*} [Fintype ι] + +/-- **Coordinate-power normalization with a nonvanishing leading factor.** A holomorphic +function of finite order `d` in the distinguished coordinate decomposes, on some initial +polydisc-ball, as `f1 * z.2 ^ d` plus a Weierstrass remainder whose coefficients vanish at +the parameter origin; moreover `f1` itself is nonzero throughout a (possibly smaller) +polydisc-ball. This supplies the normalization in `exists_isWeierstrassDivisionOn_of_bounded`. -/ +theorem exists_coordinatePower_leadingFactor_ne_zero {d : ℕ} {f : (ι → ℂ) × ℂ → ℂ} + {U : Set ((ι → ℂ) × ℂ)} (hU : IsOpen U) (h0 : 0 ∈ U) (hf : DifferentiableOn ℂ f U) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (f1 : (ι → ℂ) × ℂ → ℂ) (c : Fin d → (ι → ℂ) → ℂ) (ε₀ ε₁ : ℝ), 0 < ε₀ ∧ 0 < ε₁ ∧ + polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀ ⊆ U ∧ + IsWeierstrassDivisionOn (fun z => z.2 ^ d) f f1 c + (polydisc (0 : ι → ℂ) (fun _ => ε₀)) ε₀ ∧ + (∀ j, c j 0 = 0) ∧ + polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁ ⊆ + polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀ ∧ + ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁, f1 z ≠ 0 := by + obtain ⟨ε₀, hε₀, hε₀U⟩ := exists_polydisc_ball_subset hU h0 + have hf0 : DifferentiableOn ℂ f (polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball 0 ε₀) := + hf.mono hε₀U + obtain ⟨f1, c, hfdiv, hf1bound, hf1uniq⟩ := + coordinatePower_division d hε₀ hf0 + have hz0V : (0 : ι → ℂ) ∈ polydisc (0 : ι → ℂ) (fun _ => ε₀) := + mem_polydisc.mpr fun i => by simpa using hε₀ + have hforder : AnalyticAt ℂ (fun w : ℂ => f (0, w)) 0 := + (differentiableOn_snd_slice hf0 hz0V).analyticOnNhd_of_finiteDimensional isOpen_ball + 0 (mem_ball_self hε₀) + have hcj0 : ∀ j : Fin d, c j 0 = 0 := by + intro j + rw [coeff_eq_iteratedDeriv_of_coordinatePower_division hfdiv hε₀ hz0V j] + have hle : (d : ℕ∞) ≤ analyticOrderAt (fun w : ℂ => f (0, w)) 0 := horder.ge + rw [(natCast_le_analyticOrderAt_iff_iteratedDeriv_eq_zero hforder).mp hle (j : ℕ) j.isLt] + simp + have hf1_eq : ∀ ζ ∈ ball (0 : ℂ) ε₀, f (0, ζ) = f1 (0, ζ) * ζ ^ d := by + intro ζ hζ + have := hfdiv.eq (Set.mk_mem_prod hz0V hζ) + simpa [weierstrassRemainder, hcj0, mul_comm] using this + have hf1A0 : AnalyticAt ℂ (fun ζ : ℂ => f1 (0, ζ)) 0 := + (differentiableOn_snd_slice hfdiv.differentiableOn_quotient + hz0V).analyticOnNhd_of_finiteDimensional + isOpen_ball 0 (mem_ball_self hε₀) + have horder' : analyticOrderAt (fun ζ : ℂ => f1 (0, ζ) * ζ ^ d) 0 = d := by + rw [← analyticOrderAt_congr (Filter.eventuallyEq_of_mem (isOpen_ball.mem_nhds + (mem_ball_self hε₀)) hf1_eq)] + exact horder + have hf1ord0 : analyticOrderAt (fun ζ : ℂ => f1 (0, ζ)) 0 = 0 := by + have hpow : AnalyticAt ℂ (fun ζ : ℂ => ζ ^ d) 0 := analyticAt_id.pow d + have hpow' : analyticOrderAt (fun ζ : ℂ => ζ ^ d) 0 = d := by + have h := analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ) (z := (0 : ℂ))) d + simpa [analyticOrderAt_id, Pi.pow_def] using h + have hmul : analyticOrderAt (fun ζ : ℂ => f1 (0, ζ) * ζ ^ d) 0 = + analyticOrderAt (fun ζ : ℂ => f1 (0, ζ)) 0 + analyticOrderAt (fun ζ : ℂ => ζ ^ d) 0 := + analyticOrderAt_mul hf1A0 hpow + rw [hmul, hpow'] at horder' + set y := analyticOrderAt (fun ζ : ℂ => f1 (0, ζ)) 0 with hy + clear_value y + induction y using ENat.recTopCoe with + | top => + exfalso + rw [show ((⊤ : ℕ∞) + (d : ℕ∞)) = ⊤ from rfl] at horder' + exact absurd horder' (ENat.natCast_ne_top d).symm + | coe n => + have hcast : ((n + d : ℕ) : ℕ∞) = ((d : ℕ) : ℕ∞) := horder' + have hn : n + d = d := WithTop.coe_injective hcast + have hn0 : n = 0 := by omega + rw [hn0] + rfl + have hf1ne0 : f1 (0, 0) ≠ 0 := hf1A0.analyticOrderAt_eq_zero.mp hf1ord0 + have hz00 : ((0 : ι → ℂ), (0 : ℂ)) ∈ + polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀ := + ⟨hz0V, mem_ball_self hε₀⟩ + have hf1contAt : ContinuousAt f1 (0, 0) := + ((hfdiv.differentiableOn_quotient.analyticOnNhd_of_finiteDimensional + ((isOpen_polydisc _ _).prod isOpen_ball)) _ hz00).continuousAt + have hf1ev : ∀ᶠ z in 𝓝 ((0 : ι → ℂ), (0 : ℂ)), f1 z ≠ 0 := + hf1contAt.eventually_ne hf1ne0 + obtain ⟨S, hSf1, hSopen, hS0⟩ := _root_.eventually_nhds_iff.mp hf1ev + obtain ⟨ε₁, hε₁, hε₁sub⟩ := exists_polydisc_ball_subset + (hSopen.inter ((isOpen_polydisc (0 : ι → ℂ) (fun _ => ε₀)).prod isOpen_ball)) + ⟨hS0, hz00⟩ + have hε₁ε₀ : polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁ ⊆ + polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀ := + fun z hz => (hε₁sub hz).2 + have hf1ne0' : ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁, f1 z ≠ 0 := + fun z hz => hSf1 z (hε₁sub hz).1 + exact ⟨f1, c, ε₀, ε₁, hε₀, hε₁, hε₀U, hfdiv, hcj0, hε₁ε₀, hf1ne0'⟩ + +omit [Fintype ι] in +/-- Uniform coefficient bounds give a uniform bound for a Weierstrass remainder on a scalar disc, +including the empty remainder when `d = 0`. -/ +private theorem norm_weierstrassRemainder_le {d : ℕ} {c : Fin d → (ι → ℂ) → ℂ} + {w : ι → ℂ} {ζ : ℂ} {R ε : ℝ} (hε : 0 ≤ ε) + (hc : ∀ j, ‖c j w‖ ≤ ε) (hζ : ‖ζ‖ ≤ R) : + ‖weierstrassRemainder c (w, ζ)‖ ≤ (d : ℝ) * ε * (max R 1) ^ d := by + have hpow (j : Fin d) : ‖ζ‖ ^ (j : ℕ) ≤ (max R 1) ^ d := + (pow_le_pow_left₀ (norm_nonneg _) (hζ.trans (le_max_left _ _)) _).trans + (pow_le_pow_right₀ (le_max_right _ _) j.isLt.le) + calc + ‖weierstrassRemainder c (w, ζ)‖ ≤ ∑ j : Fin d, ‖c j w * ζ ^ (j : ℕ)‖ := + norm_sum_le _ _ + _ ≤ ∑ _j : Fin d, ε * (max R 1) ^ d := by + apply Finset.sum_le_sum + intro j _ + rw [norm_mul, norm_pow] + exact mul_le_mul (hc j) (hpow j) (by positivity) hε + _ = (d : ℝ) * ε * (max R 1) ^ d := by simp; ring + +/-- If the remainder coefficients tend to zero and the leading factor is bounded away from zero, +shrinking only the parameter polydisc gives the contraction bound. The scalar radius and an +upper bound for the parameter radius can be prescribed. -/ +private theorem exists_small_remainder_div {d : ℕ} {c : Fin d → (ι → ℂ) → ℂ} + {f1 : (ι → ℂ) × ℂ → ℂ} {R δ r₀ : ℝ} (hR : 0 < R) (hδ : 0 < δ) (hr₀ : 0 < r₀) + (hc : ∀ j, Tendsto (c j) (𝓝 0) (𝓝 0)) + (hlower : ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => r₀) ×ˢ ball (0 : ℂ) R, + δ ≤ ‖f1 z‖) : + ∃ r : ℝ, 0 < r ∧ r ≤ r₀ ∧ + ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => r) ×ˢ ball (0 : ℂ) R, + ‖weierstrassRemainder c z / f1 z‖ ≤ R ^ d / (2 * (d + 1)) := by + let ε := δ * R ^ d / (2 * (d + 1) * (d + 1) * (max R 1) ^ d) + have hε : 0 < ε := by dsimp [ε]; positivity + have hev : ∀ᶠ w in 𝓝 (0 : ι → ℂ), ∀ j, ‖c j w‖ < ε := by + apply eventually_all.mpr + intro j + have ht : Tendsto (fun w => ‖c j w‖) (𝓝 0) (𝓝 0) := by simpa using (hc j).norm + exact ht.eventually_lt_const hε + obtain ⟨s, hs, hsmall⟩ := Metric.eventually_nhds_iff.mp hev + refine ⟨min s r₀, lt_min hs hr₀, min_le_right _ _, ?_⟩ + rintro ⟨w, ζ⟩ ⟨hw, hζ⟩ + have hw' : ‖w‖ < min s r₀ := by + simpa [pi_norm_lt_iff (lt_min hs hr₀), mem_polydisc] using hw + have hcw : ∀ j, ‖c j w‖ ≤ ε := fun j => + (hsmall (by simpa [dist_zero_right] using hw'.trans_le (min_le_left s r₀)) j).le + have hnum := norm_weierstrassRemainder_le hε.le hcw (mem_ball_zero_iff.mp hζ).le + have hl := hlower (w, ζ) ⟨polydisc_mono _ (fun _ => min_le_right s r₀) hw, hζ⟩ + rw [norm_div] + calc + ‖weierstrassRemainder c (w, ζ)‖ / ‖f1 (w, ζ)‖ ≤ + ((d : ℝ) * ε * (max R 1) ^ d) / δ := + (div_le_div_of_nonneg_right hnum (hδ.trans_le hl).le).trans + (div_le_div_of_nonneg_left (by positivity) hδ hl) + _ = (d : ℝ) * R ^ d / (2 * (d + 1) * (d + 1)) := by dsimp [ε]; field_simp + _ ≤ R ^ d / (2 * (d + 1)) := by + rw [div_le_div_iff₀ (by positivity) (by positivity)] + nlinarith [pow_pos hR d] + +/-- **A uniformly small perturbation of the coordinate power.** Given a coordinate-power +decomposition `f = f1 * z.2 ^ d + weierstrassRemainder c` with `f1` nonvanishing on a +polydisc-ball of radius `ε₁`, the perturbation `weierstrassRemainder c / f1` is analytic +there and, on a smaller polydisc-ball, uniformly bounded by `R₂ ^ d / (2 * (d + 1))`: small +enough for the Picard iteration against the divisor `z ^ d` to contract in +`exists_isWeierstrassDivisionOn_of_bounded`. The bound `δ` on `‖f1‖` over a fixed compact set is +also returned, since the germ-uniqueness argument reuses it at a further-shrunk radius. -/ +theorem exists_perturbation_bound_of_coordinatePower_leadingFactor {d : ℕ} {f : (ι → ℂ) × ℂ → ℂ} + {f1 : (ι → ℂ) × ℂ → ℂ} {c : Fin d → (ι → ℂ) → ℂ} {ε₀ ε₁ : ℝ} (hε₁ : 0 < ε₁) + (hε₁ε₀ : polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁ ⊆ + polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀) + (hfdiv : IsWeierstrassDivisionOn (fun z => z.2 ^ d) f f1 c + (polydisc (0 : ι → ℂ) (fun _ => ε₀)) ε₀) + (hcj0 : ∀ j, c j 0 = 0) + (hf1ne0' : ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁, f1 z ≠ 0) : + ∃ R₂ δ r₃ : ℝ, 0 < R₂ ∧ R₂ < ε₁ ∧ 0 < δ ∧ 0 < r₃ ∧ r₃ ≤ ε₁ / 2 ∧ + DifferentiableOn ℂ (fun z => weierstrassRemainder c z / f1 z) + (polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁) ∧ + (∀ j, Tendsto (c j) (𝓝 0) (𝓝 0)) ∧ + (∀ z ∈ closedPolydisc (0 : ι → ℂ) (fun _ => ε₁ / 2) ×ˢ closedBall (0 : ℂ) R₂, + δ ≤ ‖f1 z‖) ∧ + ∀ w ∈ polydisc (0 : ι → ℂ) (fun _ => r₃), ∀ ζ ∈ ball (0 : ℂ) R₂, + ‖weierstrassRemainder c (w, ζ) / f1 (w, ζ)‖ ≤ R₂ ^ d / (2 * (d + 1)) := by + have hpoly1sub : polydisc (0 : ι → ℂ) (fun _ => ε₁) ⊆ + polydisc (0 : ι → ℂ) (fun _ => ε₀) := + fun z hz => (hε₁ε₀ (Set.mk_mem_prod hz (mem_ball_self hε₁))).1 + have hcA1 : ∀ j, DifferentiableOn ℂ (c j) (polydisc (0 : ι → ℂ) (fun _ => ε₁)) := + fun j => (hfdiv.differentiableOn_coeff j).mono hpoly1sub + have hremA1 : DifferentiableOn ℂ (weierstrassRemainder c) + (polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁) := by + unfold weierstrassRemainder + apply DifferentiableOn.fun_sum + intro j _ + exact ((hcA1 j).comp differentiableOn_fst (fun z hz => hz.1)).mul + (differentiableOn_snd.pow (j : ℕ)) + have hf1A1 : DifferentiableOn ℂ f1 + (polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁) := + hfdiv.differentiableOn_quotient.mono hε₁ε₀ + have hhA1 : DifferentiableOn ℂ (fun z => weierstrassRemainder c z / f1 z) + (polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁) := by + simp_rw [div_eq_mul_inv] + exact hremA1.mul (hf1A1.inv hf1ne0') + set R₂ : ℝ := ε₁ / 2 with hR₂def + have hR₂pos : 0 < R₂ := by positivity + have hR₂ε₁ : R₂ < ε₁ := by rw [hR₂def]; linarith + set K : Set ((ι → ℂ) × ℂ) := + closedPolydisc (0 : ι → ℂ) (fun _ => ε₁ / 2) ×ˢ closedBall (0 : ℂ) R₂ with hKdef + have hKsub : K ⊆ polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁ := by + apply Set.prod_mono + · exact closedPolydisc_subset_polydisc _ (fun _ => by linarith) + · exact closedBall_subset_ball hR₂ε₁ + have hKcompact : IsCompact K := + (isCompact_closedPolydisc _ _).prod (isCompact_closedBall _ _) + have hKne : K.Nonempty := ⟨(0, 0), by + refine ⟨mem_closedPolydisc.mpr fun i => ?_, mem_closedBall_self hR₂pos.le⟩ + simpa using (half_pos hε₁).le⟩ + have hf1contK : ContinuousOn f1 K := (hf1A1.mono hKsub).continuousOn + obtain ⟨zmin, hzminK, hzminmin⟩ := hKcompact.exists_isMinOn hKne hf1contK.norm + set δ : ℝ := ‖f1 zmin‖ with hδdef + have hδpos : 0 < δ := norm_pos_iff.mpr (hf1ne0' zmin (hKsub hzminK)) + have hδle : ∀ z ∈ K, δ ≤ ‖f1 z‖ := fun z hz => hzminmin hz + have hcj0' : ∀ j : Fin d, Tendsto (c j) (𝓝 0) (𝓝 0) := fun j => + (hcj0 j) ▸ ((hcA1 j).continuousOn.continuousAt (isOpen_polydisc _ _ |>.mem_nhds + (mem_polydisc.mpr fun i => by simpa using half_pos hε₁))) + obtain ⟨r₃, hr₃pos, hr₃ε₁, hhbound⟩ := + exists_small_remainder_div hR₂pos hδpos (half_pos hε₁) hcj0' + (fun z hz => hδle z ⟨mem_closedPolydisc.mpr (fun i => (mem_polydisc.mp + hz.1 i).le), + ball_subset_closedBall hz.2⟩) + + exact ⟨R₂, δ, r₃, hR₂pos, hR₂ε₁, hδpos, hr₃pos, hr₃ε₁, hhA1, hcj0', hδle, + fun w hw ζ hζ => hhbound (w, ζ) ⟨hw, hζ⟩⟩ + +/-- Germ uniqueness for division by a normalized divisor. A fresh small-remainder estimate allows +comparison on any smaller neighborhood supporting the other decomposition; bounded fixed-point +uniqueness then identifies both germs. -/ +private theorem normalized_division_germ_unique {d : ℕ} {r₃ R₂ δ : ℝ} + {f f1 g S : (ι → ℂ) × ℂ → ℂ} {c aOut : Fin d → (ι → ℂ) → ℂ} + (hr₃pos : 0 < r₃) (hR₂pos : 0 < R₂) (hδpos : 0 < δ) + (hf1FINAL : DifferentiableOn ℂ f1 + (polydisc 0 (fun _ => r₃) ×ˢ ball 0 R₂)) + (hlower : ∀ z ∈ polydisc 0 (fun _ => r₃) ×ˢ ball 0 R₂, δ ≤ ‖f1 z‖) + (hcj0' : ∀ j, Tendsto (c j) (𝓝 0) (𝓝 0)) + (hhFINAL : DifferentiableOn ℂ (fun z => weierstrassRemainder c z / f1 z) + (polydisc 0 (fun _ => r₃) ×ˢ ball 0 R₂)) + (hf_eq2 : ∀ z ∈ polydisc 0 (fun _ => r₃) ×ˢ ball 0 R₂, + f z = f1 z * (z.2 ^ d + weierstrassRemainder c z / f1 z)) + (hfixed : IsWeierstrassDivisionOn (fun z => z.2 ^ d) + (g - (fun z => weierstrassRemainder c z / f1 z) * S) S aOut + (polydisc 0 (fun _ => r₃)) R₂) + {q' : (ι → ℂ) × ℂ → ℂ} {a' : Fin d → (ι → ℂ) → ℂ} + (hdiv' : IsWeierstrassDivisionAt f g q' a') : + (fun z => S z / f1 z) =ᶠ[𝓝 0] q' ∧ ∀ j, aOut j =ᶠ[𝓝 0] a' j := by + let domFINAL := polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂ + let hh := fun z => weierstrassRemainder c z / f1 z + let q := fun z => S z / f1 z + have hf1ne0FINAL : ∀ z ∈ domFINAL, f1 z ≠ 0 := + fun z hz => norm_pos_iff.mp (hδpos.trans_le (hlower z hz)) + have h00 : (0 : (ι → ℂ) × ℂ) ∈ domFINAL := + ⟨mem_polydisc.mpr fun i => by simpa using hr₃pos, mem_ball_self hR₂pos⟩ + obtain ⟨ρ₀, hρ₀pos, hρ₀sub, hlocal⟩ := hdiv'.exists_divisionOn + ((isOpen_polydisc _ _).prod isOpen_ball) h00 + obtain ⟨ρ, hρpos, hρρ₀⟩ := exists_between hρ₀pos + have hρsub : polydisc (0 : ι → ℂ) (fun _ => ρ) ×ˢ ball (0 : ℂ) ρ ⊆ domFINAL := + (Set.prod_mono (polydisc_mono _ (fun _ => hρρ₀.le)) + (ball_subset_ball hρρ₀.le)).trans hρ₀sub + -- The same small-remainder lemma applies at this smaller scalar radius. + obtain ⟨r₅, hr₅pos, hr₅ρ, hhb3⟩ := + exists_small_remainder_div hρpos hδpos hρpos hcj0' + (fun z hz => hlower z (hρsub hz)) + have hdomsub5 : polydisc (0 : ι → ℂ) (fun _ => r₅) ×ˢ ball (0 : ℂ) ρ ⊆ domFINAL := + fun z hz => hρsub ⟨polydisc_mono _ (fun _ => hr₅ρ) hz.1, hz.2⟩ + set dom5 : Set ((ι → ℂ) × ℂ) := polydisc (0 : ι → ℂ) (fun _ => r₅) ×ˢ ball (0 : ℂ) ρ + with hdom5def + have hlocalSub : dom5 ⊆ polydisc 0 (fun _ => ρ₀) ×ˢ ball 0 ρ₀ := + Set.prod_mono (polydisc_mono _ (fun _ => hr₅ρ.trans hρρ₀.le)) + (ball_subset_ball hρρ₀.le) + have hq'Adiff : DifferentiableOn ℂ q' dom5 := hlocal.differentiableOn_quotient.mono hlocalSub + have ha'Adiff : ∀ j, DifferentiableOn ℂ (a' j) (polydisc 0 (fun _ => r₅)) := + fun j => (hlocal.differentiableOn_coeff j).mono + (polydisc_mono _ (fun _ => hr₅ρ.trans hρρ₀.le)) + have hf1diff5 : DifferentiableOn ℂ f1 dom5 := hf1FINAL.mono hdomsub5 + set s' : (ι → ℂ) × ℂ → ℂ := fun z => q' z * f1 z with hs'def + have hs'diff : DifferentiableOn ℂ s' dom5 := hq'Adiff.mul hf1diff5 + have hhFINAL5 : DifferentiableOn ℂ hh dom5 := hhFINAL.mono hdomsub5 + have hpoly53 : polydisc (0 : ι → ℂ) (fun _ => r₅) ⊆ + polydisc (0 : ι → ℂ) (fun _ => r₃) := + fun w hw => (hdomsub5 (⟨hw, mem_ball_self hρpos⟩ : (w, (0:ℂ)) ∈ dom5)).1 + have hdiv' : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - hh * s') s' a' + (polydisc (0 : ι → ℂ) (fun _ => r₅)) ρ := by + refine ⟨hs'diff, ha'Adiff, ?_⟩ + intro z hz + have heqz : g z = q' z * f z + weierstrassRemainder a' z := hlocal.eq (hlocalSub hz) + have heqf5 : f z = f1 z * (z.2 ^ d + hh z) := hf_eq2 z (hdomsub5 hz) + show g z - hh z * s' z = s' z * z.2 ^ d + weierstrassRemainder a' z + simp only [hs'def] + rw [heqz, heqf5] + ring + have hSdiv : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - hh * S) S aOut + (polydisc (0 : ι → ℂ) (fun _ => r₅)) ρ := + ⟨hfixed.differentiableOn_quotient.mono hdomsub5, + fun j => (hfixed.differentiableOn_coeff j).mono hpoly53, fun _ hz => hfixed.eq (hdomsub5 hz)⟩ + -- Compact containment bounds the difference of the two fixed-point candidates. + let K := closedPolydisc (0 : ι → ℂ) (fun _ => ρ) ×ˢ closedBall (0 : ℂ) ρ + have hclosedsub : K ⊆ polydisc 0 (fun _ => ρ₀) ×ˢ ball 0 ρ₀ := + Set.prod_mono (closedPolydisc_subset_polydisc _ (fun _ => hρρ₀)) + (closedBall_subset_ball hρρ₀) + have hKfinal := hclosedsub.trans hρ₀sub + have hcompact : IsCompact K := + (isCompact_closedPolydisc _ _).prod (isCompact_closedBall _ _) + have hcont : ContinuousOn (fun z => S z - s' z) K := + (hfixed.differentiableOn_quotient.continuousOn.mono hKfinal).sub + ((hlocal.differentiableOn_quotient.continuousOn.mono hclosedsub).mul + (hf1FINAL.continuousOn.mono hKfinal)) + obtain ⟨C1, hC1⟩ := hcompact.bddAbove_image hcont.norm + have hM3b : ∀ z ∈ dom5, ‖S z - s' z‖ ≤ max C1 0 := by + intro z hz + apply (hC1 ⟨z, ?_, rfl⟩).trans (le_max_left _ _) + exact ⟨mem_closedPolydisc.mpr fun i => + (mem_polydisc.mp hz.1 i).le.trans hr₅ρ, ball_subset_closedBall hz.2⟩ + obtain ⟨hSeqs', haOuteqa'⟩ := eqOn_of_isWeierstrassDivisionOn_selfPerturbed + hρpos hh g S s' aOut a' hhFINAL5 hhb3 hSdiv hdiv' (max C1 0) (le_max_right _ _) hM3b + have hqeqq' : EqOn q q' dom5 := by + intro z hz + show S z / f1 z = q' z + rw [hSeqs' hz] + show s' z / f1 z = q' z + rw [hs'def] + exact mul_div_cancel_right₀ _ (hf1ne0FINAL z (hdomsub5 hz)) + have h05 : (0 : (ι → ℂ) × ℂ) ∈ dom5 := + ⟨mem_polydisc.mpr fun i => by simpa using hr₅pos, mem_ball_self hρpos⟩ + have hnbhd : dom5 ∈ 𝓝 (0 : (ι → ℂ) × ℂ) := + (isOpen_polydisc _ _ |>.prod isOpen_ball).mem_nhds h05 + refine ⟨Filter.eventuallyEq_of_mem hnbhd hqeqq', fun j => Filter.eventuallyEq_of_mem + ((isOpen_polydisc (0 : ι → ℂ) (fun _ => r₅)).mem_nhds + (mem_polydisc.mpr fun i => by simpa using hr₅pos)) (haOuteqa' j)⟩ + +/-- Undoing the nonvanishing leading factor converts a normalized fixed-point division into division +by the original divisor. The remainder is unchanged. -/ +private theorem divisionOn_div_leadingFactor {d : ℕ} {r : ι → ℝ} {R : ℝ} + {f f1 g h S : (ι → ℂ) × ℂ → ℂ} {a : Fin d → (ι → ℂ) → ℂ} + (hf1 : DifferentiableOn ℂ f1 (polydisc 0 r ×ˢ ball 0 R)) + (hne : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, f1 z ≠ 0) + (heq : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, f z = f1 z * (z.2 ^ d + h z)) + (hfixed : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - h * S) S a + (polydisc 0 r) R) : + IsWeierstrassDivisionOn f g (fun z => S z / f1 z) a (polydisc 0 r) R := by + refine ⟨?_, hfixed.differentiableOn_coeff, ?_⟩ + · change DifferentiableOn ℂ (fun z => S z / f1 z) _ + simp_rw [div_eq_mul_inv] + exact hfixed.differentiableOn_quotient.mul (hf1.inv hne) + · intro z hz + change g z = S z / f1 z * f z + weierstrassRemainder a z + have hqf : S z / f1 z * f z = S z * (z.2 ^ d + h z) := by + rw [heq z hz] + field_simp [hne z hz] + rw [hqf] + have h := hfixed.eq hz + dsimp only [Pi.sub_apply, Pi.mul_apply] at h + linear_combination h + +/-- **Weierstrass division ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.3).** A divisor whose +central +scalar slice has finite order `d` admits division of every bounded holomorphic numerator +on a fixed polydisc. The quotient bound is uniform in the numerator. Uniqueness is local, +so it also compares decompositions initially defined on smaller neighborhoods. +The proof combines normalization, the Picard limit, and local fixed-point uniqueness. -/ +theorem exists_isWeierstrassDivisionOn_of_bounded {d : ℕ} {f : (ι → ℂ) × ℂ → ℂ} + {U : Set ((ι → ℂ) × ℂ)} (hU : IsOpen U) (h0 : 0 ∈ U) + (hf : DifferentiableOn ℂ f U) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (r : ι → ℝ) (R C : ℝ), (∀ i, 0 < r i) ∧ 0 < R ∧ 0 < C ∧ + polydisc 0 r ×ˢ ball 0 R ⊆ U ∧ + ∀ (g : (ι → ℂ) × ℂ → ℂ), + DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R) → + ∀ M : ℝ, 0 ≤ M → (∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖g z‖ ≤ M) → + ∃ (q : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), + IsWeierstrassDivisionOn f g q a (polydisc 0 r) R ∧ + (∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖q z‖ ≤ C * M) ∧ + (∀ q' a', IsWeierstrassDivisionAt f g q' a' → + q =ᶠ[𝓝 0] q' ∧ ∀ j, a j =ᶠ[𝓝 0] a' j) := by + -- Normalize the divisor and choose a nonvanishing leading factor. + obtain ⟨f1, c, ε₀, ε₁, hε₀, hε₁, hε₀U, hfdiv, hcj0, hε₁ε₀, hf1ne0'⟩ := + exists_coordinatePower_leadingFactor_ne_zero hU h0 hf horder + -- Choose a domain on which the normalized perturbation contracts. + obtain ⟨R₂, δ, r₃, hR₂pos, hR₂ε₁, hδpos, hr₃pos, hr₃ε₁, hhA1, hcj0', hδle, hhbound⟩ := + exists_perturbation_bound_of_coordinatePower_leadingFactor hε₁ hε₁ε₀ hfdiv hcj0 hf1ne0' + set hh : (ι → ℂ) × ℂ → ℂ := fun z => weierstrassRemainder c z / f1 z with hhdef + set K : Set ((ι → ℂ) × ℂ) := + closedPolydisc (0 : ι → ℂ) (fun _ => ε₁ / 2) ×ˢ closedBall (0 : ℂ) R₂ with hKdef + -- Restrict to the common domain for all bounded numerators. + have hr₃ε₁' : r₃ ≤ ε₁ := hr₃ε₁.trans (by linarith) + have hR₂ε₁' : R₂ ≤ ε₁ := hR₂ε₁.le + have hFINALsubε₁ : polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂ ⊆ + polydisc (0 : ι → ℂ) (fun _ => ε₁) ×ˢ ball (0 : ℂ) ε₁ := + Set.prod_mono (polydisc_mono _ (fun _ => hr₃ε₁')) (ball_subset_ball hR₂ε₁') + have hFINALsub : polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂ ⊆ U := + hFINALsubε₁.trans (fun z hz => hε₀U (hε₁ε₀ hz)) + have hhFINAL : DifferentiableOn ℂ (fun z => weierstrassRemainder c z / f1 z) + (polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂) := + hhA1.mono hFINALsubε₁ + have hhboundFINAL : ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂, + ‖weierstrassRemainder c z / f1 z‖ ≤ R₂ ^ d / (2 * (d + 1)) := + fun z hz => hhbound z.1 hz.1 z.2 hz.2 + refine ⟨fun _ => r₃, R₂, 2 * ((d : ℝ) + 1) / (R₂ ^ d * δ), fun _ => hr₃pos, hR₂pos, + by positivity, hFINALsub, ?_⟩ + intro g hg M hM0 hMb + set domFINAL : Set ((ι → ℂ) × ℂ) := + polydisc (0 : ι → ℂ) (fun _ => r₃) ×ˢ ball (0 : ℂ) R₂ with hdomFINALdef + set sSeq := fun k => picardApprox d (fun _ => r₃) R₂ (fun _ => hr₃pos) hR₂pos hh g hg hhFINAL k + with hsSeqdef + set B : ℝ := ((d + 1 : ℕ) : ℝ) / R₂ ^ d * M with hBdef + obtain ⟨S, hSanalytic, hSbound⟩ := exists_tendstoUniformlyOn_picardApprox d (fun _ => r₃) R₂ + (fun _ => hr₃pos) hR₂pos hh g hg hhFINAL M hM0 hMb hhboundFINAL + obtain ⟨aOut, haFINAL, hkey⟩ := exists_weierstrassRemainder_eq_of_tendstoUniformlyOn_picardApprox + d (fun _ => r₃) R₂ (fun _ => hr₃pos) hR₂pos hh g hg hhFINAL hhboundFINAL M hM0 S + hSanalytic.differentiableOn hSbound + -- Undo normalization, retaining the uniform quotient estimate. + have hf1ne0FINAL : ∀ z ∈ domFINAL, f1 z ≠ 0 := fun z hz => hf1ne0' z (hFINALsubε₁ hz) + have hf_eq2 : ∀ z ∈ domFINAL, f z = f1 z * (z.2 ^ d + hh z) := by + intro z hz + have hz0 : z ∈ polydisc (0 : ι → ℂ) (fun _ => ε₀) ×ˢ ball (0 : ℂ) ε₀ := + hε₁ε₀ (hFINALsubε₁ hz) + have h1 : f z = f1 z * z.2 ^ d + weierstrassRemainder c z := hfdiv.eq hz0 + have h2 : weierstrassRemainder c z = hh z * f1 z := by + show weierstrassRemainder c z = weierstrassRemainder c z / f1 z * f1 z + rw [div_mul_cancel₀ _ (hf1ne0FINAL z hz)] + rw [h2] at h1 + rw [h1]; ring + set q : (ι → ℂ) × ℂ → ℂ := fun z => S z / f1 z with hqdef + have hf1FINAL : DifferentiableOn ℂ f1 domFINAL := + hfdiv.differentiableOn_quotient.mono (hFINALsubε₁.trans hε₁ε₀) + have hfixed : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - hh * S) S aOut + (polydisc 0 (fun _ => r₃)) R₂ := by + refine ⟨hSanalytic.differentiableOn, haFINAL, ?_⟩ + intro z hz + have h := hkey z.1 hz.1 z.2 hz.2 + dsimp only [Pi.sub_apply, Pi.mul_apply] + linear_combination h + have hdivision := divisionOn_div_leadingFactor hf1FINAL hf1ne0FINAL hf_eq2 hfixed + have hdomFINALsubK : domFINAL ⊆ K := by + apply Set.prod_mono + · intro w hw + exact mem_closedPolydisc.mpr fun i => + (mem_polydisc.mp hw i).le.trans hr₃ε₁ + · exact ball_subset_closedBall + refine ⟨q, aOut, hdivision, ?_, ?_⟩ + · intro z hz + have hS0eq : (sSeq 0).1 = 0 := rfl + have hb0 := hSbound 0 z hz + rw [hS0eq] at hb0 + have hSb : ‖S z‖ ≤ 2 * B := by + have hthis : ‖(0:ℂ) - S z‖ ≤ B * (1/2)^0 / (1 - 1/2) := hb0 + rw [zero_sub, norm_neg] at hthis + norm_num at hthis + linarith + have hf1ge : δ ≤ ‖f1 z‖ := hδle _ (hdomFINALsubK hz) + have hf1pos' : 0 < ‖f1 z‖ := hδpos.trans_le hf1ge + show ‖S z / f1 z‖ ≤ 2 * ((d:ℝ) + 1) / (R₂ ^ d * δ) * M + rw [norm_div] + calc ‖S z‖ / ‖f1 z‖ ≤ (2 * B) / ‖f1 z‖ := div_le_div_of_nonneg_right hSb hf1pos'.le + _ ≤ (2 * B) / δ := div_le_div_of_nonneg_left (by positivity) hδpos hf1ge + _ = 2 * ((d:ℝ) + 1) / (R₂ ^ d * δ) * M := by + rw [hBdef]; push_cast; field_simp + · intro q' a' hdiv' + exact normalized_division_germ_unique hr₃pos hR₂pos hδpos hf1FINAL + (fun z hz => hδle z (hdomFINALsubK hz)) hcj0' hhFINAL hf_eq2 + hfixed hdiv' + +/-- Analytic Weierstrass division for arbitrary numerator germs. No boundedness assumption is needed +because the representatives can be restricted to a smaller neighborhood. The uniform division +theorem supplies the quotient and its germ uniqueness. -/ +theorem exists_isWeierstrassDivisionAt {d : ℕ} {f g : (ι → ℂ) × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (q : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), + IsWeierstrassDivisionAt f g q a ∧ + ∀ q' a', IsWeierstrassDivisionAt f g q' a' → + q =ᶠ[𝓝 0] q' ∧ ∀ j, a j =ᶠ[𝓝 0] a' j := by + have hb : ∀ᶠ z in 𝓝 0, ‖g z‖ < ‖g 0‖ + 1 := + hg.continuousAt.norm.eventually_lt_const (lt_add_one _) + obtain ⟨U, hsub, hU, h0⟩ := _root_.eventually_nhds_iff.mp + (hf.eventually_analyticAt.and (hg.eventually_analyticAt.and hb)) + obtain ⟨r, R, C, hr, hR, _, hPU, hdiv⟩ := + exists_isWeierstrassDivisionOn_of_bounded hU h0 + (fun z hz => (hsub z hz).1.differentiableAt.differentiableWithinAt) + horder + obtain ⟨q, a, hqa, _, huniq⟩ := hdiv g + (fun z hz => (hsub z (hPU hz)).2.1.differentiableAt.differentiableWithinAt) + (‖g 0‖ + 1) (by positivity) (fun z hz => (hsub z (hPU hz)).2.2.le) + refine ⟨q, a, hqa.at_zero (isOpen_polydisc _ _) ?_ hR, huniq⟩ + simpa using hr + +/-- Two local division decompositions agree as germs, including every remainder coefficient. This +follows from the uniform division theorem. -/ +theorem IsWeierstrassDivisionAt.unique {d : ℕ} {f g q q' : (ι → ℂ) × ℂ → ℂ} + {a a' : Fin d → (ι → ℂ) → ℂ} + (h : IsWeierstrassDivisionAt f g q a) (h' : IsWeierstrassDivisionAt f g q' a') + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + q =ᶠ[𝓝 0] q' ∧ ∀ j, a j =ᶠ[𝓝 0] a' j := by + obtain ⟨q₀, a₀, _, hu⟩ := exists_isWeierstrassDivisionAt hf hg horder + exact ⟨(hu q a h).1.symm.trans (hu q' a' h').1, + fun j => ((hu q a h).2 j).symm.trans ((hu q' a' h').2 j)⟩ + +/-- Local uniqueness extends to the whole product domain by the identity theorem. In particular this +gives uniqueness on the fixed polydisc in the bounded division theorem. -/ +theorem IsWeierstrassDivisionOn.unique {d : ℕ} {f g q q' : (ι → ℂ) × ℂ → ℂ} + {a a' : Fin d → (ι → ℂ) → ℂ} {V : Set (ι → ℂ)} {R : ℝ} + (h : IsWeierstrassDivisionOn f g q a V R) (h' : IsWeierstrassDivisionOn f g q' a' V R) + (hV : IsOpen V) (hconn : IsPreconnected V) (h0 : 0 ∈ V) (hR : 0 < R) + (hf : DifferentiableOn ℂ f (V ×ˢ ball 0 R)) + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + EqOn q q' (V ×ˢ ball 0 R) ∧ ∀ j, EqOn (a j) (a' j) V := by + have hz : (0 : (ι → ℂ) × ℂ) ∈ V ×ˢ ball 0 R := ⟨h0, mem_ball_self hR⟩ + have ho : IsOpen (V ×ˢ ball (0 : ℂ) R) := hV.prod isOpen_ball + obtain ⟨hq, ha⟩ := (h.at_zero hV h0 hR).unique (h'.at_zero hV h0 hR) + ((hf.analyticOnNhd_of_finiteDimensional ho) _ hz) + ((hg.analyticOnNhd_of_finiteDimensional ho) _ hz) horder + exact ⟨DifferentiableOn.eqOn_of_preconnected_of_eventuallyEq ho + (hconn.prod (convex_ball (0 : ℂ) R).isPreconnected) + h.differentiableOn_quotient h'.differentiableOn_quotient hz hq, + fun j => DifferentiableOn.eqOn_of_preconnected_of_eventuallyEq hV hconn + (h.differentiableOn_coeff j) (h'.differentiableOn_coeff j) h0 (ha j)⟩ + +/-- Division transports along a continuous linear equivalence of the parameter space. -/ +theorem IsWeierstrassDivisionAt.comp_equiv {F : Type*} [NormedAddCommGroup F] + [NormedSpace ℂ F] (φ : F ≃L[ℂ] E) {d : ℕ} {f g q : E × ℂ → ℂ} {a : Fin d → E → ℂ} + (h : IsWeierstrassDivisionAt f g q a) : + IsWeierstrassDivisionAt (fun z : F × ℂ => f (φ z.1, z.2)) (fun z : F × ℂ => g (φ z.1, z.2)) + (fun z : F × ℂ => q (φ z.1, z.2)) (fun j x => a j (φ x)) := by + have hφ : AnalyticAt ℂ φ (0 : F) := φ.toContinuousLinearMap.analyticAt 0 + have hφmap : φ (0 : F) = 0 := φ.map_zero + have hpair : AnalyticAt ℂ (fun z : F × ℂ => (φ z.1, z.2)) (0 : F × ℂ) := + (hφ.comp_of_eq analyticAt_fst rfl).prod analyticAt_snd + have h0 : (fun z : F × ℂ => (φ z.1, z.2)) 0 = (0 : E × ℂ) := by simp [hφmap] + have ht : Tendsto (fun z : F × ℂ => (φ z.1, z.2)) (𝓝 0) (𝓝 (0 : E × ℂ)) := by + rw [← h0]; exact hpair.continuousAt.tendsto + refine ⟨h.analyticAt_quotient.comp_of_eq hpair h0, + fun j => (h.analyticAt_coeff j).comp_of_eq hφ hφmap, + (h.eq.comp_tendsto ht).mono fun z hz => by + simpa [weierstrassRemainder] using hz⟩ + +/-- **Weierstrass division for analytic germs on any finite-dimensional parameter space.** +Obtained by transporting the coordinate version along a basis; no choice of coordinates +occurs in the statement. -/ +theorem exists_isWeierstrassDivisionAt_of_finiteDimensional [FiniteDimensional ℂ E] {d : ℕ} + {f g : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (q : E × ℂ → ℂ) (a : Fin d → E → ℂ), + IsWeierstrassDivisionAt f g q a ∧ + ∀ q' a', IsWeierstrassDivisionAt f g q' a' → + q =ᶠ[𝓝 0] q' ∧ ∀ j, a j =ᶠ[𝓝 0] a' j := by + set e := (Module.finBasis ℂ E).equivFunL with he_def + set fg : (Fin (Module.finrank ℂ E) → ℂ) × ℂ → ℂ := fun z => f (e.symm z.1, z.2) with hfg_def + set gg : (Fin (Module.finrank ℂ E) → ℂ) × ℂ → ℂ := fun z => g (e.symm z.1, z.2) with hgg_def + have hfg0 : (fun w : ℂ => fg (0, w)) = fun w : ℂ => f (0, w) := by funext w; simp [hfg_def] + have hfgan : AnalyticAt ℂ fg 0 := + hf.comp_of_eq (((e.symm.toContinuousLinearMap.analyticAt 0).comp_of_eq analyticAt_fst rfl).prod + analyticAt_snd) (by simp) + have hggan : AnalyticAt ℂ gg 0 := + hg.comp_of_eq (((e.symm.toContinuousLinearMap.analyticAt 0).comp_of_eq analyticAt_fst rfl).prod + analyticAt_snd) (by simp) + have hfgorder : analyticOrderAt (fun w : ℂ => fg (0, w)) 0 = d := by rw [hfg0]; exact horder + obtain ⟨q, a, Hq, huniqq⟩ := exists_isWeierstrassDivisionAt hfgan hggan hfgorder + have hf_eq : f = fun z : E × ℂ => fg (e z.1, z.2) := by funext z; simp [hfg_def] + have hg_eq : g = fun z : E × ℂ => gg (e z.1, z.2) := by funext z; simp [hgg_def] + have Hf : IsWeierstrassDivisionAt f g (fun z : E × ℂ => q (e z.1, z.2)) + (fun j x => a j (e x)) := by + rw [hf_eq, hg_eq]; exact Hq.comp_equiv e + refine ⟨_, _, Hf, fun q' a' Hq' => ?_⟩ + have Hq'' : IsWeierstrassDivisionAt fg gg (fun z => q' (e.symm z.1, z.2)) + (fun j x => a' j (e.symm x)) := by + rw [hfg_def, hgg_def]; exact Hq'.comp_equiv e.symm + obtain ⟨huq, hab⟩ := huniqq _ _ Hq'' + have ht : Tendsto (fun z : E × ℂ => (e z.1, z.2)) (𝓝 0) + (𝓝 (0 : (Fin (Module.finrank ℂ E) → ℂ) × ℂ)) := by + have h0 : (fun z : E × ℂ => (e z.1, z.2)) 0 = (0 : (Fin (Module.finrank ℂ E) → ℂ) × ℂ) := by + simp + rw [← h0] + exact (((e.toContinuousLinearMap.analyticAt 0).comp_of_eq analyticAt_fst rfl).prod + analyticAt_snd).continuousAt.tendsto + refine ⟨(huq.comp_tendsto ht).mono fun z hz => ?_, fun j => ?_⟩ + · simpa using hz + · have htj : Tendsto e (𝓝 (0 : E)) (𝓝 (0 : Fin (Module.finrank ℂ E) → ℂ)) := by + simpa using (e.toContinuousLinearMap.analyticAt 0).continuousAt.tendsto + exact ((hab j).comp_tendsto htj).mono fun x hx => by simpa using hx + +/-- A local division identity is an identity in the project's ring of analytic germs. -/ +theorem IsWeierstrassDivisionAt.germ_eq {d : ℕ} {f g q : E × ℂ → ℂ} + {a : Fin d → E → ℂ} (h : IsWeierstrassDivisionAt f g q a) + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) : + AnalyticGerm.ofAnalyticAt g hg = + AnalyticGerm.ofAnalyticAt q h.analyticAt_quotient * AnalyticGerm.ofAnalyticAt f hf + + AnalyticGerm.ofAnalyticAt (weierstrassRemainder a) + (analyticAt_weierstrassRemainder h.analyticAt_coeff) := by + apply Subtype.ext + exact Germ.coe_eq.mpr h.eq + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean new file mode 100644 index 0000000000..97f7caf364 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean @@ -0,0 +1,167 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc + +/-! +# Weierstrass division predicates + +A remainder of degree less than `d` is represented by its `Fin d` coefficient functions on the +parameter space. We define division at the origin and on a product domain, prove the elementary +order-zero case, and pass between local division and division on a sufficiently small polydisc. +The case `d = 0` and empty finite parameter index types are included. + +The existence theorem for a general divisor is in `SeveralComplexVariables.WeierstrassDivision`. + +## Main definitions + +* `weierstrassRemainder`: Evaluate a polynomial of degree less than `d` in the distinguished scalar + coordinate. +* `IsWeierstrassDivisionAt`: Local analytic division, with remainder degree encoded by its + coefficient index. +* `IsWeierstrassDivisionOn`: Division on a product of a parameter domain and a scalar disc. + +## Main results + +* `IsWeierstrassDivisionOn.at_zero`: An open-domain division identity induces division at the + origin. +* `isWeierstrassDivisionAt_zero`: Division by a nonvanishing analytic function is ordinary division, + with zero remainder. +* `IsWeierstrassDivisionAt.exists_divisionOn`: A germ division identity holds as a holomorphic + division on a sufficiently small polydisc-ball inside any prescribed open neighborhood of the + origin. +-/ + +public noncomputable section + +open Complex Filter Finset Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- Evaluate a polynomial of degree less than `d` in the distinguished scalar coordinate. The +coefficients are functions of the parameter alone. -/ +@[expose] def weierstrassRemainder {d : ℕ} (a : Fin d → E → ℂ) (z : E × ℂ) : ℂ := + ∑ j : Fin d, a j z.1 * z.2 ^ (j : ℕ) + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] in +/-- The only remainder of degree less than zero is the zero function. -/ +@[simp] theorem weierstrassRemainder_zero (a : Fin 0 → E → ℂ) : + weierstrassRemainder a = 0 := by + funext z + simp [weierstrassRemainder] + +/-- Analytic coefficients give a jointly analytic polynomial in the scalar coordinate. -/ +theorem analyticAt_weierstrassRemainder {d : ℕ} {a : Fin d → E → ℂ} {z : E × ℂ} + (ha : ∀ j, AnalyticAt ℂ (a j) z.1) : AnalyticAt ℂ (weierstrassRemainder a) z := by + apply Finset.analyticAt_fun_sum + intro j _ + exact ((ha j).comp analyticAt_fst).mul (analyticAt_snd.pow (j : ℕ)) + +/-- Local analytic division, with remainder degree encoded by its coefficient index. -/ +structure IsWeierstrassDivisionAt {d : ℕ} (f g q : E × ℂ → ℂ) + (a : Fin d → E → ℂ) : Prop where + /-- The quotient is analytic at the origin. -/ + analyticAt_quotient : AnalyticAt ℂ q 0 + /-- Each remainder coefficient is analytic at the parameter origin. -/ + analyticAt_coeff : ∀ j, AnalyticAt ℂ (a j) 0 + /-- As germs, the dividend equals quotient times divisor plus remainder. -/ + eq : g =ᶠ[𝓝 0] fun z => q z * f z + weierstrassRemainder a z + +/-- Division on a product of a parameter domain and a scalar disc. -/ +structure IsWeierstrassDivisionOn {d : ℕ} (f g q : E × ℂ → ℂ) + (a : Fin d → E → ℂ) (V : Set E) (R : ℝ) : Prop where + /-- The quotient is holomorphic on the product domain. -/ + differentiableOn_quotient : DifferentiableOn ℂ q (V ×ˢ ball 0 R) + /-- Each remainder coefficient is holomorphic on the parameter domain. -/ + differentiableOn_coeff : ∀ j, DifferentiableOn ℂ (a j) V + /-- On the product domain, the dividend equals quotient times divisor plus remainder. -/ + eq : EqOn g (fun z => q z * f z + weierstrassRemainder a z) (V ×ˢ ball 0 R) + +/-- An open-domain division identity induces division at the origin. -/ +theorem IsWeierstrassDivisionOn.at_zero [FiniteDimensional ℂ E] + {d : ℕ} {f g q : E × ℂ → ℂ} {a : Fin d → E → ℂ} {V : Set E} {R : ℝ} + (h : IsWeierstrassDivisionOn f g q a V R) (hV : IsOpen V) (h0 : 0 ∈ V) + (hR : 0 < R) : IsWeierstrassDivisionAt f g q a := by + have hz : (0 : E × ℂ) ∈ V ×ˢ ball 0 R := ⟨h0, mem_ball_self hR⟩ + exact ⟨(h.differentiableOn_quotient.analyticOnNhd_of_finiteDimensional + (hV.prod isOpen_ball)) _ hz, + fun j => ((h.differentiableOn_coeff j).analyticOnNhd_of_finiteDimensional hV) _ h0, + Filter.mem_of_superset ((hV.prod isOpen_ball).mem_nhds hz) (fun _ hx => h.eq hx)⟩ + +/-- Division by a nonvanishing analytic function is ordinary division, with zero remainder. This +proves the order-zero existence case without Weierstrass division. -/ +theorem isWeierstrassDivisionAt_zero {f g : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (hg : AnalyticAt ℂ g 0) (h0 : f 0 ≠ 0) : + IsWeierstrassDivisionAt f g (fun z => g z / f z) (fun j : Fin 0 => Fin.elim0 j) := by + refine ⟨hg.div hf h0, fun j => Fin.elim0 j, ?_⟩ + filter_upwards [hf.continuousAt.eventually_ne h0] with z hz + simp [weierstrassRemainder, hz] + +/-- In order zero the quotient germ is unique whenever the divisor is nonvanishing. -/ +theorem IsWeierstrassDivisionAt.unique_zero {f g q q' : E × ℂ → ℂ} + {a a' : Fin 0 → E → ℂ} (h : IsWeierstrassDivisionAt f g q a) + (h' : IsWeierstrassDivisionAt f g q' a') + (hf : AnalyticAt ℂ f 0) (h0 : f 0 ≠ 0) : q =ᶠ[𝓝 0] q' := by + filter_upwards [h.eq, h'.eq, hf.continuousAt.eventually_ne h0] with z hz hz' hne + have he : q z * f z = q' z * f z := by simpa using hz.symm.trans hz' + exact mul_right_cancel₀ hne he + +/-- The Weierstrass remainder is linear (here, additive) in its coefficient tuple. -/ +theorem weierstrassRemainder_sub {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {d : ℕ} (a b : Fin d → E → ℂ) (z : E × ℂ) : + weierstrassRemainder a z - weierstrassRemainder b z = + weierstrassRemainder (fun j => a j - b j) z := by + unfold weierstrassRemainder + rw [← Finset.sum_sub_distrib] + exact Finset.sum_congr rfl fun j _ => by simp; ring + +variable {ι : Type*} [Fintype ι] + +/-- Every open neighborhood of the origin in `(ι → ℂ) × ℂ` contains a product of a constant-radius +polydisc and a ball of the same radius. -/ +theorem exists_polydisc_ball_subset {U : Set ((ι → ℂ) × ℂ)} + (hU : IsOpen U) (h0 : (0 : (ι → ℂ) × ℂ) ∈ U) : + ∃ ε : ℝ, 0 < ε ∧ polydisc (0 : ι → ℂ) (fun _ => ε) ×ˢ ball (0 : ℂ) ε ⊆ U := by + obtain ⟨ε, hε, hsub⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds h0) + refine ⟨ε, hε, fun z hz => hsub ?_⟩ + rw [mem_ball, dist_zero_right, Prod.norm_def] + rw [polydisc_const_eq_ball (0 : ι → ℂ) hε] at hz + obtain ⟨h1, h2⟩ := hz + apply max_lt + · simpa [mem_ball, dist_zero_right] using h1 + · simpa [mem_ball, dist_zero_right] using h2 + +/-- A germ division identity holds as a holomorphic division on a sufficiently small polydisc-ball +inside any prescribed open neighborhood of the origin. -/ +theorem IsWeierstrassDivisionAt.exists_divisionOn {d : ℕ} + {f g q : (ι → ℂ) × ℂ → ℂ} {a : Fin d → (ι → ℂ) → ℂ} + (h : IsWeierstrassDivisionAt f g q a) + {U : Set ((ι → ℂ) × ℂ)} (hU : IsOpen U) (h0 : 0 ∈ U) : + ∃ ρ : ℝ, 0 < ρ ∧ polydisc 0 (fun _ => ρ) ×ˢ ball 0 ρ ⊆ U ∧ + IsWeierstrassDivisionOn f g q a (polydisc 0 (fun _ => ρ)) ρ := by + obtain ⟨V, hV, hVo, hV0⟩ := _root_.eventually_nhds_iff.mp + (h.analyticAt_quotient.eventually_analyticAt.and h.eq) + obtain ⟨W, hW, hWo, hW0⟩ := _root_.eventually_nhds_iff.mp + (Filter.eventually_all.mpr fun j => (h.analyticAt_coeff j).eventually_analyticAt) + obtain ⟨ρ, hρ, hsub⟩ := exists_polydisc_ball_subset + (hVo.inter ((hWo.prod isOpen_univ).inter hU)) ⟨hV0, ⟨hW0, trivial⟩, h0⟩ + refine ⟨ρ, hρ, fun z hz => (hsub hz).2.2, ?_, ?_, ?_⟩ + · intro z hz + exact (hV z (hsub hz).1).1.differentiableAt.differentiableWithinAt + · intro j w hw + exact (hW w (hsub (show (w, (0 : ℂ)) ∈ _ from ⟨hw, mem_ball_self hρ⟩)).2.1.1 + j).differentiableAt.differentiableWithinAt + · intro z hz + exact (hV z (hsub hz).1).2 + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean new file mode 100644 index 0000000000..e972632858 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean @@ -0,0 +1,748 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Algebra.Field.GeomSum +public import Mathlib.Analysis.Analytic.Order +public import Mathlib.Analysis.Calculus.IteratedDeriv.Lemmas +public import Mathlib.Analysis.Complex.AbsMax +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic + +/-! +# Division by a coordinate power + +Cauchy integrals construct division by `z.2 ^ d`, with a remainder of degree less than `d`. We +establish holomorphic dependence on the parameters, compatibility of the quotient at different +integration radii, uniqueness, and the uniform quotient estimate for bounded numerators. + +The main result is `coordinatePower_division`, corresponding to +[Jakóbczak–Jarnicki][JakobczakJarnicki2021], Lemma 1.7.4. + +## Main results + +* `coordinatePower_division`: **Coordinate-power division + ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.4).** Every holomorphic function on a polydisc + has a unique quotient and polynomial remainder on division by `w^d`. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex Filter Finset Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +variable {ι : Type*} [Fintype ι] + +/-- Algebraic splitting of the Cauchy kernel into a polynomial part of degree `< d` and a remainder +with a factor `w^d`. -/ +theorem weierstrass_kernel_identity (d : ℕ) {s w : ℂ} (hs : s ≠ 0) (hsw : s ≠ w) : + (∑ j ∈ range d, w ^ j / s ^ (j + 1)) + w ^ d / (s ^ d * (s - w)) = (s - w)⁻¹ := by + have hne : s - w ≠ 0 := sub_ne_zero.mpr hsw + have hsne : s ^ d ≠ 0 := pow_ne_zero d hs + have hgeom : ∑ i ∈ range d, s ^ i * w ^ (d - 1 - i) = (s ^ d - w ^ d) / (s - w) := + (Commute.all s w).geom_sum₂ hsw d + have hpoly : ∑ j ∈ range d, w ^ j / s ^ (j + 1) = (s ^ d - w ^ d) / (s ^ d * (s - w)) := by + have hreindex : ∑ i ∈ range d, w ^ (d - 1 - i) / s ^ (d - i) = + ∑ j ∈ range d, w ^ j / s ^ (j + 1) := by + refine Eq.trans ?_ (sum_range_reflect (fun j => w ^ j / s ^ (j + 1)) d) + refine sum_congr rfl fun i hi => ?_ + have : d - 1 - i + 1 = d - i := by + have := mem_range.mp hi + omega + rw [this] + trans ∑ i ∈ range d, w ^ (d - 1 - i) / s ^ (d - i) + · exact hreindex.symm + trans (∑ i ∈ range d, s ^ i * w ^ (d - 1 - i)) / s ^ d + · rw [sum_div] + refine sum_congr rfl fun i hi => ?_ + have hle : i ≤ d := (mem_range.mp hi).le + have hsi : s ^ (d - i) ≠ 0 := pow_ne_zero _ hs + field_simp [hsne, hsi, pow_ne_zero i hs] + rw [mul_assoc, ← pow_add, Nat.sub_add_cancel hle] + · rw [hgeom, div_div, mul_comm (s - w)] + have hsplit : (s ^ d - w ^ d) / (s ^ d * (s - w)) + w ^ d / (s ^ d * (s - w)) = + (s - w)⁻¹ := by + rw [← add_div, sub_add_cancel, div_mul_eq_div_div, div_self hsne, one_div] + rw [hpoly, hsplit] + +/-- A jointly holomorphic function on a product remains holomorphic in the last coordinate. -/ +theorem differentiableOn_snd_slice {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {V : Set E} {R : ℝ} {g : E × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {z : E} (hz : z ∈ V) : + DifferentiableOn ℂ (fun w => g (z, w)) (ball 0 R) := by + intro w hw + exact (hg (z, w) ⟨hz, hw⟩).comp w + ((differentiableAt_const z).prodMk differentiableAt_id).differentiableWithinAt + (fun t ht => ⟨hz, ht⟩) + +/-- Restricting a product slice to a strictly smaller disc gives continuity up to the closed +disc. -/ +theorem diffContOnCl_snd_slice {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {V : Set E} {R ρ : ℝ} {g : E × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {z : E} (hz : z ∈ V) + (hρ : 0 < ρ) (hρR : ρ < R) : + DiffContOnCl ℂ (fun w => g (z, w)) (ball 0 ρ) := by + refine ⟨(differentiableOn_snd_slice hg hz).mono (ball_subset_ball hρR.le), ?_⟩ + rw [closure_ball _ hρ.ne'] + exact hg.continuousOn.comp (continuousOn_const.prodMk continuousOn_id) + (fun w hw => ⟨hz, closedBall_subset_ball hρR hw⟩) + +/-- The Taylor coefficients of a polynomial remainder of degree less than `d`. -/ +theorem iteratedDeriv_weierstrassRemainder_const {d : ℕ} (a : Fin d → ℂ) (k : ℕ) : + iteratedDeriv k (fun w : ℂ => ∑ j : Fin d, a j * w ^ (j : ℕ)) 0 = + if h : k < d then (k.factorial : ℂ) * a ⟨k, h⟩ else 0 := by + have hsum := iteratedDeriv_fun_sum (I := Finset.univ) (n := k) + (f := fun j : Fin d => fun w : ℂ => a j * w ^ (j : ℕ)) + (x := (0 : ℂ)) (fun _ _ => by fun_prop) + simp only [hsum, iteratedDeriv_const_mul_field, iteratedDeriv_fun_pow_zero] + split_ifs with hk + · rw [Fintype.sum_eq_single ⟨k, hk⟩] + · simp [mul_comm] + · intro j hj + have hjk : k ≠ (j : ℕ) := by + intro h + exact hj (Fin.ext h.symm) + simp [hjk] + · apply Finset.sum_eq_zero + intro j _ + have hjk : k ≠ (j : ℕ) := + ne_of_gt (j.isLt.trans_le (le_of_not_gt hk)) + simp [hjk] + +/-- In coordinate-power division the remainder coefficients are the Taylor coefficients of the +last-coordinate slice. -/ +theorem coeff_eq_iteratedDeriv_of_coordinatePower_division {d : ℕ} + {V : Set (ι → ℂ)} {R : ℝ} {g q : (ι → ℂ) × ℂ → ℂ} {a : Fin d → (ι → ℂ) → ℂ} + (h : IsWeierstrassDivisionOn (fun z => z.2 ^ d) g q a V R) + (hR : 0 < R) {z : ι → ℂ} (hz : z ∈ V) (j : Fin d) : + a j z = ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun w => g (z, w)) 0 := by + have hz0 : (0 : ℂ) ∈ ball 0 R := mem_ball_self hR + have hqA : AnalyticAt ℂ (fun w => q (z, w)) 0 := + ((differentiableOn_snd_slice h.differentiableOn_quotient hz).analyticOnNhd_of_finiteDimensional + isOpen_ball) _ hz0 + have hpow : AnalyticAt ℂ (fun w : ℂ => w ^ d) 0 := analyticAt_id.pow d + have hprod : AnalyticAt ℂ (fun w => w ^ d * q (z, w)) 0 := hpow.mul hqA + have hrem : AnalyticAt ℂ (fun w => ∑ k : Fin d, a k z * w ^ (k : ℕ)) 0 := by fun_prop + have hid : (fun w => g (z, w)) =ᶠ[𝓝 0] + (fun w => w ^ d * q (z, w) + ∑ k : Fin d, a k z * w ^ (k : ℕ)) := + Filter.mem_of_superset (isOpen_ball.mem_nhds hz0) fun w hw => by + have hmem : (z, w) ∈ V ×ˢ ball (0 : ℂ) R := ⟨hz, hw⟩ + simpa [weierstrassRemainder, mul_comm] using h.eq hmem + have hord : (d : ℕ∞) ≤ analyticOrderAt (fun w => w ^ d * q (z, w)) 0 := by + have hmul := analyticOrderAt_mul hpow hqA + have hpow' : analyticOrderAt (fun w : ℂ => w ^ d) 0 = d := by + have h := analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ) (z := (0 : ℂ))) d + simpa [analyticOrderAt_id, Pi.pow_def] using h + have heq : analyticOrderAt (fun w => w ^ d * q (z, w)) 0 = + analyticOrderAt ((fun w : ℂ => w ^ d) * fun w => q (z, w)) 0 := by + congr 1 + rw [heq, hmul, hpow'] + exact le_self_add + have hvan (k : ℕ) (hk : k < d) : + iteratedDeriv k (fun w => w ^ d * q (z, w)) 0 = 0 := + ((natCast_le_analyticOrderAt_iff_iteratedDeriv_eq_zero hprod).mp hord) k hk + have hder := hid.iteratedDeriv_eq (j : ℕ) + have hadd : + iteratedDeriv (j : ℕ) + (fun w => w ^ d * q (z, w) + ∑ k : Fin d, a k z * w ^ (k : ℕ)) 0 = + iteratedDeriv (j : ℕ) (fun w => w ^ d * q (z, w)) 0 + + iteratedDeriv (j : ℕ) (fun w => ∑ k : Fin d, a k z * w ^ (k : ℕ)) 0 := by + convert iteratedDeriv_add (n := (j : ℕ)) (x := (0 : ℂ)) + hprod.contDiffAt hrem.contDiffAt + have hj : (j : ℕ) < d := j.isLt + rw [hder, hadd, hvan _ hj, zero_add, iteratedDeriv_weierstrassRemainder_const, dite_eq_left hj] + field_simp [Nat.cast_ne_zero.mpr (Nat.factorial_ne_zero (j : ℕ))] + +/-- Coordinate-power decompositions are unique: remainder coefficients are Taylor coefficients of +the last-coordinate slice, and the quotient is then recovered from the identity. Continuity +fills in the central fibre `w = 0`. -/ +theorem unique_coordinatePower_division {d : ℕ} {V : Set (ι → ℂ)} {R : ℝ} + {g q q' : (ι → ℂ) × ℂ → ℂ} {a a' : Fin d → (ι → ℂ) → ℂ} + (h : IsWeierstrassDivisionOn (fun z => z.2 ^ d) g q a V R) + (h' : IsWeierstrassDivisionOn (fun z => z.2 ^ d) g q' a' V R) + (hR : 0 < R) : + EqOn q q' (V ×ˢ ball 0 R) ∧ ∀ j, EqOn (a j) (a' j) V := by + have ha (j : Fin d) : EqOn (a j) (a' j) V := by + intro z hz + exact (coeff_eq_iteratedDeriv_of_coordinatePower_division h hR hz j).trans + (coeff_eq_iteratedDeriv_of_coordinatePower_division h' hR hz j).symm + refine ⟨?_, ha⟩ + intro z hz + have hrem : weierstrassRemainder a z = weierstrassRemainder a' z := by + simp [weierstrassRemainder, ha _ hz.1] + have hid : q z * z.2 ^ d + weierstrassRemainder a z = + q' z * z.2 ^ d + weierstrassRemainder a' z := + (h.eq hz).symm.trans (h'.eq hz) + have hmul : q z * z.2 ^ d = q' z * z.2 ^ d := by + simpa [hrem] using hid + by_cases hw : z.2 = 0 + · have hqA : AnalyticAt ℂ (fun w => q (z.1, w)) 0 := + ((differentiableOn_snd_slice h.differentiableOn_quotient + hz.1).analyticOnNhd_of_finiteDimensional + isOpen_ball) _ (mem_ball_self hR) + have hqA' : AnalyticAt ℂ (fun w => q' (z.1, w)) 0 := + ((differentiableOn_snd_slice h'.differentiableOn_quotient + hz.1).analyticOnNhd_of_finiteDimensional + isOpen_ball) _ (mem_ball_self hR) + have heq : (fun w => q (z.1, w)) =ᶠ[𝓝[≠] (0 : ℂ)] fun w => q' (z.1, w) := by + have hball : ∀ᶠ w in 𝓝[≠] (0 : ℂ), w ∈ ball (0 : ℂ) R := + nhdsWithin_le_nhds (isOpen_ball.mem_nhds (mem_ball_self hR)) + filter_upwards [hball, self_mem_nhdsWithin] with w hwball hw0 + have hwP : (z.1, w) ∈ V ×ˢ ball (0 : ℂ) R := ⟨hz.1, hwball⟩ + have hremw : weierstrassRemainder a (z.1, w) = weierstrassRemainder a' (z.1, w) := by + simp [weierstrassRemainder, ha _ hz.1] + have hidw : q (z.1, w) * w ^ d + weierstrassRemainder a (z.1, w) = + q' (z.1, w) * w ^ d + weierstrassRemainder a' (z.1, w) := + (h.eq hwP).symm.trans (h'.eq hwP) + have : q (z.1, w) * w ^ d = q' (z.1, w) * w ^ d := by + simpa [hremw] using hidw + exact mul_right_cancel₀ (pow_ne_zero d hw0) this + have hlim : Tendsto (fun w => q (z.1, w)) (𝓝[≠] (0 : ℂ)) (𝓝 (q (z.1, 0))) := + hqA.continuousAt.tendsto.mono_left nhdsWithin_le_nhds + have hlim' : Tendsto (fun w => q' (z.1, w)) (𝓝[≠] (0 : ℂ)) (𝓝 (q' (z.1, 0))) := + hqA'.continuousAt.tendsto.mono_left nhdsWithin_le_nhds + have heq0 : q (z.1, 0) = q' (z.1, 0) := + tendsto_nhds_unique (hlim.congr' heq) hlim' + rw [show z = (z.1, (0 : ℂ)) from Prod.ext rfl hw] + exact heq0 + · exact mul_right_cancel₀ (pow_ne_zero d hw) hmul + +/-- Mixed last-coordinate derivatives at the origin are Cauchy integrals on a smaller circle. -/ +theorem iteratedDeriv_snd_slice_circleIntegral + {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {z : ι → ℂ} (hz : z ∈ V) + (hρ : 0 < ρ) (hρR : ρ < R) (n : ℕ) : + iteratedDeriv n (fun w => g (z, w)) 0 = + (n.factorial : ℂ) * (2 * Real.pi * I : ℂ)⁻¹ * + ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s) := by + simpa [sub_zero] using + (diffContOnCl_snd_slice hg hz hρ hρR).iteratedDeriv_eq_circleIntegral_sub_zpow_mul + hρ n (mem_ball_self hρ) + +/-- The Cauchy integral of a jointly holomorphic kernel in the last coordinate remains holomorphic +in the parameters. -/ +theorem analyticOnNhd_circleIntegral_snd_zpow_mul + {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R)) (hρ : 0 < ρ) (hρR : ρ < R) (n : ℕ) : + AnalyticOnNhd ℂ (fun z => ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s)) V := by + have hfθ : ContinuousOn (fun s : ℂ => s ^ (-(n + 1 : ℤ))) (sphere 0 ρ) := by + refine continuousOn_id.zpow₀ (-(n + 1 : ℤ)) fun s hs => Or.inl ?_ + intro h0 + have hsρ : ‖s‖ = ρ := by + rw [← dist_zero_right] + exact mem_sphere.mp hs + have hs00 : s = 0 := h0 + rw [hs00, norm_zero] at hsρ + linarith + have hI := analyticOnNhd_circleIntegral_kernel_mul (E := ι → ℂ) hV hg hρ.le hfθ + (fun z hz s hs => + ⟨hz, (sphere_subset_closedBall.trans (closedBall_subset_ball hρR)) hs⟩) + refine hI.congr hV fun z hz => ?_ + exact circleIntegral.integral_congr hρ.le fun s _ => mul_comm _ _ + +/-- The Taylor remainder coefficients of a last-coordinate slice depend holomorphically on the +remaining coordinates. -/ +theorem differentiableOn_iteratedDeriv_snd_slice + {V : Set (ι → ℂ)} (hV : IsOpen V) {R : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hR : 0 < R) (n : ℕ) : + DifferentiableOn ℂ (fun z => iteratedDeriv n (fun w => g (z, w)) 0) V := by + let ρ := R / 2 + have hρ : 0 < ρ := half_pos hR + have hρR : ρ < R := half_lt_self hR + have hgA : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R) := + hg.analyticOnNhd_of_finiteDimensional (hV.prod isOpen_ball) + have hI := analyticOnNhd_circleIntegral_snd_zpow_mul hV hgA hρ hρR n + have hEq : EqOn (fun z => iteratedDeriv n (fun w => g (z, w)) 0) + (fun z => (n.factorial : ℂ) * (2 * Real.pi * I : ℂ)⁻¹ * + ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s)) V := + fun z hz => iteratedDeriv_snd_slice_circleIntegral hg hz hρ hρR n + exact ((hI.const_smul (c := (n.factorial : ℂ) * (2 * Real.pi * I : ℂ)⁻¹)).congr hV + (fun z hz => (hEq hz).symm)).differentiableOn + +/-- Cauchy integral representing the Weierstrass quotient for division by `w^d`. -/ +private def weierstrassCauchyQuotient (d : ℕ) (g : (ι → ℂ) × ℂ → ℂ) (ρ : ℝ) + (z : (ι → ℂ) × ℂ) : ℂ := + (2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), g (z.1, s) / (s ^ d * (s - z.2)) + +/-- The Cauchy quotient is jointly holomorphic on a strictly smaller product polydisc. -/ +private theorem analyticOnNhd_weierstrassCauchyQuotient + {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ₀ ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R)) + (hρ₀ : 0 < ρ₀) (hρ₀ρ : ρ₀ < ρ) (hρR : ρ < R) (d : ℕ) : + AnalyticOnNhd ℂ (weierstrassCauchyQuotient d g ρ) (V ×ˢ ball 0 ρ₀) := by + let W : Set (((ι → ℂ) × ℂ) × ℂ) := + {p | p.1.1 ∈ V ∧ p.2 ∈ ball (0 : ℂ) R ∧ p.2 ≠ 0 ∧ p.2 ≠ p.1.2} + let H : ((ι → ℂ) × ℂ) × ℂ → ℂ := fun p => + g (p.1.1, p.2) / (p.2 ^ d * (p.2 - p.1.2)) + have hH : AnalyticOnNhd ℂ H W := by + intro p hp + have hnum : AnalyticAt ℂ (fun q : ((ι → ℂ) × ℂ) × ℂ => g (q.1.1, q.2)) p := + (hg (p.1.1, p.2) ⟨hp.1, hp.2.1⟩).comp_of_eq + ((analyticAt_fst (𝕜 := ℂ)).comp (analyticAt_fst (𝕜 := ℂ)) |>.prod + (analyticAt_snd (𝕜 := ℂ))) rfl + have hden : AnalyticAt ℂ + (fun q : ((ι → ℂ) × ℂ) × ℂ => q.2 ^ d * (q.2 - q.1.2)) p := + (analyticAt_snd.pow d).mul + (analyticAt_snd.sub ((analyticAt_snd (𝕜 := ℂ)).comp (analyticAt_fst (𝕜 := ℂ)))) + exact hnum.div hden (mul_ne_zero (pow_ne_zero d hp.2.2.1) + (sub_ne_zero.mpr hp.2.2.2)) + have hfθ : ContinuousOn (fun _ : ℂ => (1 : ℂ)) (sphere 0 ρ) := continuousOn_const + have hmem : ∀ x ∈ V ×ˢ ball (0 : ℂ) ρ₀, ∀ s ∈ sphere (0 : ℂ) ρ, (x, s) ∈ W := by + intro x hx s hs + have hsρ : ‖s‖ = ρ := by + rw [← dist_zero_right] + exact mem_sphere.mp hs + have hs0 : s ≠ 0 := by + intro h0 + rw [h0, norm_zero] at hsρ + linarith + have hsw : s ≠ x.2 := by + intro h + have hxρ : ‖x.2‖ < ρ₀ := by simpa [dist_eq_norm] using hx.2 + rw [h] at hsρ + linarith + exact ⟨hx.1, (sphere_subset_closedBall.trans (closedBall_subset_ball hρR)) hs, hs0, hsw⟩ + have hI := (analyticOnNhd_circleIntegral_kernel_mul (E := (ι → ℂ) × ℂ) + (hV.prod isOpen_ball) hH (le_of_lt (hρ₀.trans hρ₀ρ)) hfθ hmem).const_smul + (c := (2 * Real.pi * I : ℂ)⁻¹) + refine hI.congr (hV.prod isOpen_ball) fun z hz => ?_ + simp [weierstrassCauchyQuotient, smul_eq_mul, H] + +/-- A bound of the form `M / ρ ^ n`, valid for every positive `ρ < R`, persists at `R` itself by +continuity of the bound in `ρ`. -/ +theorem le_div_pow_of_forall_lt {M : ℝ} {R : ℝ} (hR : 0 < R) (n : ℕ) {x : ℝ} + (h : ∀ ρ, 0 < ρ → ρ < R → x ≤ M / ρ ^ n) : x ≤ M / R ^ n := by + have hcont : ContinuousAt (fun ρ : ℝ => M / ρ ^ n) R := + continuousAt_const.div (continuousAt_id.pow n) (pow_ne_zero n hR.ne') + have htendsto : Tendsto (fun ρ : ℝ => M / ρ ^ n) (nhdsWithin R (Iio R)) (nhds (M / R ^ n)) := + hcont.continuousWithinAt + refine ge_of_tendsto htendsto ?_ + filter_upwards [self_mem_nhdsWithin, + (eventually_gt_nhds hR).filter_mono nhdsWithin_le_nhds] with ρ hρR hρ0 + exact h ρ hρ0 hρR + +/-- Cauchy's estimate for the Taylor coefficients of a last-coordinate slice, uniform up to the +boundary radius `R` even though the function is only assumed holomorphic on the open polydisc. -/ +theorem norm_iteratedDeriv_snd_slice_le {V : Set (ι → ℂ)} {R : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + {M : ℝ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hR : 0 < R) {z : ι → ℂ} (hz : z ∈ V) + (hM : ∀ w ∈ ball (0 : ℂ) R, ‖g (z, w)‖ ≤ M) (n : ℕ) : + ‖iteratedDeriv n (fun w => g (z, w)) 0‖ ≤ (n.factorial : ℝ) * M / R ^ n := by + apply le_div_pow_of_forall_lt hR + intro ρ hρ hρR + rw [iteratedDeriv_snd_slice_circleIntegral hg hz hρ hρR n, mul_assoc, norm_mul] + have hkernel : ‖(2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s)‖ + ≤ M / ρ ^ n := by + rw [← smul_eq_mul ((2 * Real.pi * I : ℂ)⁻¹)] + have hb := circleIntegral.norm_two_pi_i_inv_smul_integral_le_of_norm_le_const + (f := fun s => s ^ (-(n + 1 : ℤ)) * g (z, s)) (c := (0 : ℂ)) (R := ρ) + (C := M / ρ ^ (n + 1)) hρ.le + (fun s hs => by + have hsρ : ‖s‖ = ρ := by rw [← dist_zero_right]; exact mem_sphere.mp hs + have hs0 : s ≠ 0 := by intro h; rw [h, norm_zero] at hsρ; exact hρ.ne' hsρ.symm + have hzpow : ‖s ^ (-(n + 1 : ℤ))‖ = (ρ ^ (n + 1))⁻¹ := by + have he : (-(n + 1 : ℤ)) = -((n + 1 : ℕ) : ℤ) := by push_cast; ring + rw [norm_zpow, hsρ, he, zpow_neg, zpow_natCast] + rw [norm_mul, hzpow, div_eq_inv_mul] + exact mul_le_mul_of_nonneg_left (hM s ((mem_ball.mpr (by simpa [hsρ] using hρR)))) + (by positivity)) + calc ‖(2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s)‖ + ≤ ρ * (M / ρ ^ (n + 1)) := hb + _ = M / ρ ^ n := by field_simp; ring + simp only [Complex.norm_natCast] + calc (n.factorial : ℝ) * ‖(2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s)‖ + ≤ (n.factorial : ℝ) * (M / ρ ^ n) := mul_le_mul_of_nonneg_left hkernel (by positivity) + _ = (n.factorial : ℝ) * M / ρ ^ n := by ring + +/-- The Cauchy coefficient of a last-coordinate slice equals a division-kernel circle integral, +matching the shape used by the coordinate-power kernel identity. -/ +theorem cauchyCoeff_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {w : ι → ℂ} (hw : w ∈ V) + (hρ : 0 < ρ) (hρR : ρ < R) (j : ℕ) : + (2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), g (w, s) / s ^ (j + 1) = + ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv j (fun s => g (w, s)) 0 := by + rw [iteratedDeriv_snd_slice_circleIntegral hg hw hρ hρR j] + have hEq : EqOn (fun s : ℂ => g (w, s) / s ^ (j + 1)) + (fun s => s ^ (-(j + 1 : ℤ)) * g (w, s)) (sphere (0 : ℂ) ρ) := by + intro s _ + show g (w, s) / s ^ (j + 1) = s ^ (-(j + 1 : ℤ)) * g (w, s) + rw [div_eq_inv_mul, show (-(j + 1 : ℤ)) = -((j + 1 : ℕ) : ℤ) by push_cast; ring, + zpow_neg, zpow_natCast] + rw [circleIntegral.integral_congr hρ.le hEq, + mul_assoc ((j : ℕ).factorial : ℂ) ((2 * Real.pi * I : ℂ)⁻¹), + inv_mul_cancel_left₀ (by exact_mod_cast j.factorial_ne_zero : + ((j : ℕ).factorial : ℂ) ≠ 0)] + +/-- The Cauchy quotient at a fixed admissible radius solves the coordinate-power division identity +there, with remainder coefficients given by Taylor coefficients of the last-coordinate slice. -/ +private theorem coordinatePower_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρ : 0 < ρ) (hρR : ρ < R) (d : ℕ) + {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ : ζ ∈ ball (0 : ℂ) ρ) : + g (w, ζ) = weierstrassRemainder + (fun j : Fin d => fun v : ι → ℂ => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ) + + ζ ^ d * weierstrassCauchyQuotient d g ρ (w, ζ) := by + have hζρ : ‖ζ‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ + have hslice : DiffContOnCl ℂ (fun s => g (w, s)) (ball 0 ρ) := + diffContOnCl_snd_slice hg hw hρ hρR + have hcauchy : g (w, ζ) = (2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), (s - ζ)⁻¹ * g (w, s) := by + simpa using hslice.iteratedDeriv_eq_circleIntegral_sub_zpow_mul hρ 0 hζ + have hcontslice : ContinuousOn (fun s => g (w, s)) (sphere (0 : ℂ) ρ) := + hg.continuousOn.comp (continuousOn_const.prodMk continuousOn_id) + (fun s hs => ⟨hw, (sphere_subset_closedBall.trans (closedBall_subset_ball hρR)) hs⟩) + have hne0 : ∀ s ∈ sphere (0 : ℂ) ρ, s ≠ 0 := by + intro s hs hcontra + have hsρ : ‖s‖ = ρ := by rw [← dist_zero_right]; exact mem_sphere.mp hs + rw [hcontra, norm_zero] at hsρ; exact hρ.ne' hsρ.symm + have hnesw : ∀ s ∈ sphere (0 : ℂ) ρ, s ≠ ζ := by + intro s hs hcontra + have hsρ : ‖s‖ = ρ := by rw [← dist_zero_right]; exact mem_sphere.mp hs + rw [hcontra] at hsρ; linarith + have hEqOn : EqOn (fun s => (s - ζ)⁻¹ * g (w, s)) + (fun s => (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) + + ζ ^ d / (s ^ d * (s - ζ)) * g (w, s)) (sphere (0 : ℂ) ρ) := by + intro s hs + show (s - ζ)⁻¹ * g (w, s) = + (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) + ζ ^ d / (s ^ d * (s - ζ)) * g (w, s) + rw [← add_mul, weierstrass_kernel_identity d (hne0 s hs) (hnesw s hs)] + rw [circleIntegral.integral_congr hρ.le hEqOn] at hcauchy + have hcont1 : ContinuousOn (fun s => (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s)) + (sphere (0 : ℂ) ρ) := by + apply ContinuousOn.mul _ hcontslice + apply continuousOn_finsetSum + intro j _ + exact ContinuousOn.div continuousOn_const (continuousOn_pow _) + (fun s hs => pow_ne_zero _ (hne0 s hs)) + have hcont2 : ContinuousOn (fun s => ζ ^ d / (s ^ d * (s - ζ)) * g (w, s)) (sphere (0 : ℂ) ρ) := + by + apply ContinuousOn.mul _ hcontslice + exact ContinuousOn.div continuousOn_const + ((continuousOn_pow _).mul (continuousOn_id.sub continuousOn_const)) + (fun s hs => mul_ne_zero (pow_ne_zero _ (hne0 s hs)) (sub_ne_zero.mpr (hnesw s hs))) + have hcirc1 : CircleIntegrable (fun s => (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s)) 0 ρ := + ContinuousOn.circleIntegrable' (by rwa [abs_of_pos hρ]) + have hcirc2 : CircleIntegrable (fun s => ζ ^ d / (s ^ d * (s - ζ)) * g (w, s)) 0 ρ := + ContinuousOn.circleIntegrable' (by rwa [abs_of_pos hρ]) + rw [circleIntegral.integral_add hcirc1 hcirc2] at hcauchy + have hsum : (∮ s in C(0, ρ), (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s)) = + ∑ j ∈ range d, ζ ^ j * ∮ s in C(0, ρ), g (w, s) / s ^ (j + 1) := by + have hcongr : (∮ s in C(0, ρ), (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s)) = + ∮ s in C(0, ρ), ∑ j ∈ range d, ζ ^ j * (g (w, s) / s ^ (j + 1)) := by + apply circleIntegral.integral_congr hρ.le + intro s _ + show (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) = + ∑ j ∈ range d, ζ ^ j * (g (w, s) / s ^ (j + 1)) + rw [Finset.sum_mul] + exact Finset.sum_congr rfl fun j _ => by ring + rw [hcongr, circleIntegral.integral_fun_sum (fun j _ => by + apply ContinuousOn.circleIntegrable' (R := ρ) + rw [show |ρ| = ρ from abs_of_pos hρ] + exact ContinuousOn.mul continuousOn_const + (ContinuousOn.div hcontslice (continuousOn_pow _) (fun s hs => pow_ne_zero _ (hne0 s hs))))] + exact Finset.sum_congr rfl fun j _ => circleIntegral.integral_const_mul _ _ _ _ + have hquot : (∮ s in C(0, ρ), ζ ^ d / (s ^ d * (s - ζ)) * g (w, s)) = + ζ ^ d * ∮ s in C(0, ρ), g (w, s) / (s ^ d * (s - ζ)) := by + rw [← circleIntegral.integral_const_mul] + exact circleIntegral.integral_congr hρ.le fun s _ => by ring + rw [hsum, hquot, mul_add] at hcauchy + have hstep1 : (2 * Real.pi * I : ℂ)⁻¹ * + ∑ j ∈ range d, ζ ^ j * ∮ s in C(0, ρ), g (w, s) / s ^ (j + 1) = + ∑ j ∈ range d, (((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv j (fun s => g (w, s)) 0) * ζ ^ j + := by + rw [Finset.mul_sum] + exact Finset.sum_congr rfl fun j _ => by + rw [mul_left_comm, cauchyCoeff_eq_of_lt hg hw hρ hρR j, mul_comm] + rw [hstep1] at hcauchy + rw [hcauchy, weierstrassCauchyQuotient, weierstrassRemainder, + Fin.sum_univ_eq_sum_range (fun j => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv j (fun s => g (w, s)) 0 * ζ ^ j)] + ring + +/-- The Cauchy quotient at two admissible radii agrees at every nonzero point where both are +defined. -/ +private theorem weierstrassCauchyQuotient_eq_of_ne {V : Set (ι → ℂ)} {R ρ₁ ρ₂ : ℝ} + {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) + (hρ₁ : 0 < ρ₁) (hρ₁R : ρ₁ < R) (hρ₂ : 0 < ρ₂) (hρ₂R : ρ₂ < R) (d : ℕ) + {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ0 : ζ ≠ 0) + (hζ₁ : ζ ∈ ball (0 : ℂ) ρ₁) (hζ₂ : ζ ∈ ball (0 : ℂ) ρ₂) : + weierstrassCauchyQuotient d g ρ₁ (w, ζ) = weierstrassCauchyQuotient d g ρ₂ (w, ζ) := by + have h1 := coordinatePower_eq_of_lt hg hρ₁ hρ₁R d hw hζ₁ + have h2 := coordinatePower_eq_of_lt hg hρ₂ hρ₂R d hw hζ₂ + have heq : ζ ^ d * weierstrassCauchyQuotient d g ρ₁ (w, ζ) = + ζ ^ d * weierstrassCauchyQuotient d g ρ₂ (w, ζ) := by + rw [← add_right_inj (weierstrassRemainder + (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) + (w, ζ)), ← h1, ← h2] + exact mul_left_cancel₀ (pow_ne_zero d hζ0) heq + +/-- The Cauchy quotient at two admissible radii agrees wherever both are defined. -/ +private theorem weierstrassCauchyQuotient_eq_of_lt {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ₁ ρ₂ : ℝ} + {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) + (hρ₁ : 0 < ρ₁) (hρ₁R : ρ₁ < R) (hρ₂ : 0 < ρ₂) (hρ₂R : ρ₂ < R) (d : ℕ) + {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ₁ : ζ ∈ ball (0 : ℂ) ρ₁) (hζ₂ : ζ ∈ ball (0 : ℂ) ρ₂) : + weierstrassCauchyQuotient d g ρ₁ (w, ζ) = weierstrassCauchyQuotient d g ρ₂ (w, ζ) := by + rcases eq_or_ne ζ 0 with hζ0 | hζ0 + · subst hζ0 + set ρ₀ := min ρ₁ ρ₂ / 2 with hρ₀def + have hρ₀pos : 0 < ρ₀ := by positivity + have hρ₀ρ₁ : ρ₀ < ρ₁ := + calc ρ₀ ≤ ρ₁ / 2 := by rw [hρ₀def]; gcongr; exact min_le_left ρ₁ ρ₂ + _ < ρ₁ := by linarith + have hρ₀ρ₂ : ρ₀ < ρ₂ := + calc ρ₀ ≤ ρ₂ / 2 := by rw [hρ₀def]; gcongr; exact min_le_right ρ₁ ρ₂ + _ < ρ₂ := by linarith + have hgA : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R) := hg.analyticOnNhd_of_finiteDimensional + (hV.prod isOpen_ball) + have hA1 : AnalyticOnNhd ℂ (fun ζ' => weierstrassCauchyQuotient d g ρ₁ (w, ζ')) (ball 0 ρ₀) := + fun ζ' hζ' => ((analyticOnNhd_weierstrassCauchyQuotient hV hgA hρ₀pos hρ₀ρ₁ hρ₁R d) + (w, ζ') ⟨hw, hζ'⟩).comp_of_eq + ((analyticAt_const (v := w)).prod analyticAt_id) rfl + have hA2 : AnalyticOnNhd ℂ (fun ζ' => weierstrassCauchyQuotient d g ρ₂ (w, ζ')) (ball 0 ρ₀) := + fun ζ' hζ' => ((analyticOnNhd_weierstrassCauchyQuotient hV hgA hρ₀pos hρ₀ρ₂ hρ₂R d) + (w, ζ') ⟨hw, hζ'⟩).comp_of_eq + ((analyticAt_const (v := w)).prod analyticAt_id) rfl + have heqn : (fun ζ' => weierstrassCauchyQuotient d g ρ₁ (w, ζ')) =ᶠ[𝓝[≠] (0 : ℂ)] + (fun ζ' => weierstrassCauchyQuotient d g ρ₂ (w, ζ')) := by + filter_upwards [self_mem_nhdsWithin, + mem_nhdsWithin_of_mem_nhds (isOpen_ball.mem_nhds (mem_ball_self hρ₀pos))] + with ζ' hζ'0 hζ'0' + exact weierstrassCauchyQuotient_eq_of_ne hg hρ₁ hρ₁R hρ₂ hρ₂R d hw hζ'0 + (ball_subset_ball hρ₀ρ₁.le hζ'0') (ball_subset_ball hρ₀ρ₂.le hζ'0') + have hlim1 : Tendsto (fun ζ' => weierstrassCauchyQuotient d g ρ₁ (w, ζ')) (𝓝[≠] (0 : ℂ)) + (𝓝 (weierstrassCauchyQuotient d g ρ₁ (w, 0))) := + (hA1 0 (mem_ball_self hρ₀pos)).continuousAt.tendsto.mono_left nhdsWithin_le_nhds + have hlim2 : Tendsto (fun ζ' => weierstrassCauchyQuotient d g ρ₂ (w, ζ')) (𝓝[≠] (0 : ℂ)) + (𝓝 (weierstrassCauchyQuotient d g ρ₂ (w, 0))) := + (hA2 0 (mem_ball_self hρ₀pos)).continuousAt.tendsto.mono_left nhdsWithin_le_nhds + exact tendsto_nhds_unique (hlim1.congr' heqn) hlim2 + · exact weierstrassCauchyQuotient_eq_of_ne hg hρ₁ hρ₁R hρ₂ hρ₂R d hw hζ0 hζ₁ hζ₂ + +/-- Subtracting the Taylor polynomial of degree less than `d` from a function bounded by `M` gives a +numerator bounded by `(d + 1) * M`. The triangle inequality and Cauchy's coefficient bounds +control each of the `d` remainder terms on the smaller disc. -/ +theorem norm_sub_weierstrassRemainder_iteratedDeriv_le {V : Set (ι → ℂ)} {R ρ M : ℝ} + {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρR : ρ < R) (d : ℕ) + (hM : ∀ z ∈ V ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) {w : ι → ℂ} (hw : w ∈ V) {ζ' : ℂ} + (hζ' : ζ' ∈ ball (0 : ℂ) ρ) : + ‖g (w, ζ') - weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ ((d + 1 : ℕ) : ℝ) * M := by + have hζ'ρ : ‖ζ'‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ' + have hζ'R : ‖ζ'‖ < R := hζ'ρ.trans hρR + have hR0 : 0 < R := (norm_nonneg ζ').trans_lt hζ'R + have hgb : ‖g (w, ζ')‖ ≤ M := hM (w, ζ') ⟨hw, mem_ball_zero_iff.mpr hζ'R⟩ + have hMnn : 0 ≤ M := (norm_nonneg _).trans hgb + have haj : ∀ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ ≤ M / R ^ (j : ℕ) := by + intro j + have hb := norm_iteratedDeriv_snd_slice_le hg hR0 hw (fun s hs => hM (w, s) ⟨hw, hs⟩) + (j : ℕ) + rw [norm_mul, norm_inv, Complex.norm_natCast] + calc ((j : ℕ).factorial : ℝ)⁻¹ * ‖iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0‖ + ≤ ((j : ℕ).factorial : ℝ)⁻¹ * (((j : ℕ).factorial : ℝ) * M / R ^ (j : ℕ)) := + mul_le_mul_of_nonneg_left hb (by positivity) + _ = M / R ^ (j : ℕ) := by field_simp + have hrem : ‖weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ (d : ℝ) * M := by + unfold weierstrassRemainder + calc ‖∑ j : Fin d, (((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ + ≤ ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ := norm_sum_le _ _ + _ = ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) := by + simp [norm_pow] + _ ≤ ∑ _j : Fin d, (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by + apply Finset.sum_le_sum + intro j _ + calc ‖(((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) + (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) + ≤ (M / R ^ (j : ℕ)) * R ^ (j : ℕ) := + mul_le_mul (haj j) (pow_le_pow_left₀ (norm_nonneg _) + (hζ'ρ.trans hρR).le _) (by positivity) (by positivity) + _ = M := by field_simp + _ = (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by simp + _ = (d : ℝ) * M := by simp [Finset.sum_const, Finset.card_univ, mul_comm] + calc ‖g (w, ζ') - weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ + ≤ ‖g (w, ζ')‖ + ‖weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ := norm_sub_le _ _ + _ ≤ M + (d : ℝ) * M := add_le_add hgb hrem + _ = ((d + 1 : ℕ) : ℝ) * M := by push_cast; ring + +/-- The **uniform coordinate-power quotient bound**: the Cauchy quotient at radius `ρ` is bounded by +`(d+1) M / ρ ^ d` throughout the disc, using a bound `M` on the numerator over the whole domain. +The proof compares the numerator to its degree-`< d` Taylor polynomial, bounded by `(d+1) M` via +`norm_sub_weierstrassRemainder_iteratedDeriv_le`, then applies the maximum modulus principle to +the quotient itself and lets the comparison radius approach `ρ`. -/ +private theorem norm_weierstrassCauchyQuotient_le {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ M : ℝ} + {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) + (hρ : 0 < ρ) (hρR : ρ < R) (d : ℕ) + (hM : ∀ z ∈ V ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) {w : ι → ℂ} (hw : w ∈ V) {ζ0 : ℂ} + (hζ0 : ζ0 ∈ ball (0 : ℂ) ρ) : + ‖weierstrassCauchyQuotient d g ρ (w, ζ0)‖ ≤ ((d + 1 : ℕ) : ℝ) * M / ρ ^ d := by + have hR0 : 0 < R := hρ.trans hρR + have hMnn : 0 ≤ M := (norm_nonneg _).trans (hM (w, 0) ⟨hw, mem_ball_self hR0⟩) + have hgA : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R) := hg.analyticOnNhd_of_finiteDimensional + (hV.prod isOpen_ball) + have hψ : ∀ ζ' : ℂ, ζ' ∈ ball (0 : ℂ) ρ → + ‖g (w, ζ') - weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ ((d + 1 : ℕ) : ℝ) * M := + fun ζ' hζ' => norm_sub_weierstrassRemainder_iteratedDeriv_le hg hρR d hM hw hζ' + have hqbound : ∀ ρ', ‖ζ0‖ < ρ' → ρ' < ρ → + ‖weierstrassCauchyQuotient d g ρ (w, ζ0)‖ ≤ ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d := by + intro ρ' hζ0ρ' hρ'ρ + have hρ'pos : 0 < ρ' := (norm_nonneg _).trans_lt hζ0ρ' + have hbdry : ∀ ζ' ∈ sphere (0 : ℂ) ρ', + ‖weierstrassCauchyQuotient d g ρ (w, ζ')‖ ≤ ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d := by + intro ζ' hζ' + have hζ'ρ' : ‖ζ'‖ = ρ' := by rw [← dist_zero_right]; exact mem_sphere.mp hζ' + have hζ'0 : ζ' ≠ 0 := by intro h; rw [h, norm_zero] at hζ'ρ'; exact hρ'pos.ne' hζ'ρ'.symm + have hζ'ball : ζ' ∈ ball (0 : ℂ) ρ := by + rw [mem_ball_zero_iff, hζ'ρ']; exact hρ'ρ + have heq := coordinatePower_eq_of_lt hg hρ hρR d hw hζ'ball + have hpsi := hψ ζ' hζ'ball + have hval : ζ' ^ d * weierstrassCauchyQuotient d g ρ (w, ζ') = + g (w, ζ') - weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ') := by + rw [heq]; ring + have hnorm : ‖ζ'‖ ^ d * ‖weierstrassCauchyQuotient d g ρ (w, ζ')‖ ≤ + ((d + 1 : ℕ) : ℝ) * M := by + rw [← norm_pow, ← norm_mul, hval]; exact hpsi + rw [hζ'ρ'] at hnorm + rw [le_div_iff₀ (by positivity : (0 : ℝ) < ρ' ^ d), mul_comm] + exact hnorm + obtain ⟨ρ'', hρ'ρ'', hρ''ρ⟩ := exists_between hρ'ρ + have hAslice : AnalyticOnNhd ℂ (fun ζ' => weierstrassCauchyQuotient d g ρ (w, ζ')) + (ball (0 : ℂ) ρ'') := fun ζ' hζ' => + ((analyticOnNhd_weierstrassCauchyQuotient hV hgA (hρ'pos.trans hρ'ρ'') hρ''ρ hρR d) + (w, ζ') ⟨hw, hζ'⟩).comp_of_eq ((analyticAt_const (v := w)).prod analyticAt_id) rfl + have hslice : DiffContOnCl ℂ (fun ζ' => weierstrassCauchyQuotient d g ρ (w, ζ')) + (ball (0 : ℂ) ρ') := + ⟨(hAslice.mono (ball_subset_ball hρ'ρ''.le)).differentiableOn, by + rw [closure_ball (0 : ℂ) hρ'pos.ne'] + exact hAslice.continuousOn.mono (closedBall_subset_ball hρ'ρ'')⟩ + exact Complex.norm_le_of_forall_mem_frontier_norm_le Metric.isBounded_ball hslice + (fun ζ' hζ' => by rw [frontier_ball (0 : ℂ) hρ'pos.ne'] at hζ'; exact hbdry ζ' hζ') + (subset_closure (mem_ball_zero_iff.mpr hζ0ρ')) + have hζ0ρ : ‖ζ0‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ0 + have hcont : ContinuousAt (fun ρ' : ℝ => ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d) ρ := + continuousAt_const.div (continuousAt_id.pow d) (pow_ne_zero d hρ.ne') + have htendsto : Tendsto (fun ρ' : ℝ => ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d) + (nhdsWithin ρ (Iio ρ)) (nhds (((d + 1 : ℕ) : ℝ) * M / ρ ^ d)) := + hcont.continuousWithinAt + refine ge_of_tendsto htendsto ?_ + filter_upwards [self_mem_nhdsWithin, + mem_nhdsWithin_of_mem_nhds (eventually_gt_nhds hζ0ρ)] with ρ' hρ'ρ hρ'ζ0 + exact hqbound ρ' hρ'ζ0 hρ'ρ + +/-- **Coordinate-power division ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.4).** Every +holomorphic function +on a polydisc has a unique quotient and polynomial remainder on division by `w^d`. +The quotient estimate applies whenever the numerator is bounded. Uniqueness follows +from the coordinate-power uniqueness theorem above. +Empty parameter index types and `d = 0` are included. -/ +theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < R) + {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) : + ∃ q : (ι → ℂ) × ℂ → ℂ, ∃ a : Fin d → (ι → ℂ) → ℂ, + IsWeierstrassDivisionOn (fun z => z.2 ^ d) g q a (polydisc 0 r) R ∧ + (∀ M : ℝ, 0 ≤ M → + (∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖g z‖ ≤ M) → + ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖q z‖ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * M) ∧ + (∀ q' a', IsWeierstrassDivisionOn (fun z => z.2 ^ d) g q' a' + (polydisc 0 r) R → + EqOn q q' (polydisc 0 r ×ˢ ball 0 R) ∧ + ∀ j, EqOn (a j) (a' j) (polydisc 0 r)) := by + set V := polydisc (0 : ι → ℂ) r with hVdef + have hVo : IsOpen V := isOpen_polydisc _ _ + have hgA : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R) := hg.analyticOnNhd_of_finiteDimensional + (hVo.prod isOpen_ball) + set a : Fin d → (ι → ℂ) → ℂ := fun j w => + ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0 with hadef + set q : (ι → ℂ) × ℂ → ℂ := fun z => weierstrassCauchyQuotient d g ((‖z.2‖ + R) / 2) z with hqdef + have hρz : ∀ ζ : ℂ, ‖ζ‖ < R → 0 < (‖ζ‖ + R) / 2 ∧ ‖ζ‖ < (‖ζ‖ + R) / 2 ∧ + (‖ζ‖ + R) / 2 < R := fun ζ hζ => ⟨by linarith [norm_nonneg ζ], by linarith, by linarith⟩ + have hqanalytic : AnalyticOnNhd ℂ q (V ×ˢ ball 0 R) := by + rintro z ⟨hz1, hz2⟩ + have hζR : ‖z.2‖ < R := by simpa [mem_ball, dist_eq_norm] using hz2 + obtain ⟨hρ0pos, hρ0ζ, hρ0R⟩ := hρz z.2 hζR + obtain ⟨ρbig, hρ0ρbig, hρbigR⟩ := exists_between hρ0R + have hkey : ‖z.2‖ < 2 * ρbig - R := by nlinarith + obtain ⟨ρ0', hζρ0', hρ0'key⟩ := exists_between hkey + have hρ0'ρbig : ρ0' < ρbig := by linarith + have hAbig : AnalyticOnNhd ℂ (weierstrassCauchyQuotient d g ρbig) (V ×ˢ ball 0 ρ0') := + analyticOnNhd_weierstrassCauchyQuotient hVo hgA + ((norm_nonneg z.2).trans_lt hζρ0') hρ0'ρbig hρbigR d + have hzmem : z ∈ V ×ˢ ball (0 : ℂ) ρ0' := ⟨hz1, mem_ball_zero_iff.mpr hζρ0'⟩ + have heqOn : EqOn q (weierstrassCauchyQuotient d g ρbig) (V ×ˢ ball (0 : ℂ) ρ0') := by + rintro y ⟨hy1, hy2⟩ + have hy2' : ‖y.2‖ < ρ0' := by simpa [mem_ball, dist_eq_norm] using hy2 + have hy2R : ‖y.2‖ < R := hy2'.trans (hρ0'ρbig.trans hρbigR) + obtain ⟨hρypos, hρyζ, hρyR⟩ := hρz y.2 hy2R + have hyρbig : ‖y.2‖ < ρbig := hy2'.trans hρ0'ρbig + have hρylt : (‖y.2‖ + R) / 2 < ρbig := by linarith + show weierstrassCauchyQuotient d g ((‖y.2‖ + R) / 2) y = + weierstrassCauchyQuotient d g ρbig y + exact weierstrassCauchyQuotient_eq_of_lt hVo hg hρypos hρyR + ((norm_nonneg y.2).trans_lt hyρbig) hρbigR d hy1 + (mem_ball_zero_iff.mpr hρyζ) (mem_ball_zero_iff.mpr hyρbig) + have heq : q =ᶠ[𝓝 z] weierstrassCauchyQuotient d g ρbig := by + filter_upwards [(hVo.prod isOpen_ball).mem_nhds hzmem] with y hy using heqOn hy + exact (hAbig z hzmem).congr heq.symm + have haholo : ∀ j, DifferentiableOn ℂ (a j) V := fun j => + (differentiableOn_iteratedDeriv_snd_slice hVo hg hR (j : ℕ)).const_mul _ + have hqholo : DifferentiableOn ℂ q (V ×ˢ ball 0 R) := + hqanalytic.differentiableOn + have heqOnV : EqOn g (fun z => q z * (fun z => z.2 ^ d) z + weierstrassRemainder a z) + (V ×ˢ ball 0 R) := by + rintro z ⟨hz1, hz2⟩ + have hζR : ‖z.2‖ < R := by simpa [mem_ball, dist_eq_norm] using hz2 + obtain ⟨hρ0pos, hρ0ζ, hρ0R⟩ := hρz z.2 hζR + have := coordinatePower_eq_of_lt hg hρ0pos hρ0R d hz1 (mem_ball_zero_iff.mpr hρ0ζ) + show g z = q z * z.2 ^ d + weierstrassRemainder a z + rw [this]; ring + refine ⟨q, a, ⟨hqholo, haholo, heqOnV⟩, ?_, ?_⟩ + · intro M hM0 hMb z hz + obtain ⟨hz1, hz2⟩ := hz + have hζR : ‖z.2‖ < R := by simpa [mem_ball, dist_eq_norm] using hz2 + obtain ⟨hρ0pos, hρ0ζ, hρ0R⟩ := hρz z.2 hζR + have hbnd : ∀ ρ', ‖z.2‖ < ρ' → ρ' < R → ‖q z‖ ≤ ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d := by + intro ρ' hζρ' hρ'R + have hle := norm_weierstrassCauchyQuotient_le hVo hg ((norm_nonneg z.2).trans_lt hζρ') + hρ'R d hMb hz1 (mem_ball_zero_iff.mpr hζρ') + rwa [show q z = weierstrassCauchyQuotient d g ρ' z from + weierstrassCauchyQuotient_eq_of_lt hVo hg hρ0pos hρ0R + ((norm_nonneg z.2).trans_lt hζρ') hρ'R d hz1 (mem_ball_zero_iff.mpr hρ0ζ) + (mem_ball_zero_iff.mpr hζρ')] + have hcont : ContinuousAt (fun ρ' : ℝ => ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d) R := + continuousAt_const.div (continuousAt_id.pow d) (pow_ne_zero d hR.ne') + have htendsto : Tendsto (fun ρ' : ℝ => ((d + 1 : ℕ) : ℝ) * M / ρ' ^ d) + (nhdsWithin R (Iio R)) (nhds (((d + 1 : ℕ) : ℝ) * M / R ^ d)) := + hcont.continuousWithinAt + have hfinal : ‖q z‖ ≤ ((d + 1 : ℕ) : ℝ) * M / R ^ d := by + refine ge_of_tendsto htendsto ?_ + filter_upwards [self_mem_nhdsWithin, + mem_nhdsWithin_of_mem_nhds (eventually_gt_nhds hζR)] with ρ' hρ'R hζρ' + exact hbnd ρ' hζρ' hρ'R + rw [show ((d + 1 : ℕ) : ℝ) / R ^ d * M = ((d + 1 : ℕ) : ℝ) * M / R ^ d from by ring] + exact hfinal + · intro q' a' h' + exact unique_coordinatePower_division ⟨hqholo, haholo, heqOnV⟩ h' hR + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean new file mode 100644 index 0000000000..5991a7361d --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean @@ -0,0 +1,548 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower + +/-! +# Picard iteration for Weierstrass division + +Starting from division by a coordinate power, we construct successive approximations for a small +perturbation of that divisor. A geometric error bound gives a holomorphic limit; convergence of +Taylor coefficients identifies its polynomial remainder. A separate contraction argument proves +uniqueness for the perturbed division equation. + +These results supply the iterative step of [Jakóbczak–Jarnicki][JakobczakJarnicki2021], Theorem +1.7.3. Normalization of a general divisor is in `SeveralComplexVariables.WeierstrassDivision`. + +## Main definitions + +* `picardApprox`: The Picard-iteration approximations to the coordinate-power quotient of `g` by a + small perturbation `h` of `z ^ d`: `s 0 = 0`, and `s (k+1)` is the coordinate-power quotient of `g + - h * s k`. +* `picardApproxCoeff`: The remainder coefficients accompanying `picardApprox`'s quotient at each + step. + +## Main results + +* `picardApprox_diff_bound`: **Contraction estimate for the Picard iteration.** Consecutive Picard + approximations of the coordinate-power quotient by `g - h * s_k` differ by a geometrically + shrinking amount, given the numerator bound `M` for `g` and the small-perturbation bound on `h`. +* `exists_tendstoUniformlyOn_picardApprox`: **Locally uniform limit of the Picard iteration.** Under + the contraction estimate of `picardApprox_diff_bound`, the Picard approximations converge + uniformly on the domain to an analytic limit, with the geometric tail bound summed over all later + steps. +* `exists_weierstrassRemainder_eq_of_tendstoUniformlyOn_picardApprox`: **The remainder of a Picard + limit is itself a Weierstrass remainder.** Given a bound on the distance from each Picard + approximation to a limit `S` (as produced by `exists_tendstoUniformlyOn_picardApprox`), the + limiting perturbed-division remainder `g - h * S - ζ ^ d * S` is the Weierstrass remainder of the + coefficients obtained by passing derivatives of the numerator's slices to the limit. +* `eqOn_of_isWeierstrassDivisionOn_selfPerturbed`: **Direct uniqueness for the perturbed + coordinate-power fixed-point equation.** If `h` is uniformly small relative to `R` on a domain, + any two decompositions of the *same* `g` against the divisor `z ^ d + h`, each individually + bounded there, agree. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Complex Filter Finset Metric Set +open scoped Real Topology + +namespace SeveralComplexVariables.WeierstrassDivision + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +variable {ι : Type*} [Fintype ι] + +/-- The Picard-iteration approximations to the coordinate-power quotient of `g` by a small +perturbation `h` of `z ^ d`: `s 0 = 0`, and `s (k+1)` is the coordinate-power quotient of `g - h +* s k`. Each approximation is holomorphic on the fixed polydisc. -/ +@[expose] noncomputable def picardApprox (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) + (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) : + ℕ → {s : (ι → ℂ) × ℂ → ℂ // DifferentiableOn ℂ s (polydisc 0 r ×ˢ ball 0 R)} + | 0 => ⟨0, differentiableOn_const 0⟩ + | (k + 1) => + let prev := picardApprox d r R hr hR h g hg hh k + ⟨(coordinatePower_division d hR (hg.sub (hh.mul prev.2))).choose, + (coordinatePower_division d hR + (hg.sub (hh.mul prev.2))).choose_spec.choose_spec.1.differentiableOn_quotient⟩ + +/-- The remainder coefficients accompanying `picardApprox`'s quotient at each step. -/ +noncomputable def picardApproxCoeff (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) (k : ℕ) : + Fin d → (ι → ℂ) → ℂ := + (coordinatePower_division d hR + (hg.sub (hh.mul (picardApprox d r R hr hR h g hg hh k).2))).choose_spec.choose + +/-- Each Picard step genuinely divides `g - h * (previous step)` by `z ^ d`. -/ +theorem picardApprox_succ_isWeierstrassDivisionOn (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) + (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) (k : ℕ) : + IsWeierstrassDivisionOn (fun z => z.2 ^ d) + (g - h * (picardApprox d r R hr hR h g hg hh k).1) + (picardApprox d r R hr hR h g hg hh (k + 1)).1 + (picardApproxCoeff d r R hr hR h g hg hh k) (polydisc 0 r) R := + (coordinatePower_division d hR + (hg.sub (hh.mul (picardApprox d r R hr hR h g hg hh k).2))).choose_spec.choose_spec.1 + +/-- The quotient bound of `coordinatePower_division`, specialized to a Picard step. -/ +theorem picardApprox_succ_bound (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) (k : ℕ) (M : ℝ) (hM0 : 0 ≤ M) + (hb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(g - h * (picardApprox d r R hr hR h g hg hh k).1) z‖ ≤ M) : + ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(picardApprox d r R hr hR h g hg hh (k + 1)).1 z‖ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * M := + (coordinatePower_division d hR + (hg.sub (hh.mul (picardApprox d r R hr hR h g hg hh k).2))).choose_spec.choose_spec.2.1 M + hM0 hb + +/-- Uniqueness of `coordinatePower_division`, specialized to a Picard step: any other valid +decomposition of the same numerator agrees with the Picard step's output. -/ +theorem picardApprox_succ_unique (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) (k : ℕ) + (q' : (ι → ℂ) × ℂ → ℂ) (a' : Fin d → (ι → ℂ) → ℂ) + (hdiv' : IsWeierstrassDivisionOn (fun z => z.2 ^ d) + (g - h * (picardApprox d r R hr hR h g hg hh k).1) q' a' (polydisc 0 r) R) : + EqOn (picardApprox d r R hr hR h g hg hh (k + 1)).1 q' + (polydisc 0 r ×ˢ ball 0 R) ∧ + ∀ j, EqOn (picardApproxCoeff d r R hr hR h g hg hh k j) (a' j) (polydisc 0 r) := + (coordinatePower_division d hR + (hg.sub (hh.mul (picardApprox d r R hr hR h g hg hh k).2))).choose_spec.choose_spec.2.2 q' a' + hdiv' + +/-- Iterated derivatives converge along a locally uniform limit of holomorphic one-variable +functions, evaluated at any point of the domain. -/ +theorem tendsto_iteratedDeriv_of_tendstoLocallyUniformlyOn {V : Set ℂ} (hV : IsOpen V) (j : ℕ) : + ∀ (F : ℕ → ℂ → ℂ) (f' : ℂ → ℂ), TendstoLocallyUniformlyOn F f' atTop V → + (∀ n, DifferentiableOn ℂ (F n) V) → ∀ {x : ℂ}, x ∈ V → + Tendsto (fun n => iteratedDeriv j (F n) x) atTop (𝓝 (iteratedDeriv j f' x)) := by + induction j with + | zero => + intro F f' hF _hFa x hx + simpa [iteratedDeriv_zero] using hF.tendsto_at hx + | succ j ih => + intro F f' hF hFa x hx + have hderiv : TendstoLocallyUniformlyOn (deriv ∘ F) (deriv f') atTop V := + hF.deriv (Filter.Eventually.of_forall hFa) hV + have hderivDiff : ∀ n, DifferentiableOn ℂ (deriv (F n)) V := fun n => + (DifferentiableOn.analyticOnNhd_of_finiteDimensional (hFa n) hV).deriv.differentiableOn + have := ih (deriv ∘ F) (deriv f') hderiv hderivDiff hx + simpa [iteratedDeriv_succ', Function.comp_def] using this + +/-- **Contraction estimate for the Picard iteration.** Consecutive Picard approximations +of the coordinate-power quotient by `g - h * s_k` differ by a geometrically shrinking +amount, given the numerator bound `M` for `g` and the small-perturbation bound on `h`. -/ +theorem picardApprox_diff_bound (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) + (M : ℝ) (hM0 : 0 ≤ M) (hgb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖g z‖ ≤ M) + (hhb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖h z‖ ≤ R ^ d / (2 * (d + 1))) : + ∀ k, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(picardApprox d r R hr hR h g hg hh (k + 1)).1 z - + (picardApprox d r R hr hR h g hg hh k).1 z‖ ≤ + ((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ k := by + intro k + induction k with + | zero => + intro z hz + have hb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(g - h * (picardApprox d r R hr hR h g hg hh 0).1) z‖ ≤ M := by + intro z hz + show ‖g z - h z * (picardApprox d r R hr hR h g hg hh 0).1 z‖ ≤ M + simpa [picardApprox] using hgb z hz + have hbnd := picardApprox_succ_bound d r R hr hR h g hg hh 0 M hM0 hb z hz + simpa [picardApprox] using hbnd + | succ k ih => + intro z hz + set sk := (picardApprox d r R hr hR h g hg hh k).1 with hskdef + set sk1 := (picardApprox d r R hr hR h g hg hh (k + 1)).1 with hsk1def + set sk2 := (picardApprox d r R hr hR h g hg hh (k + 2)).1 with hsk2def + set ak := picardApproxCoeff d r R hr hR h g hg hh k with hakdef + set ak1 := picardApproxCoeff d r R hr hR h g hg hh (k + 1) with hak1def + have hdivk := picardApprox_succ_isWeierstrassDivisionOn d r R hr hR h g hg hh k + have hdivk1 := picardApprox_succ_isWeierstrassDivisionOn d r R hr hR h g hg hh (k + 1) + have hQA : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (h * (sk1 - sk)) + (sk1 - sk2) (fun j => ak j - ak1 j) (polydisc 0 r) R := by + refine ⟨(picardApprox d r R hr hR h g hg hh (k + 1)).2.sub + (picardApprox d r R hr hR h g hg hh (k + 2)).2, + fun j => (hdivk.differentiableOn_coeff j).sub (hdivk1.differentiableOn_coeff j), ?_⟩ + intro w hw + have e1 := hdivk.eq hw + have e2 := hdivk1.eq hw + show h w * (sk1 w - sk w) = (sk1 w - sk2 w) * w.2 ^ d + + weierstrassRemainder (fun j => ak j - ak1 j) w + rw [← weierstrassRemainder_sub] + have e1' : g w - h w * sk w = sk1 w * w.2 ^ d + weierstrassRemainder ak w := e1 + have e2' : g w - h w * sk1 w = sk2 w * w.2 ^ d + weierstrassRemainder ak1 w := e2 + have : h w * (sk1 w - sk w) = (sk1 w * w.2 ^ d + weierstrassRemainder ak w) - + (sk2 w * w.2 ^ d + weierstrassRemainder ak1 w) := by + rw [← e1', ← e2']; ring + rw [this]; ring + obtain ⟨q'', a'', hdiv'', hbound'', huniq''⟩ := coordinatePower_division d hR + (hh.mul ((picardApprox d r R hr hR h g hg hh (k + 1)).2.sub + (picardApprox d r R hr hR h g hg hh k).2)) + have hEq := (huniq'' (sk1 - sk2) (fun j => ak j - ak1 j) hQA).1 + have hbndM : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(h * (sk1 - sk)) z‖ ≤ (R ^ d / (2 * (d + 1))) * + (((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ k) := by + intro z hz + show ‖h z * (sk1 z - sk z)‖ ≤ _ + rw [norm_mul] + exact mul_le_mul (hhb z hz) (ih z hz) (norm_nonneg _) (by positivity) + have hq''bound := hbound'' _ (by positivity) hbndM z hz + rw [hEq hz] at hq''bound + have hQval : ‖(sk1 - sk2) z‖ = ‖sk2 z - sk1 z‖ := by + rw [show (sk1 - sk2) z = sk1 z - sk2 z from rfl, ← norm_neg] + congr 1; ring + rw [hQval] at hq''bound + calc ‖sk2 z - sk1 z‖ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * + ((R ^ d / (2 * (d + 1))) * (((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ k)) := hq''bound + _ = ((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ (k + 1) := by + rw [pow_succ] + have hRd : R ^ d ≠ 0 := by positivity + have hd1 : ((d:ℝ) + 1) ≠ 0 := by positivity + push_cast + field_simp + +/-- **Locally uniform limit of the Picard iteration.** Under the contraction estimate of +`picardApprox_diff_bound`, the Picard approximations converge uniformly on the domain to an +analytic limit, with the geometric tail bound summed over all later steps. -/ +theorem exists_tendstoUniformlyOn_picardApprox (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) + (hR : 0 < R) (h g : (ι → ℂ) × ℂ → ℂ) (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball + 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) + (M : ℝ) (hM0 : 0 ≤ M) (hgb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖g z‖ ≤ M) + (hhb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖h z‖ ≤ R ^ d / (2 * (d + 1))) : + ∃ S : (ι → ℂ) × ℂ → ℂ, + AnalyticOnNhd ℂ S (polydisc 0 r ×ˢ ball 0 R) ∧ + ∀ n, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(picardApprox d r R hr hR h g hg hh n).1 z - S z‖ ≤ + ((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ n / (1 - 1 / 2) := by + set sSeq := fun k => picardApprox d r R hr hR h g hg hh k with hsSeqdef + set B : ℝ := ((d + 1 : ℕ) : ℝ) / R ^ d * M with hBdef + have hB0 : 0 ≤ B := by rw [hBdef]; positivity + have hdiff : ∀ k, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(sSeq (k + 1)).1 z - (sSeq k).1 z‖ ≤ B * (1 / 2) ^ k := + picardApprox_diff_bound d r R hr hR h g hg hh M hM0 hgb hhb + have hpt : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, CauchySeq (fun k => (sSeq k).1 z) := by + intro z hz + apply cauchySeq_of_le_geometric (r := 1 / 2) (C := B) (by norm_num) + intro n + rw [dist_eq_norm, norm_sub_rev] + exact hdiff n z hz + have hex : ∀ z : (ι → ℂ) × ℂ, ∃ y : ℂ, + z ∈ polydisc 0 r ×ˢ ball 0 R → Tendsto (fun k => (sSeq k).1 z) atTop (𝓝 y) := by + intro z + by_cases hz : z ∈ polydisc 0 r ×ˢ ball 0 R + · obtain ⟨y, hy⟩ := cauchySeq_tendsto_of_complete (hpt z hz) + exact ⟨y, fun _ => hy⟩ + · exact ⟨0, fun hz' => absurd hz' hz⟩ + choose S hStendsto using hex + have hSbound : ∀ n, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(sSeq n).1 z - S z‖ ≤ B * (1 / 2) ^ n / (1 - 1 / 2) := by + intro n z hz + have h := dist_le_of_le_geometric_of_tendsto (r := 1 / 2) (C := B) (by norm_num) + (f := fun k => (sSeq k).1 z) (fun k => by + rw [dist_eq_norm, norm_sub_rev]; exact hdiff k z hz) + (hStendsto z hz) n + rwa [dist_eq_norm] at h + have hTU : TendstoUniformlyOn (fun k z => (sSeq k).1 z) S atTop + (polydisc 0 r ×ˢ ball 0 R) := by + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + rcases eq_or_lt_of_le hB0 with hB0' | hB0' + · filter_upwards with n z hz + rw [dist_comm, dist_eq_norm] + calc ‖(sSeq n).1 z - S z‖ ≤ B * (1 / 2) ^ n / (1 - 1 / 2) := hSbound n z hz + _ = 0 := by rw [← hB0']; ring + _ < ε := hε + · obtain ⟨N, hN⟩ := exists_pow_lt_of_lt_one + (show (0:ℝ) < ε * (1 - 1/2) / B by positivity) (by norm_num : (1/2:ℝ) < 1) + filter_upwards [eventually_ge_atTop N] with n hn z hz + rw [dist_comm, dist_eq_norm] + calc ‖(sSeq n).1 z - S z‖ ≤ B * (1 / 2) ^ n / (1 - 1 / 2) := hSbound n z hz + _ ≤ B * (1 / 2) ^ N / (1 - 1 / 2) := by + have hpow : (1 / 2 : ℝ) ^ n ≤ (1 / 2 : ℝ) ^ N := + pow_le_pow_of_le_one (by norm_num) (by norm_num) hn + have hmul : B * (1 / 2 : ℝ) ^ n ≤ B * (1 / 2 : ℝ) ^ N := + mul_le_mul_of_nonneg_left hpow hB0 + exact div_le_div_of_nonneg_right hmul (by norm_num) + _ < ε := by + rw [div_lt_iff₀ (by norm_num : (0:ℝ) < 1 - 1/2), mul_comm] + exact (lt_div_iff₀ hB0').mp hN + have hSanalytic : AnalyticOnNhd ℂ S (polydisc 0 r ×ˢ ball 0 R) := + TendstoLocallyUniformlyOn.analyticOnNhd_of_finiteDimensional + hTU.tendstoLocallyUniformlyOn + (Filter.Eventually.of_forall fun k => + (sSeq k).2.analyticOnNhd_of_finiteDimensional (isOpen_polydisc _ _ |>.prod + isOpen_ball)) + (isOpen_polydisc _ _ |>.prod isOpen_ball) + exact ⟨S, hSanalytic, hSbound⟩ + +/-- The geometric error bound for Picard approximations also controls the remainders uniformly on +each scalar slice. -/ +private theorem tendstoUniformlyOn_picardRemainder + (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) + (h g : (ι → ℂ) × ℂ → ℂ) + (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) + (hhb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖h z‖ ≤ R ^ d / (2 * (d + 1))) + (M : ℝ) (hM0 : 0 ≤ M) (S : (ι → ℂ) × ℂ → ℂ) + (hSbound : ∀ k, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(picardApprox d r R hr hR h g hg hh k).1 z - S z‖ ≤ + ((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ k / (1 - 1 / 2)) + {w : ι → ℂ} (hw : w ∈ polydisc 0 r) : + TendstoUniformlyOn + (fun k ζ => g (w, ζ) - h (w, ζ) * (picardApprox d r R hr hR h g hg hh k).1 (w, ζ) - + ζ ^ d * (picardApprox d r R hr hR h g hg hh (k + 1)).1 (w, ζ)) + (fun ζ => g (w, ζ) - h (w, ζ) * S (w, ζ) - ζ ^ d * S (w, ζ)) + atTop (ball (0 : ℂ) R) := by + let sSeq := fun k => picardApprox d r R hr hR h g hg hh k + let B : ℝ := ((d + 1 : ℕ) : ℝ) / R ^ d * M + let rFun := fun z => g z - h z * S z - z.2 ^ d * S z + let Fk := fun k ζ => g (w, ζ) - h (w, ζ) * (sSeq k).1 (w, ζ) - + ζ ^ d * (sSeq (k + 1)).1 (w, ζ) + have hFkbound : ∀ k, ∀ ζ' ∈ ball (0 : ℂ) R, ‖Fk k ζ' - rFun (w, ζ')‖ ≤ + (R ^ d / (2 * (d + 1))) * (B * (1 / 2) ^ k / (1 - 1 / 2)) + + R ^ d * (B * (1 / 2) ^ (k + 1) / (1 - 1 / 2)) := by + intro k ζ' hζ' + have hwz' : (w, ζ') ∈ polydisc 0 r ×ˢ ball 0 R := ⟨hw, hζ'⟩ + have hb1 := hSbound k (w, ζ') hwz' + have hb2 := hSbound (k + 1) (w, ζ') hwz' + have hζ'le : ‖ζ'‖ ≤ R := (mem_ball_zero_iff.mp hζ').le + have hhle : ‖h (w, ζ')‖ ≤ R ^ d / (2 * (d + 1)) := hhb (w, ζ') hwz' + have hdiff_eq : Fk k ζ' - rFun (w, ζ') = + -(h (w, ζ') * ((sSeq k).1 (w, ζ') - S (w, ζ'))) - + ζ' ^ d * ((sSeq (k + 1)).1 (w, ζ') - S (w, ζ')) := by + show (g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - + ζ' ^ d * (sSeq (k + 1)).1 (w, ζ')) - + (g (w, ζ') - h (w, ζ') * S (w, ζ') - ζ' ^ d * S (w, ζ')) = _ + ring + rw [hdiff_eq] + calc ‖-(h (w, ζ') * ((sSeq k).1 (w, ζ') - S (w, ζ'))) - + ζ' ^ d * ((sSeq (k + 1)).1 (w, ζ') - S (w, ζ'))‖ + = ‖h (w, ζ') * ((sSeq k).1 (w, ζ') - S (w, ζ')) + + ζ' ^ d * ((sSeq (k + 1)).1 (w, ζ') - S (w, ζ'))‖ := by + rw [← norm_neg]; congr 1; ring + _ ≤ ‖h (w, ζ') * ((sSeq k).1 (w, ζ') - S (w, ζ'))‖ + + ‖ζ' ^ d * ((sSeq (k + 1)).1 (w, ζ') - S (w, ζ'))‖ := norm_add_le _ _ + _ = ‖h (w, ζ')‖ * ‖(sSeq k).1 (w, ζ') - S (w, ζ')‖ + + ‖ζ'‖ ^ d * ‖(sSeq (k + 1)).1 (w, ζ') - S (w, ζ')‖ := by + rw [norm_mul, norm_mul, norm_pow] + _ ≤ (R ^ d / (2 * (d + 1))) * (B * (1 / 2) ^ k / (1 - 1 / 2)) + + R ^ d * (B * (1 / 2) ^ (k + 1) / (1 - 1 / 2)) := by + gcongr + have hFktendsto : Tendsto (fun k => (R ^ d / (2 * (d + 1))) * (B * (1 / 2) ^ k / (1 - 1 / 2)) + + R ^ d * (B * (1 / 2) ^ (k + 1) / (1 - 1 / 2))) atTop (𝓝 0) := by + have h1 : Tendsto (fun k : ℕ => (1 / 2 : ℝ) ^ k) atTop (𝓝 0) := + tendsto_pow_atTop_nhds_zero_of_lt_one (by norm_num) (by norm_num) + have h2 : Tendsto (fun k : ℕ => (1 / 2 : ℝ) ^ (k + 1)) atTop (𝓝 0) := + h1.comp (tendsto_add_atTop_nat 1) + have e1 : Tendsto (fun k => (R ^ d / (2 * (d + 1))) * (B * (1 / 2) ^ k / (1 - 1 / 2))) + atTop (𝓝 ((R ^ d / (2 * (d + 1))) * (B * 0 / (1 - 1 / 2)))) := + ((h1.const_mul B).div_const (1 - 1/2)).const_mul _ + have e2 : Tendsto (fun k => R ^ d * (B * (1 / 2) ^ (k + 1) / (1 - 1 / 2))) + atTop (𝓝 (R ^ d * (B * 0 / (1 - 1 / 2)))) := + ((h2.const_mul B).div_const (1 - 1/2)).const_mul _ + simpa using e1.add e2 + have hFkTU : TendstoUniformlyOn Fk (fun ζ' => rFun (w, ζ')) atTop (ball (0:ℂ) R) := by + rw [Metric.tendstoUniformlyOn_iff] + intro ε hε + have := (Metric.tendsto_atTop.mp hFktendsto) ε hε + obtain ⟨N, hN⟩ := this + filter_upwards [eventually_ge_atTop N] with k hk ζ' hζ' + rw [dist_comm, dist_eq_norm] + calc ‖Fk k ζ' - rFun (w, ζ')‖ ≤ _ := hFkbound k ζ' hζ' + _ = ‖(R ^ d / (2 * (d + 1))) * (B * (1 / 2) ^ k / (1 - 1 / 2)) + + R ^ d * (B * (1 / 2) ^ (k + 1) / (1 - 1 / 2)) - 0‖ := by + rw [sub_zero] + rw [Real.norm_of_nonneg (by positivity)] + _ < ε := hN k hk + exact hFkTU + +/-- A uniform limit of scalar polynomials of degree less than `d` is the polynomial formed from its +first `d` Taylor coefficients. Derivative convergence identifies the coefficients, and the +finite sum then passes to the limit. -/ +private theorem eq_taylorPolynomial_of_tendstoUniformlyOn {d : ℕ} {R : ℝ} (hR : 0 < R) + {F : ℕ → ℂ → ℂ} {f : ℂ → ℂ} {a : ℕ → Fin d → ℂ} + (hpoly : ∀ k, EqOn (F k) (fun ζ => ∑ j : Fin d, a k j * ζ ^ (j : ℕ)) (ball 0 R)) + (hlim : TendstoUniformlyOn F f atTop (ball 0 R)) + (hdiff : ∀ k, DifferentiableOn ℂ (F k) (ball 0 R)) + {ζ : ℂ} (hζ : ζ ∈ ball 0 R) : + f ζ = ∑ j : Fin d, (((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) f 0) * ζ ^ (j : ℕ) := by + have hcoeff (j : Fin d) : Tendsto (fun k => a k j) atTop + (𝓝 (((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) f 0)) := by + have hder := tendsto_iteratedDeriv_of_tendstoLocallyUniformlyOn isOpen_ball + (j : ℕ) F f hlim.tendstoLocallyUniformlyOn hdiff (mem_ball_self hR) + have heq (k : ℕ) : iteratedDeriv (j : ℕ) (F k) 0 = + ((j : ℕ).factorial : ℂ) * a k j := by + rw [(Filter.eventuallyEq_of_mem (ball_mem_nhds 0 hR) (hpoly k)).iteratedDeriv_eq, + iteratedDeriv_weierstrassRemainder_const, dite_eq_left j.isLt] + have h := hder.const_mul (((j : ℕ).factorial : ℂ)⁻¹) + have hfac : ((j : ℕ).factorial : ℂ) ≠ 0 := by exact_mod_cast (j : ℕ).factorial_ne_zero + simpa only [heq, ← mul_assoc, inv_mul_cancel₀ hfac, + one_mul] using h + have hsum := tendsto_finsetSum Finset.univ (fun j _ => (hcoeff j).mul_const (ζ ^ (j : ℕ))) + have hvalue : Tendsto (fun k => F k ζ) atTop + (𝓝 (∑ j : Fin d, (((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) f 0) * ζ ^ (j : ℕ))) := + hsum.congr' (.of_forall fun k => (hpoly k hζ).symm) + exact tendsto_nhds_unique (hlim.tendsto_at hζ) hvalue + +/-- **The remainder of a Picard limit is itself a Weierstrass remainder.** Given a bound +on the distance from each Picard approximation to a limit `S` (as produced by +`exists_tendstoUniformlyOn_picardApprox`), the limiting perturbed-division remainder +`g - h * S - ζ ^ d * S` is the Weierstrass remainder of the coefficients obtained by +passing derivatives of the numerator's slices to the limit. No identity theorem is used: +each Taylor coefficient of the remainder is recovered directly as the limit of the +corresponding coefficient of the finite Picard step. -/ +theorem exists_weierstrassRemainder_eq_of_tendstoUniformlyOn_picardApprox + (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i, 0 < r i) (hR : 0 < R) (h g : (ι → ℂ) × ℂ → ℂ) + (hg : DifferentiableOn ℂ g (polydisc 0 r ×ˢ ball 0 R)) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) + (hhb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖h z‖ ≤ R ^ d / (2 * (d + 1))) + (M : ℝ) (hM0 : 0 ≤ M) (S : (ι → ℂ) × ℂ → ℂ) + (hSdiff : DifferentiableOn ℂ S (polydisc 0 r ×ˢ ball 0 R)) + (hSbound : ∀ n, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, + ‖(picardApprox d r R hr hR h g hg hh n).1 z - S z‖ ≤ + ((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ n / (1 - 1 / 2)) : + ∃ a : Fin d → (ι → ℂ) → ℂ, (∀ j, DifferentiableOn ℂ (a j) (polydisc (0 : ι → ℂ) r)) ∧ + ∀ w ∈ polydisc (0 : ι → ℂ) r, ∀ ζ ∈ ball (0 : ℂ) R, + g (w, ζ) - h (w, ζ) * S (w, ζ) - ζ ^ d * S (w, ζ) = weierstrassRemainder a (w, ζ) := by + set sSeq := fun k => picardApprox d r R hr hR h g hg hh k with hsSeqdef + set rFun : (ι → ℂ) × ℂ → ℂ := fun z => g z - h z * S z - z.2 ^ d * S z with hrFundef + set aOut : Fin d → (ι → ℂ) → ℂ := fun j w => + ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) (fun ζ => rFun (w, ζ)) 0 with haOutdef + have hrFunDiffFull : DifferentiableOn ℂ rFun (polydisc 0 r ×ˢ ball 0 R) := by + have h4 : DifferentiableOn ℂ (fun z : (ι → ℂ) × ℂ => z.2 ^ d) + (polydisc 0 r ×ˢ ball 0 R) := (differentiableOn_snd).pow d + exact (hg.sub (hh.mul hSdiff)).sub (h4.mul hSdiff) + have haDiff : ∀ j, DifferentiableOn ℂ (aOut j) (polydisc (0 : ι → ℂ) r) := fun j => + (differentiableOn_iteratedDeriv_snd_slice (isOpen_polydisc _ _) + hrFunDiffFull hR (j : ℕ)).const_mul _ + refine ⟨aOut, haDiff, fun w hw ζ hζ => ?_⟩ + set Fk : ℕ → ℂ → ℂ := fun k ζ' => + g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - ζ' ^ d * (sSeq (k + 1)).1 (w, ζ') with hFkdef + have hFkeq : ∀ k, ∀ ζ' ∈ ball (0 : ℂ) R, Fk k ζ' = + weierstrassRemainder (picardApproxCoeff d r R hr hR h g hg hh k) (w, ζ') := by + intro k ζ' hζ' + have hthis := (picardApprox_succ_isWeierstrassDivisionOn d r R hr hR h g hg hh k).eq + (⟨hw, hζ'⟩ : (w, ζ') ∈ polydisc 0 r ×ˢ ball 0 R) + show g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - ζ' ^ d * (sSeq (k + 1)).1 (w, ζ') = _ + have hthis' : g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') = + (sSeq (k + 1)).1 (w, ζ') * ζ' ^ d + + weierstrassRemainder (picardApproxCoeff d r R hr hR h g hg hh k) (w, ζ') := hthis + rw [hthis']; ring + have hFkTU : TendstoUniformlyOn Fk (fun ζ' => rFun (w, ζ')) atTop (ball (0 : ℂ) R) := + tendstoUniformlyOn_picardRemainder d r R hr hR h g hg hh hhb M hM0 S hSbound hw + have hFkDiff : ∀ k, DifferentiableOn ℂ (Fk k) (ball (0 : ℂ) R) := by + intro k + have h1 : DifferentiableOn ℂ (fun ζ' => g (w, ζ')) (ball (0:ℂ) R) := + differentiableOn_snd_slice hg hw + have h2 : DifferentiableOn ℂ (fun ζ' => h (w, ζ')) (ball (0:ℂ) R) := + differentiableOn_snd_slice hh hw + have h3 : DifferentiableOn ℂ (fun ζ' => (sSeq k).1 (w, ζ')) (ball (0:ℂ) R) := + differentiableOn_snd_slice (sSeq k).2 hw + have h4 : DifferentiableOn ℂ (fun ζ' => (sSeq (k+1)).1 (w, ζ')) (ball (0:ℂ) R) := + differentiableOn_snd_slice (sSeq (k+1)).2 hw + exact (h1.sub (h2.mul h3)).sub ((differentiableOn_pow d).mul h4) + exact eq_taylorPolynomial_of_tendstoUniformlyOn + (a := fun k j => picardApproxCoeff d r R hr hR h g hg hh k j w) + hR hFkeq hFkTU hFkDiff hζ + +/-- **Direct uniqueness for the perturbed coordinate-power fixed-point equation.** +If `h` is uniformly small relative to `R` on a domain, any two decompositions of the +*same* `g` against the divisor `z ^ d + h`, each individually bounded there, agree. -/ +theorem eqOn_of_isWeierstrassDivisionOn_selfPerturbed {d : ℕ} {r : ι → ℝ} {R : ℝ} + (hR : 0 < R) (h g s s' : (ι → ℂ) × ℂ → ℂ) (a a' : Fin d → (ι → ℂ) → ℂ) + (hh : DifferentiableOn ℂ h (polydisc 0 r ×ˢ ball 0 R)) + (hhb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖h z‖ ≤ R ^ d / (2 * (d + 1))) + (hdiv : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - h * s) s a (polydisc 0 r) R) + (hdiv' : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - h * s') s' a' + (polydisc 0 r) R) + (M : ℝ) (hM0 : 0 ≤ M) (hsb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖s z - s' z‖ ≤ M) : + EqOn s s' (polydisc 0 r ×ˢ ball 0 R) ∧ ∀ j, EqOn (a j) (a' j) (polydisc 0 r) + := by + suffices hs : EqOn s s' (polydisc 0 r ×ˢ ball 0 R) by + refine ⟨hs, ?_⟩ + have hdiv2 : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (g - h * s) s' a' + (polydisc 0 r) R := + ⟨hdiv'.differentiableOn_quotient, + hdiv'.differentiableOn_coeff, + fun z hz => by + show (g z - h z * s z) = s' z * z.2 ^ d + weierstrassRemainder a' z + rw [hs hz] + exact hdiv'.eq hz⟩ + exact (unique_coordinatePower_division hdiv hdiv2 hR).2 + have hQA : ∀ M' : ℝ, 0 ≤ M' → + (∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖s z - s' z‖ ≤ M') → + ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖s z - s' z‖ ≤ M' / 2 := by + intro M' hM'0 hM' z hz + have hQAdiv : IsWeierstrassDivisionOn (fun z => z.2 ^ d) (h * (s' - s)) (s - s') + (fun j => a j - a' j) (polydisc 0 r) R := by + refine ⟨hdiv.differentiableOn_quotient.sub hdiv'.differentiableOn_quotient, + fun j => (hdiv.differentiableOn_coeff j).sub (hdiv'.differentiableOn_coeff j), ?_⟩ + intro w hw + have e1 : g w - h w * s w = s w * w.2 ^ d + weierstrassRemainder a w := hdiv.eq hw + have e2 : g w - h w * s' w = s' w * w.2 ^ d + weierstrassRemainder a' w := hdiv'.eq hw + show h w * (s' w - s w) = (s w - s' w) * w.2 ^ d + weierstrassRemainder (fun j => a j - a' + j) w + rw [← weierstrassRemainder_sub] + have : h w * (s' w - s w) = (s w * w.2 ^ d + weierstrassRemainder a w) - + (s' w * w.2 ^ d + weierstrassRemainder a' w) := by rw [← e1, ← e2]; ring + rw [this]; ring + have hhdiff : DifferentiableOn ℂ (h * (s' - s)) (polydisc 0 r ×ˢ ball 0 R) := + hh.mul (hdiv'.differentiableOn_quotient.sub hdiv.differentiableOn_quotient) + obtain ⟨q'', a'', hdiv'', hbound'', huniq''⟩ := coordinatePower_division d hR hhdiff + have hEq := (huniq'' (s - s') (fun j => a j - a' j) hQAdiv).1 + have hb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖(h * (s' - s)) z‖ ≤ + (R ^ d / (2 * (d + 1))) * M' := by + intro z hz + show ‖h z * (s' z - s z)‖ ≤ _ + rw [norm_mul, ← norm_sub_rev (s z) (s' z)] + exact mul_le_mul (hhb z hz) (hM' z hz) (norm_nonneg _) (by positivity) + have hq''bound := hbound'' _ (by positivity) hb z hz + rw [hEq hz] at hq''bound + calc ‖s z - s' z‖ = ‖(s - s') z‖ := rfl + _ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * ((R ^ d / (2 * (d + 1))) * M') := hq''bound + _ = M' / 2 := by + have hRd : R ^ d ≠ 0 := by positivity + have hd1 : ((d : ℝ) + 1) ≠ 0 := by positivity + push_cast + field_simp + have hind : ∀ n, ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖s z - s' z‖ ≤ M * (1 / 2) ^ n := by + intro n + induction n with + | zero => simpa using hsb + | succ n ih => + intro z hz + have := hQA (M * (1/2)^n) (by positivity) ih z hz + calc ‖s z - s' z‖ ≤ M * (1/2)^n / 2 := this + _ = M * (1/2)^(n+1) := by ring + intro z hz + have htendsto : Tendsto (fun n => M * (1 / 2 : ℝ) ^ n) atTop (𝓝 0) := by + have := tendsto_pow_atTop_nhds_zero_of_lt_one (r := (1/2:ℝ)) (by norm_num) (by norm_num) + simpa using this.const_mul M + have hle : ‖s z - s' z‖ ≤ 0 := + ge_of_tendsto htendsto (Filter.Eventually.of_forall fun n => hind n z hz) + have := norm_nonneg (s z - s' z) + have heq0 : ‖s z - s' z‖ = 0 := le_antisymm hle this + exact sub_eq_zero.mp (norm_eq_zero.mp heq0) + +end SeveralComplexVariables.WeierstrassDivision + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean new file mode 100644 index 0000000000..01f806110b --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean @@ -0,0 +1,314 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision + +/-! +# Analytic Weierstrass preparation + +A function regular of order `d` in the distinguished coordinate factors locally as a +nonvanishing holomorphic function times a monic polynomial of degree `d`. The lower coefficients +are holomorphic in the parameters and vanish at the parameter origin. + +Reference: [Jakóbczak–Jarnicki][JakobczakJarnicki2021], Theorem 1.7.2. Preparation and its +uniqueness are derived from the analytic division theorem. The proof includes degree zero, and +empty parameter types recover one-variable theory. + +## Main definitions + +* `weierstrassPolynomial`: The monic polynomial in the distinguished coordinate with prescribed + lower coefficients. +* `IsWeierstrassPreparationAt`: Local preparation consists of a unit and a monic polynomial whose + lower coefficients vanish at the parameter origin. + +## Main results + +* `exists_isWeierstrassPreparationAt`: **Weierstrass preparation for analytic germs.** Divide `w^d` + by `f`, identify the central coefficients using one-variable order factorization and division + uniqueness, and invert the resulting quotient. +* `exists_eqOn_mul_weierstrassPolynomial`: **Weierstrass preparation + ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.2).** On a sufficiently small polydisc, a regular + holomorphic function is a nonvanishing holomorphic factor times a monic polynomial with + holomorphic lower coefficients vanishing at the origin. +* `exists_isWeierstrassPreparationAt_of_finiteDimensional`: **Weierstrass preparation for analytic + germs on any finite-dimensional parameter space.** Obtained by transporting the coordinate version + along a basis; no choice of coordinates occurs in the statement. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public noncomputable section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- The monic polynomial in the distinguished coordinate with prescribed lower coefficients. -/ +@[expose] def weierstrassPolynomial {d : ℕ} (a : Fin d → E → ℂ) (z : E × ℂ) : ℂ := + z.2 ^ d + weierstrassRemainder a z + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] in +/-- Negating the coefficient functions negates the remainder polynomial. -/ +@[simp] theorem weierstrassRemainder_neg {d : ℕ} (a : Fin d → E → ℂ) (z : E × ℂ) : + weierstrassRemainder (fun j x => -a j x) z = -weierstrassRemainder a z := by + simp [weierstrassRemainder, Finset.sum_neg_distrib] + +omit [NormedAddCommGroup E] [NormedSpace ℂ E] in +/-- A monic polynomial of degree zero is the constant one. -/ +@[simp] theorem weierstrassPolynomial_zero (a : Fin 0 → E → ℂ) : + weierstrassPolynomial a = 1 := by + funext z + simp [weierstrassPolynomial] + +/-- Analytic coefficients give a jointly analytic monic polynomial. -/ +theorem analyticAt_weierstrassPolynomial {d : ℕ} {a : Fin d → E → ℂ} {z : E × ℂ} + (ha : ∀ j, AnalyticAt ℂ (a j) z.1) : AnalyticAt ℂ (weierstrassPolynomial a) z := + (analyticAt_snd.pow d).add (analyticAt_weierstrassRemainder ha) + +omit [NormedSpace ℂ E] in +/-- Vanishing of the lower coefficients gives the central monomial. -/ +theorem weierstrassPolynomial_central {d : ℕ} {a : Fin d → E → ℂ} + (ha : ∀ j, a j 0 = 0) (w : ℂ) : weierstrassPolynomial a (0, w) = w ^ d := by + simp [weierstrassPolynomial, weierstrassRemainder, ha] + +/-- Local preparation consists of a unit and a monic polynomial whose lower coefficients vanish at +the parameter origin. Equality is equality of germs at the origin. -/ +structure IsWeierstrassPreparationAt {d : ℕ} (f u : E × ℂ → ℂ) + (a : Fin d → E → ℂ) : Prop where + /-- The unit factor is analytic at the origin. -/ + analyticAt_unit : AnalyticAt ℂ u 0 + /-- The unit factor does not vanish at the origin. -/ + unit_ne_zero : u 0 ≠ 0 + /-- Each polynomial coefficient is analytic at the parameter origin. -/ + analyticAt_coeff : ∀ j, AnalyticAt ℂ (a j) 0 + /-- All lower polynomial coefficients vanish at the parameter origin. -/ + coeff_zero : ∀ j, a j 0 = 0 + /-- As germs, the function equals the unit times the distinguished polynomial. -/ + eq : f =ᶠ[𝓝 0] fun z => u z * weierstrassPolynomial a z + +/-- A nonvanishing analytic function is already prepared in degree zero. -/ +theorem isWeierstrassPreparationAt_zero {f : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (h0 : f 0 ≠ 0) : + IsWeierstrassPreparationAt f f (fun j : Fin 0 => Fin.elim0 j) := by + refine ⟨hf, h0, fun j => Fin.elim0 j, fun j => Fin.elim0 j, ?_⟩ + exact .of_forall fun z => by simp + +/-- A preparation gives a division of the monomial by the original function. -/ +theorem IsWeierstrassPreparationAt.division {d : ℕ} {f u : E × ℂ → ℂ} + {a : Fin d → E → ℂ} (h : IsWeierstrassPreparationAt f u a) : + IsWeierstrassDivisionAt f (fun z => z.2 ^ d) (fun z => (u z)⁻¹) + (fun j x => -a j x) := by + refine ⟨h.analyticAt_unit.inv h.unit_ne_zero, fun j => (h.analyticAt_coeff j).neg, ?_⟩ + filter_upwards [h.eq, h.analyticAt_unit.continuousAt.eventually_ne h.unit_ne_zero] with z hz hne + rw [hz, weierstrassRemainder_neg] + simp [weierstrassPolynomial, hne] + +variable {ι : Type*} [Fintype ι] + +/-- Uniqueness of preparation follows from uniqueness of analytic division. Thus it rests on the +division theorem. -/ +theorem IsWeierstrassPreparationAt.unique {d : ℕ} {f u v : (ι → ℂ) × ℂ → ℂ} + {a b : Fin d → (ι → ℂ) → ℂ} + (h : IsWeierstrassPreparationAt f u a) (h' : IsWeierstrassPreparationAt f v b) + (hf : AnalyticAt ℂ f 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + u =ᶠ[𝓝 0] v ∧ ∀ j, a j =ᶠ[𝓝 0] b j := by + obtain ⟨hu, ha⟩ := h.division.unique h'.division hf (analyticAt_snd.pow d) horder + refine ⟨hu.mono (fun z hz => inv_injective hz), fun j => ?_⟩ + exact (ha j).mono (fun z hz => neg_injective hz) + +/-- Uniqueness of the factors and coefficients on a whole product domain follows from germ +uniqueness and the identity theorem. This applies to the polydisc of preparation. -/ +theorem IsWeierstrassPreparationAt.unique_on {d : ℕ} {f u v : (ι → ℂ) × ℂ → ℂ} + {a b : Fin d → (ι → ℂ) → ℂ} {V : Set (ι → ℂ)} {R : ℝ} + (h : IsWeierstrassPreparationAt f u a) (h' : IsWeierstrassPreparationAt f v b) + (hf : AnalyticAt ℂ f 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) + (hV : IsOpen V) (hconn : IsPreconnected V) (h0 : 0 ∈ V) (hR : 0 < R) + (hu : DifferentiableOn ℂ u (V ×ˢ ball 0 R)) + (hv : DifferentiableOn ℂ v (V ×ˢ ball 0 R)) + (ha : ∀ j, DifferentiableOn ℂ (a j) V) (hb : ∀ j, DifferentiableOn ℂ (b j) V) : + EqOn u v (V ×ˢ ball 0 R) ∧ ∀ j, EqOn (a j) (b j) V := by + obtain ⟨he, he'⟩ := h.unique h' hf horder + exact ⟨DifferentiableOn.eqOn_of_preconnected_of_eventuallyEq + (show IsOpen (V ×ˢ ball (0 : ℂ) R) from hV.prod isOpen_ball) + (hconn.prod (convex_ball (0 : ℂ) R).isPreconnected) + hu hv ⟨h0, mem_ball_self hR⟩ he, + fun j => (ha j).eqOn_of_preconnected_of_eventuallyEq hV hconn (hb j) h0 (he' j)⟩ + +/-- **Weierstrass preparation for analytic germs.** Divide `w^d` by `f`, identify the +central coefficients using one-variable order factorization and division uniqueness, +and invert the resulting quotient. This proof depends on analytic division. -/ +theorem exists_isWeierstrassPreparationAt {d : ℕ} {f : (ι → ℂ) × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (u : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), + IsWeierstrassPreparationAt f u a ∧ + ∀ v b, IsWeierstrassPreparationAt f v b → + u =ᶠ[𝓝 0] v ∧ ∀ j, a j =ᶠ[𝓝 0] b j := by + have hp : AnalyticAt ℂ (fun z : (ι → ℂ) × ℂ => z.2 ^ d) 0 := analyticAt_snd.pow d + obtain ⟨q, a, hD, _⟩ := exists_isWeierstrassDivisionAt hf hp horder + have hs : AnalyticAt ℂ (fun w : ℂ => f (0, w)) 0 := + hf.comp_of_eq (analyticAt_const.prod analyticAt_id) rfl + obtain ⟨v, hv, hv0, hfv⟩ := hs.analyticOrderAt_eq_natCast.mp horder + have hc : AnalyticAt ℂ (fun z : (ι → ℂ) × ℂ => ((0 : ι → ℂ), z.2)) 0 := + analyticAt_const.prod analyticAt_snd + have hDc : IsWeierstrassDivisionAt (fun z : (ι → ℂ) × ℂ => f (0, z.2)) + (fun z => z.2 ^ d) (fun z => q (0, z.2)) (fun j _ => a j 0) := by + refine ⟨hD.analyticAt_quotient.comp_of_eq hc rfl, fun _ => analyticAt_const, ?_⟩ + exact hD.eq.comp_tendsto hc.continuousAt + have hDv : IsWeierstrassDivisionAt (fun z : (ι → ℂ) × ℂ => f (0, z.2)) + (fun z => z.2 ^ d) (fun z => (v z.2)⁻¹) (fun _ _ => 0 : Fin d → (ι → ℂ) → ℂ) := by + refine ⟨(hv.comp_of_eq (analyticAt_snd (𝕜 := ℂ) + (p := (0 : (ι → ℂ) × ℂ))) rfl).inv hv0, fun _ => analyticAt_const, ?_⟩ + have ht : Tendsto (Prod.snd : (ι → ℂ) × ℂ → ℂ) (𝓝 0) (𝓝 0) := + continuous_snd.tendsto 0 + filter_upwards [ht.eventually hfv, ht.eventually (hv.continuousAt.eventually_ne hv0)] + with z hz hne + simp only [sub_zero, smul_eq_mul] at hz + simp [weierstrassRemainder, hz, hne, mul_comm] + obtain ⟨hq, ha⟩ := hDc.unique hDv (hf.comp_of_eq hc rfl) hp horder + have hq0 : q 0 ≠ 0 := by + have he : q 0 = (v 0)⁻¹ := hq.eq_of_nhds + rw [he] + exact inv_ne_zero hv0 + have ha0 : ∀ j, a j 0 = 0 := fun j => (ha j).eq_of_nhds + have H : IsWeierstrassPreparationAt f (fun z => (q z)⁻¹) (fun j x => -a j x) := by + refine ⟨hD.analyticAt_quotient.inv hq0, inv_ne_zero hq0, + fun j => (hD.analyticAt_coeff j).neg, fun j => by simp [ha0], ?_⟩ + filter_upwards [hD.eq, hD.analyticAt_quotient.continuousAt.eventually_ne hq0] with z hz hne + simp only [weierstrassPolynomial, weierstrassRemainder_neg] + apply (mul_left_cancel₀ hne) + rw [← mul_assoc, mul_inv_cancel₀ hne, one_mul] + linear_combination -hz + exact ⟨_, _, H, fun v b hb => H.unique hb hf horder⟩ + +/-- **Weierstrass preparation ([Jakóbczak–Jarnicki][JakobczakJarnicki2021] 1.7.2).** On a +sufficiently small +polydisc, a regular holomorphic function is a nonvanishing holomorphic factor times a +monic polynomial with holomorphic lower coefficients vanishing at the origin. +The factorization is unique as a germ. The proof depends on analytic division. -/ +theorem exists_eqOn_mul_weierstrassPolynomial {d : ℕ} {f : (ι → ℂ) × ℂ → ℂ} + {U : Set ((ι → ℂ) × ℂ)} (hU : IsOpen U) (h0 : 0 ∈ U) + (hf : DifferentiableOn ℂ f U) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (r : ι → ℝ) (R : ℝ) (u : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), + (∀ i, 0 < r i) ∧ 0 < R ∧ polydisc 0 r ×ˢ ball 0 R ⊆ U ∧ + DifferentiableOn ℂ u (polydisc 0 r ×ˢ ball 0 R) ∧ + (∀ z ∈ polydisc 0 r ×ˢ ball 0 R, u z ≠ 0) ∧ + (∀ j, DifferentiableOn ℂ (a j) (polydisc 0 r)) ∧ + (∀ j, a j 0 = 0) ∧ + EqOn f (fun z => u z * weierstrassPolynomial a z) (polydisc 0 r ×ˢ ball 0 R) ∧ + ∀ v b, IsWeierstrassPreparationAt f v b → + u =ᶠ[𝓝 0] v ∧ ∀ j, a j =ᶠ[𝓝 0] b j := by + obtain ⟨u, a, H, hu⟩ := exists_isWeierstrassPreparationAt + ((hf.analyticOnNhd_of_finiteDimensional hU) _ h0) horder + have ha' : ∀ᶠ x in 𝓝 (0 : ι → ℂ), ∀ j, AnalyticAt ℂ (a j) x := + Filter.eventually_all.mpr (fun j => (H.analyticAt_coeff j).eventually_analyticAt) + have ha : ∀ᶠ z : (ι → ℂ) × ℂ in 𝓝 0, ∀ j, AnalyticAt ℂ (a j) z.1 := + by + have ht : Tendsto (Prod.fst : (ι → ℂ) × ℂ → (ι → ℂ)) (𝓝 0) (𝓝 0) := + continuous_fst.tendsto 0 + exact ht.eventually ha' + have hU' : ∀ᶠ z in 𝓝 (0 : (ι → ℂ) × ℂ), z ∈ U := hU.mem_nhds h0 + have hn := hU'.and (H.analyticAt_unit.eventually_analyticAt.and + ((H.analyticAt_unit.continuousAt.eventually_ne H.unit_ne_zero).and (ha.and H.eq))) + obtain ⟨ε, hε, hball⟩ := Metric.mem_nhds_iff.mp hn + have hP : polydisc (0 : ι → ℂ) (fun _ => ε) ×ˢ ball (0 : ℂ) ε = + ball (0 : (ι → ℂ) × ℂ) ε := by + rw [polydisc_const_eq_ball _ hε, ball_prod_same] + rfl + have hprop := fun z (hz : z ∈ polydisc (0 : ι → ℂ) (fun _ => ε) ×ˢ ball (0 : ℂ) ε) => + hball (hP ▸ hz) + refine ⟨fun _ => ε, ε, u, a, fun _ => hε, hε, fun z hz => (hprop z hz).1, + fun z hz => (hprop z hz).2.1.differentiableAt.differentiableWithinAt, + fun z hz => (hprop z hz).2.2.1, ?_, H.coeff_zero, + fun z hz => (hprop z hz).2.2.2.2, hu⟩ + intro j z hz + exact ((hprop (z, 0) ⟨hz, mem_ball_self hε⟩).2.2.2.1 j).differentiableAt.differentiableWithinAt + +/-- Preparation transports along a continuous linear equivalence of the parameter space. -/ +theorem IsWeierstrassPreparationAt.comp_equiv {F : Type*} [NormedAddCommGroup F] + [NormedSpace ℂ F] (φ : F ≃L[ℂ] E) {d : ℕ} {f u : E × ℂ → ℂ} {a : Fin d → E → ℂ} + (h : IsWeierstrassPreparationAt f u a) : + IsWeierstrassPreparationAt (fun z : F × ℂ => f (φ z.1, z.2)) + (fun z : F × ℂ => u (φ z.1, z.2)) (fun j x => a j (φ x)) := by + have hφ : AnalyticAt ℂ φ (0 : F) := φ.toContinuousLinearMap.analyticAt 0 + have hφmap : φ (0 : F) = 0 := φ.map_zero + have hpair : AnalyticAt ℂ (fun z : F × ℂ => (φ z.1, z.2)) (0 : F × ℂ) := + (hφ.comp_of_eq analyticAt_fst rfl).prod analyticAt_snd + have h0 : (fun z : F × ℂ => (φ z.1, z.2)) 0 = (0 : E × ℂ) := by simp [hφmap] + have ht : Tendsto (fun z : F × ℂ => (φ z.1, z.2)) (𝓝 0) (𝓝 (0 : E × ℂ)) := by + rw [← h0]; exact hpair.continuousAt.tendsto + refine ⟨h.analyticAt_unit.comp_of_eq hpair h0, + by show u (φ 0, (0 : ℂ)) ≠ 0; rw [hφmap]; exact h.unit_ne_zero, + fun j => (h.analyticAt_coeff j).comp_of_eq hφ hφmap, + fun j => by show a j (φ (0 : F)) = 0; rw [hφmap]; exact h.coeff_zero j, + (h.eq.comp_tendsto ht).mono fun z hz => by + simpa [weierstrassPolynomial, weierstrassRemainder] using hz⟩ + +/-- **Weierstrass preparation for analytic germs on any finite-dimensional parameter space.** +Obtained by transporting the coordinate version along a basis; no choice of coordinates +occurs in the statement. -/ +theorem exists_isWeierstrassPreparationAt_of_finiteDimensional [FiniteDimensional ℂ E] {d : ℕ} + {f : E × ℂ → ℂ} + (hf : AnalyticAt ℂ f 0) (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (u : E × ℂ → ℂ) (a : Fin d → E → ℂ), + IsWeierstrassPreparationAt f u a ∧ + ∀ v b, IsWeierstrassPreparationAt f v b → + u =ᶠ[𝓝 0] v ∧ ∀ j, a j =ᶠ[𝓝 0] b j := by + set e := (Module.finBasis ℂ E).equivFunL with he_def + set g : (Fin (Module.finrank ℂ E) → ℂ) × ℂ → ℂ := fun z => f (e.symm z.1, z.2) with hg_def + have hg0 : (fun w : ℂ => g (0, w)) = fun w : ℂ => f (0, w) := by funext w; simp [hg_def] + have hgan : AnalyticAt ℂ g 0 := + hf.comp_of_eq (((e.symm.toContinuousLinearMap.analyticAt 0).comp_of_eq analyticAt_fst rfl).prod + analyticAt_snd) (by simp) + have hgorder : analyticOrderAt (fun w : ℂ => g (0, w)) 0 = d := by rw [hg0]; exact horder + obtain ⟨v, b, Hg, huniqg⟩ := exists_isWeierstrassPreparationAt hgan hgorder + have hf_eq : f = fun z : E × ℂ => g (e z.1, z.2) := by funext z; simp [hg_def] + have Hf : IsWeierstrassPreparationAt f (fun z : E × ℂ => v (e z.1, z.2)) + (fun j x => b j (e x)) := by + rw [hf_eq]; exact Hg.comp_equiv e + refine ⟨_, _, Hf, fun v' a' Hv' => ?_⟩ + have Hv'' : IsWeierstrassPreparationAt g (fun z => v' (e.symm z.1, z.2)) + (fun j x => a' j (e.symm x)) := by + rw [hg_def]; exact Hv'.comp_equiv e.symm + obtain ⟨huv, hab⟩ := huniqg _ _ Hv'' + have ht : Tendsto (fun z : E × ℂ => (e z.1, z.2)) (𝓝 0) + (𝓝 (0 : (Fin (Module.finrank ℂ E) → ℂ) × ℂ)) := by + have h0 : (fun z : E × ℂ => (e z.1, z.2)) 0 = (0 : (Fin (Module.finrank ℂ E) → ℂ) × ℂ) := by + simp + rw [← h0] + exact (((e.toContinuousLinearMap.analyticAt 0).comp_of_eq analyticAt_fst rfl).prod + analyticAt_snd).continuousAt.tendsto + refine ⟨(huv.comp_tendsto ht).mono fun z hz => ?_, fun j => ?_⟩ + · simpa using hz + · have htj : Tendsto e (𝓝 (0 : E)) (𝓝 (0 : Fin (Module.finrank ℂ E) → ℂ)) := by + simpa using (e.toContinuousLinearMap.analyticAt 0).continuousAt.tendsto + exact ((hab j).comp_tendsto htj).mono fun x hx => by simpa using hx + +/-- Preparation gives a factorization in the analytic germ ring with an invertible factor. -/ +theorem IsWeierstrassPreparationAt.germ_factorization {d : ℕ} {f u : E × ℂ → ℂ} + {a : Fin d → E → ℂ} (h : IsWeierstrassPreparationAt f u a) + (hf : AnalyticAt ℂ f 0) : + IsUnit (AnalyticGerm.ofAnalyticAt u h.analyticAt_unit) ∧ + AnalyticGerm.ofAnalyticAt f hf = AnalyticGerm.ofAnalyticAt u h.analyticAt_unit * + AnalyticGerm.ofAnalyticAt (weierstrassPolynomial a) + (analyticAt_weierstrassPolynomial h.analyticAt_coeff) := by + refine ⟨(AnalyticGerm.isUnit_iff _).mpr h.unit_ne_zero, ?_⟩ + apply Subtype.ext + exact Germ.coe_eq.mpr h.eq + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets.lean new file mode 100644 index 0000000000..1fa74bd6ff --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local + +/-! +# Zero sets in several complex variables + +The identity-principle consequences in `ZeroSets.Basic` and the local zero-set comparison +theorems in `ZeroSets.Local` are re-exported here. Isolated scalar zeros are excluded by the +proved puncture-removal theorem applied to the reciprocal. + +Reference: [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Corollary 2.1.3. + +## Main results + +* `frequently_zero_punctured_of_analyticAt`: A scalar holomorphic function in complex dimension at + least two cannot have an isolated zero. + +## References + +* [P. Jakóbczak and M. Jarnicki, *Lectures on Holomorphic Functions of Several Complex + Variables*][JakobczakJarnicki2021] +-/ + +public section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- A scalar holomorphic function in complex dimension at least two cannot have an isolated zero. +See [Jakóbczak–Jarnicki][JakobczakJarnicki2021] Corollary 2.1.3. Applying Hartogs extension to +the reciprocal would contradict an isolated zero. The scalar target and dimension restriction +are essential: vector-valued maps and functions of one variable can have isolated zeros. -/ +theorem frequently_zero_punctured_of_analyticAt + [FiniteDimensional ℂ E] (hdim : 2 ≤ Module.finrank ℂ E) + {f : E → ℂ} {a : E} (hf : AnalyticAt ℂ f a) (ha : f a = 0) : + ∃ᶠ z in 𝓝[≠] a, f z = 0 := by + let : Nontrivial E := Module.nontrivial_of_finrank_pos (by omega : 0 < Module.finrank ℂ E) + by_contra hn + have hne : ∀ᶠ z in 𝓝[≠] a, f z ≠ 0 := not_frequently.mp hn + have hn' : ∀ᶠ z in 𝓝 a, z ≠ a → f z ≠ 0 := by + simpa only [mem_compl_iff, mem_singleton_iff] using eventually_nhdsWithin_iff.mp hne + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hf.eventually_analyticAt.and hn') + have hfi : AnalyticOnNhd ℂ (fun z => (f z)⁻¹) (ball a r \ {a}) := + fun z hz => ((hball hz.1).1).inv ((hball hz.1).2 hz.2) + obtain ⟨g, hg, he⟩ := exists_analyticOnNhd_extension_diff_singleton hdim isOpen_ball + (mem_ball_self hr) hfi + have heq : (fun z => f z * g z) =ᶠ[𝓝[≠] a] (fun _ => (1 : ℂ)) := by + filter_upwards [nhdsWithin_le_nhds (ball_mem_nhds a hr), eventually_mem_nhdsWithin] with z hz + hza + rw [he ⟨hz, hza⟩] + exact mul_inv_cancel₀ ((hball hz).2 hza) + have hlim := (hf.continuousAt.mul (hg a (mem_ball_self hr)).continuousAt).tendsto.mono_left + (nhdsWithin_le_nhds (s := {a}ᶜ)) + have hval : f a * g a = 1 := tendsto_nhds_unique hlim (Tendsto.congr' heq.symm tendsto_const_nhds) + simp [ha] at hval + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Basic.lean new file mode 100644 index 0000000000..663cbc6a7b --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Basic.lean @@ -0,0 +1,106 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Uniqueness +public import Mathlib.Analysis.Complex.Basic +public import Mathlib.Analysis.Normed.Module.Connected + +/-! +# Identity-principle consequences for zero sets + +The nonvanishing locus of a nonzero analytic function is dense in its connected open domain, +which gives uniqueness of continuous extensions across its zero set. A product of two scalar +analytic functions vanishes near a point only if one factor does. These results support +removability and analytic germs without depending on Hartogs extension or local-ring theory. + +References: [Scheidemann][Scheidemann2005] (2005), Sections 4.1--4.2; +[Korevaar–Wiegerinck][KorevaarWiegerinck2017] (2017), Sections 4.6--4.7. The density and +extension-uniqueness results allow normed vector targets. + +## Main results + +`subset_closure_nonzero_of_analyticOnNhd` is density of the nonvanishing locus. +`eqOn_of_eqOn_nonzero_of_analyticOnNhd` is uniqueness of continuous extensions across a zero +set. `eventuallyEq_zero_or_eventuallyEq_zero_of_mul` is the product rule for vanishing germs. + +## References + +* [J. Korevaar and J. Wiegerinck, *Several Complex Variables*][KorevaarWiegerinck2017] +* [V. Scheidemann, *Introduction to Complex Analysis in Several Variables*][Scheidemann2005] +-/ + +public section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] + +/-- A nonzero analytic function on a connected open set is nonzero arbitrarily near each point of +that set. No completeness or finite-dimensionality assumption is needed. -/ +theorem exists_ne_zero_mem_ball_of_analyticOnNhd {U : Set E} {f : E → F} + (hU : IsOpen U) (hconn : IsPreconnected U) (hf : AnalyticOnNhd ℂ f U) + (hne : ∃ z ∈ U, f z ≠ 0) {x : E} (hx : x ∈ U) {r : ℝ} (hr : 0 < r) : + ∃ y ∈ U, y ∈ ball x r ∧ f y ≠ 0 := by + by_contra! h + have hzero : f =ᶠ[𝓝 x] 0 := by + filter_upwards [hU.mem_nhds hx, ball_mem_nhds x hr] with y hy hyr + exact h y hy hyr + obtain ⟨z, hz, hnz⟩ := hne + exact hnz (hf.eqOn_zero_of_preconnected_of_eventuallyEq_zero hconn hx hzero hz) + +/-- The nonvanishing locus of a nonzero analytic function is dense in its connected open domain. The +closure is taken in the ambient normed space. -/ +theorem subset_closure_nonzero_of_analyticOnNhd {U : Set E} {f : E → F} + (hU : IsOpen U) (hconn : IsPreconnected U) (hf : AnalyticOnNhd ℂ f U) + (hne : ∃ z ∈ U, f z ≠ 0) : U ⊆ closure {z | z ∈ U ∧ f z ≠ 0} := by + intro x hx + rw [Metric.mem_closure_iff] + intro r hr + obtain ⟨y, hy, hyr, hny⟩ := + exists_ne_zero_mem_ball_of_analyticOnNhd hU hconn hf hne hx hr + exact ⟨y, ⟨hy, hny⟩, by simpa [dist_comm] using hyr⟩ + +/-- Continuous extensions across the zero set of a nonzero analytic function are unique on the +domain. Their values outside the domain are unrestricted. -/ +theorem eqOn_of_eqOn_nonzero_of_analyticOnNhd + {G : Type*} [TopologicalSpace G] [T2Space G] + {U : Set E} {f : E → F} {g h : E → G} + (hU : IsOpen U) (hconn : IsPreconnected U) (hf : AnalyticOnNhd ℂ f U) + (hne : ∃ z ∈ U, f z ≠ 0) (hg : ContinuousOn g U) (hh : ContinuousOn h U) + (heq : EqOn g h {z | z ∈ U ∧ f z ≠ 0}) : EqOn g h U := + heq.of_subset_closure hg hh (fun _ hz => hz.1) + (subset_closure_nonzero_of_analyticOnNhd hU hconn hf hne) + +/-- If a product of two analytic functions vanishes near a point, one factor vanishes near that +point. This is the identity principle on a sufficiently small connected ball. -/ +theorem eventuallyEq_zero_or_eventuallyEq_zero_of_mul {𝕜 E : Type*} [RCLike 𝕜] + [NormedAddCommGroup E] [NormedSpace 𝕜 E] + {f g : E → 𝕜} {x : E} (hf : AnalyticAt 𝕜 f x) (hg : AnalyticAt 𝕜 g x) + (hfg : (fun y => f y * g y) =ᶠ[𝓝 x] 0) : + f =ᶠ[𝓝 x] 0 ∨ g =ᶠ[𝓝 x] 0 := by + let : NormedSpace ℝ E := NormedSpace.restrictScalars ℝ 𝕜 E + obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp + (hf.eventually_analyticAt.and (hg.eventually_analyticAt.and hfg)) + by_cases hzero : ∀ y ∈ ball x r, f y = 0 + · exact Or.inl (Filter.mem_of_superset (ball_mem_nhds x hr) hzero) + · push Not at hzero + obtain ⟨y, hy, hfy⟩ := hzero + have hgzero : g =ᶠ[𝓝 y] 0 := by + filter_upwards [isOpen_ball.mem_nhds hy, + (hball hy).1.continuousAt.eventually_ne hfy] with z hz hfz + exact (mul_eq_zero.mp (hball hz).2.2).resolve_left hfz + have hgon : AnalyticOnNhd 𝕜 g (ball x r) := fun z hz => (hball hz).2.1 + exact Or.inr (Filter.mem_of_superset (ball_mem_nhds x hr) + (hgon.eqOn_zero_of_preconnected_of_eventuallyEq_zero isPreconnected_ball hy hgzero)) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Connected.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Connected.lean new file mode 100644 index 0000000000..9ca9f97d42 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Connected.lean @@ -0,0 +1,104 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet + +/-! +# Connectedness of the nonvanishing locus + +Removing a proper scalar holomorphic zero set from a connected open subset of a +finite-dimensional complex space leaves a connected set. Extend the bounded locally constant +separator of a hypothetical separation and apply the identity principle. More generally, the +same holds for relatively closed sets locally contained in proper analytic zero sets, by the +locally bounded Riemann extension theorem. This consequence is kept above removability to +preserve the dependency order. + +## Main results + +`isConnected_nonzero_of_analyticOnNhd` is connectedness of the nonvanishing locus of a nonzero +scalar holomorphic function. `isConnected_sdiff_of_locallyContainedInAnalyticZeroSet` is the +corresponding statement for a relatively closed thin exceptional set. +-/ + +public section + +open Filter Metric Set +open scoped Topology + +namespace SeveralComplexVariables + +/-- A relatively closed set locally contained in proper analytic zero sets cannot disconnect a +connected open domain. No positive-dimension hypothesis is needed. -/ +theorem isConnected_sdiff_of_locallyContainedInAnalyticZeroSet + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U S : Set E} (hc : IsConnected U) + (hUS : IsOpen (U \ S)) (hS : LocallyContainedInAnalyticZeroSet U S) : + IsConnected (U \ S) := by + classical + let V := U \ S + have hVo : IsOpen V := hUS + refine ⟨?_, ?_⟩ + · by_contra h + have he : U \ S = ∅ := Set.not_nonempty_iff_eq_empty.mp h + obtain ⟨a, ha⟩ := hc.nonempty + have := hS.subset_closure ha + simp [he] at this + change IsPreconnected V + intro s t hs ht hcover hVs hVt + by_contra hmeet + have hdis : ∀ z ∈ V, z ∈ s → z ∈ t → False := by + intro z hz hzs hzt + exact hmeet ⟨z, hz, hzs, hzt⟩ + let f : E → ℂ := fun z => if z ∈ s then 1 else 0 + have hfs : ∀ z ∈ s, f =ᶠ[𝓝 z] (fun _ => (1 : ℂ)) := by + intro z hz + filter_upwards [hs.mem_nhds hz] with y hy + simp [f, hy] + have hft : ∀ z ∈ V ∩ t, f =ᶠ[𝓝 z] (fun _ => (0 : ℂ)) := by + intro z hz + filter_upwards [(hVo.inter ht).mem_nhds hz] with y hy + simp [f, show y ∉ s from fun hys => hdis y hy.1 hys hy.2] + have hf : AnalyticOnNhd ℂ f V := by + intro z hz + rcases hcover hz with hzs | hzt + · exact (analyticAt_congr (hfs z hzs)).mpr analyticAt_const + · exact (analyticAt_congr (hft z ⟨hz, hzt⟩)).mpr analyticAt_const + have hb : ∀ a ∈ U, ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, + ∀ z ∈ ball a r ∩ V, ‖f z‖ ≤ C := by + intro a _ + refine ⟨1, zero_lt_one, 1, fun z _ => ?_⟩ + dsimp [f] + split_ifs <;> simp + obtain ⟨F, hF, hEq⟩ := exists_analyticOnNhd_extension_across_locallyContainedZeroSet hUS hS hf hb + obtain ⟨a, ha, has⟩ := hVs + have hFone : F =ᶠ[𝓝 a] (fun _ => (1 : ℂ)) := by + filter_upwards [hVo.mem_nhds ha, hfs a has] with z hz hfz + exact (hEq hz).trans hfz + have hconst := hF.eqOn_of_preconnected_of_eventuallyEq analyticOnNhd_const hc.isPreconnected + ha.1 hFone + obtain ⟨b, hbV, hbt⟩ := hVt + have hbzero : F b = 0 := (hEq hbV).trans ((hft b ⟨hbV, hbt⟩).self_of_nhds) + have hbone : F b = 1 := hconst hbV.1 + exact zero_ne_one (hbzero.symm.trans hbone) + +/-- A proper holomorphic zero set cannot disconnect a connected open domain. No positive-dimension +hypothesis is needed. -/ +theorem isConnected_nonzero_of_analyticOnNhd + {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) (hc : IsPreconnected U) + {g : E → ℂ} (hg : AnalyticOnNhd ℂ g U) (hne : ∃ z ∈ U, g z ≠ 0) : + IsConnected (U \ g ⁻¹' {0}) := by + obtain ⟨z, hz, hgz⟩ := hne + apply isConnected_sdiff_of_locallyContainedInAnalyticZeroSet ⟨⟨z, hz⟩, hc⟩ + (hg.continuousOn.isOpen_inter_preimage hU isClosed_singleton.isOpen_compl) + apply locallyContainedInAnalyticZeroSet_zeroSet hU hg + intro a ha hzero + exact hgz (hg.eqOn_zero_of_preconnected_of_eventuallyEq_zero hc ha hzero hz) + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Local.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Local.lean new file mode 100644 index 0000000000..c7c5fa6dd0 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Local.lean @@ -0,0 +1,132 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Analytic.Uniqueness +public import Mathlib.Analysis.Calculus.FDeriv.Analytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence + +/-! +# Local structure of scalar zero sets + +Nontrivial analytic germs have a nonzero derivative of finite order. Minimizing this order along +a zero set supplies an analytic function with nonzero derivative that vanishes on that set. +Persistence of zeros supplies the converse inclusion after straightening this auxiliary +function. + +## Main results + +`AnalyticAt.eventuallyEq_zero_of_iteratedFDeriv_eq_zero` is vanishing of a germ whose iterated +derivatives all vanish. `exists_analytic_zeroSet_superset_fderiv_ne_zero` produces an analytic +function with nonzero derivative vanishing on a given zero set. +`eventually_zeroSet_eq_linear_zeroSet` is the local graph description after straightening. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + +/-- An analytic germ whose iterated derivatives all vanish is the zero germ. -/ +theorem _root_.AnalyticAt.eventuallyEq_zero_of_iteratedFDeriv_eq_zero {f : E → ℂ} {a : E} + (hf : AnalyticAt ℂ f a) (hzero : ∀ n, iteratedFDeriv ℂ n f a = 0) : + f =ᶠ[𝓝 a] 0 := by + obtain ⟨p, r, hp⟩ := hf + filter_upwards [eball_mem_nhds a hp.r_pos] with y hy + have hs := hp.hasSum_iteratedFDeriv (y := y - a) (by + simpa only [mem_eball, edist_zero_right, edist_eq_enorm_sub, sub_zero] using hy) + simpa [hzero] using hs.tsum_eq.symm + +/-- A nonempty proper scalar zero set is contained in the zero set of an analytic function whose +derivative is nonzero at some point of the original zero set. Choose a derivative of minimal +order that does not vanish everywhere on the set. -/ +theorem exists_analytic_zeroSet_superset_fderiv_ne_zero [FiniteDimensional ℂ E] + {U : Set E} (hU : IsOpen U) (hc : IsPreconnected U) {f : E → ℂ} + (hf : AnalyticOnNhd ℂ f U) (hne : ∃ b ∈ U, f b ≠ 0) (hz : ∃ a ∈ U, f a = 0) : + ∃ (a : E) (g : E → ℂ), a ∈ U ∧ f a = 0 ∧ AnalyticOnNhd ℂ g U ∧ + (∀ z ∈ U, f z = 0 → g z = 0) ∧ fderiv ℂ g a ≠ 0 := by + classical + have hex : ∃ n : ℕ, ∃ a ∈ U, f a = 0 ∧ iteratedFDeriv ℂ n f a ≠ 0 := by + by_contra! h + obtain ⟨a, ha, hfa⟩ := hz + have he := (hf a ha).eventuallyEq_zero_of_iteratedFDeriv_eq_zero (fun n => h n a ha hfa) + obtain ⟨b, hb, hfb⟩ := hne + exact hfb (hf.eqOn_zero_of_preconnected_of_eventuallyEq_zero hc ha he hb) + obtain ⟨a, ha, hfa, hda⟩ := Nat.find_spec hex + have hmin : ∀ n < Nat.find hex, ∀ z ∈ U, f z = 0 → iteratedFDeriv ℂ n f z = 0 := by + intro n hn z hz hfz + by_contra hd + exact Nat.find_min hex hn ⟨z, hz, hfz, hd⟩ + generalize hn : Nat.find hex = n at hda hmin + cases n with + | zero => + exact (hda (by ext v; simpa only [iteratedFDeriv_zero_apply, + zero_apply] using hfa)).elim + | succ n => + obtain ⟨v, hv⟩ : ∃ v, iteratedFDeriv ℂ (n + 1) f a v ≠ 0 := by + contrapose! hda + ext v + exact hda v + let g : E → ℂ := fun z => iteratedFDeriv ℂ n f z (Fin.tail v) + have hg : AnalyticOnNhd ℂ g U := + ((hf.iteratedFDeriv n).differentiableOn.continuousMultilinear_apply_const + (Fin.tail v)).analyticOnNhd_of_finiteDimensional hU + refine ⟨a, g, ha, hfa, hg, ?_, ?_⟩ + · intro z hz hfz + simp [g, hmin n (Nat.lt_succ_self n) z hz hfz] + · intro hd + apply hv + rw [((hf.iteratedFDeriv n) a ha).differentiableAt.iteratedFDeriv_succ_apply_left'] + change fderiv ℂ g a (v 0) = 0 + simp [hd] + +/-- If the zeros of an analytic function lie in a hyperplane and include a point of that hyperplane, +then the two zero sets agree near that point. -/ +theorem eventually_zeroSet_eq_linear_zeroSet {V : Set E} (hV : IsOpen V) + {f : E → ℂ} (hf : AnalyticOnNhd ℂ f V) {L : E →L[ℂ] ℂ} + (hL : Function.Surjective L) {a : E} (ha : a ∈ V) (hfa : f a = 0) (hLa : L a = 0) + (hsub : ∀ z ∈ V, f z = 0 → L z = 0) : + ∀ᶠ z in 𝓝 a, f z = 0 ↔ L z = 0 := by + obtain ⟨v, hv⟩ := hL 1 + let S : E × ℂ → E := fun p => p.1 + p.2 • v + have hS : Continuous S := continuous_fst.add (continuous_snd.smul continuous_const) + let W := S ⁻¹' V + have hW : IsOpen W := hV.preimage hS + have hline : Continuous (fun t : ℂ => a + t • v) := + continuous_const.add (continuous_id.smul continuous_const) + have h0 : (0 : ℂ) ∈ (fun t : ℂ => a + t • v) ⁻¹' V := by simpa using ha + obtain ⟨ε, hε, hεV⟩ := Metric.mem_nhds_iff.mp ((hV.preimage hline).mem_nhds h0) + let r := ε / 2 + have hr : 0 < r := half_pos hε + have hdisc : ∀ t ∈ closedBall (0 : ℂ) r, (a, t) ∈ W := by + intro t ht + exact hεV ((closedBall_subset_ball (half_lt_self hε)) ht) + have hboundary : ∀ t ∈ sphere (0 : ℂ) r, (f ∘ S) (a, t) ≠ 0 := by + intro t ht hft + have ht0 : t = 0 := by + simpa [S, hLa, hv] using hsub (S (a, t)) (hdisc t (sphere_subset_closedBall ht)) hft + subst t + have : r = 0 := by simpa using ht.symm + exact hr.ne' this + have hroots := eventually_exists_zero_in_fiber hW + (hf.continuousOn.comp hS.continuousOn (mapsTo_preimage _ _)) + (fun p hp => ((hf (S p) hp).differentiableAt.comp p.2 + ((differentiableAt_const p.1).add (differentiableAt_id.smul_const v)))) + hr hdisc (by simpa [S] using hfa) hboundary + filter_upwards [hV.eventually_mem ha, hroots] with z hz hroot + refine ⟨hsub z hz, fun hLz => ?_⟩ + obtain ⟨t, _, hzt, hft⟩ := hroot + have ht0 : t = 0 := by simpa [S, hLz, hv] using hsub (S (z, t)) hzt hft + simpa [S, ht0] using hft + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Persistence.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Persistence.lean new file mode 100644 index 0000000000..b1d1fb0cfe --- /dev/null +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/ZeroSets/Persistence.lean @@ -0,0 +1,98 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +module + +public import Mathlib.Analysis.Complex.AbsMax +public import Mathlib.Topology.Order.Compact + +/-! +# Persistence of zeros in holomorphic families + +A zero inside a disc persists under small continuous changes of a holomorphic function, provided +the original function has no zeros on the boundary. The proof uses the maximum modulus principle +for the reciprocal of a hypothetically nonvanishing perturbation; no root counting is required. + +## Main results + +`exists_zero_of_norm_lt_boundary` persists a zero inside a disc under a small perturbation with +no boundary zeros. `eventually_exists_zero_in_fiber` is persistence of zeros in a holomorphic +family. +-/ + +public noncomputable section + +open Set Filter Metric +open scoped Topology + +namespace SeveralComplexVariables + +/-- A holomorphic function whose value at the center is smaller in norm than all its boundary values +has a zero in the disc. -/ +theorem exists_zero_of_norm_lt_boundary {f : ℂ → ℂ} {r : ℝ} (hr : 0 < r) + (hf : DifferentiableOn ℂ f (closedBall 0 r)) + (hlt : ∀ z ∈ sphere 0 r, ‖f 0‖ < ‖f z‖) : + ∃ z ∈ ball 0 r, f z = 0 := by + by_contra! hn + have hne : ∀ z ∈ closedBall (0 : ℂ) r, f z ≠ 0 := by + intro z hz + rcases lt_or_eq_of_le (mem_closedBall.mp hz) with hz | hz + · exact hn z hz + · exact norm_pos_iff.mp ((norm_nonneg _).trans_lt (hlt z hz)) + have hi : DiffContOnCl ℂ (fun z => (f z)⁻¹) (ball 0 r) := by + refine ⟨(hf.inv hne).mono ball_subset_closedBall, ?_⟩ + rw [closure_ball (0 : ℂ) hr.ne'] + exact (hf.continuousOn.inv₀ hne) + obtain ⟨z, hz, hmax⟩ := Complex.exists_mem_frontier_isMaxOn_norm + isBounded_ball (nonempty_ball.mpr hr) hi + rw [frontier_ball (0 : ℂ) hr.ne'] at hz + have hle := hmax (subset_closure (mem_ball_self hr)) + have hpos : 0 < ‖f 0‖ := norm_pos_iff.mpr (hne 0 (mem_closedBall_self hr.le)) + have hstrict := (inv_lt_inv₀ ((hpos.le).trans_lt (hlt z hz)) hpos).2 (hlt z hz) + exact (not_le_of_gt hstrict) (by simpa [Function.comp_def, norm_inv] using hle) + +/-- A zero of a continuously varying holomorphic function persists in nearby fibers if a closed disc +in the initial fiber has no boundary zeros. The parameter space only needs a topology. -/ +theorem eventually_exists_zero_in_fiber {X : Type*} [TopologicalSpace X] + {W : Set (X × ℂ)} (hW : IsOpen W) {f : X × ℂ → ℂ} + (hf : ContinuousOn f W) + (hd : ∀ p ∈ W, DifferentiableAt ℂ (fun z => f (p.1, z)) p.2) + {a : X} {r : ℝ} (hr : 0 < r) + (hdisc : ∀ z ∈ closedBall (0 : ℂ) r, (a, z) ∈ W) + (hzero : f (a, 0) = 0) (hboundary : ∀ z ∈ sphere (0 : ℂ) r, f (a, z) ≠ 0) : + ∀ᶠ x in 𝓝 a, ∃ z ∈ ball (0 : ℂ) r, (x, z) ∈ W ∧ f (x, z) = 0 := by + have hcont (z : ℂ) (hz : z ∈ closedBall (0 : ℂ) r) : ContinuousAt f (a, z) := + hf.continuousAt (hW.mem_nhds (hdisc z hz)) + have hscont : ContinuousOn (fun z => ‖f (a, z)‖) (sphere (0 : ℂ) r) := by + intro z hz + exact ((hcont z (sphere_subset_closedBall hz)).comp + (continuousAt_const.prodMk continuousAt_id)).norm.continuousWithinAt + obtain ⟨b, hb, hmin⟩ := (isCompact_sphere (0 : ℂ) r).exists_isMinOn + ⟨(r : ℂ), by simp [Complex.norm_real, abs_of_pos hr]⟩ hscont + let c := ‖f (a, b)‖ / 2 + have hc : 0 < c := half_pos (norm_pos_iff.mpr (hboundary b hb)) + have hsmall : ∀ᶠ x in 𝓝 a, ‖f (x, 0)‖ < c := by + have hs : ContinuousAt (fun x : X => (x, (0 : ℂ))) a := + continuousAt_id.prodMk continuousAt_const + apply ((hcont 0 (mem_closedBall_self hr.le)).comp + (f := fun x : X => (x, (0 : ℂ))) hs).norm.eventually_lt continuousAt_const + simpa [hzero] using hc + have hlarge : ∀ᶠ x in 𝓝 a, ∀ z ∈ sphere (0 : ℂ) r, c < ‖f (x, z)‖ := by + apply (isCompact_sphere (0 : ℂ) r).eventually_forall_of_forall_eventually + intro z hz + apply continuousAt_const.eventually_lt (hcont z (sphere_subset_closedBall hz)).norm + exact (half_lt_self (norm_pos_iff.mpr (hboundary b hb))).trans_le (hmin hz) + have hdomain : ∀ᶠ x in 𝓝 a, ∀ z ∈ closedBall (0 : ℂ) r, (x, z) ∈ W := by + apply (isCompact_closedBall (0 : ℂ) r).eventually_forall_of_forall_eventually + exact fun z hz => hW.eventually_mem (hdisc z hz) + filter_upwards [hsmall, hlarge, hdomain] with x hxsmall hxlarge hxdomain + obtain ⟨z, hz, hzero⟩ := exists_zero_of_norm_lt_boundary (f := fun z => f (x, z)) hr + (fun z hz => (hd (x, z) (hxdomain z hz)).differentiableWithinAt) + (fun z hz => hxsmall.trans (hxlarge z hz)) + exact ⟨z, hz, hxdomain z (ball_subset_closedBall hz), hzero⟩ + +end SeveralComplexVariables + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/Solution.lean b/LeanPool/SeveralComplexVariables/Solution.lean new file mode 100644 index 0000000000..e9dc595892 --- /dev/null +++ b/LeanPool/SeveralComplexVariables/Solution.lean @@ -0,0 +1,943 @@ +/- +Copyright (c) 2026 Bastiaan J Braams. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Bastiaan J Braams +-/ +import Mathlib +import LeanPool.SeveralComplexVariables.SeveralComplexVariables + +/-! +# Several complex variables: principal statements (`Solution.lean`) + +This file states the principal results of the `SeveralComplexVariables` library in terms of Mathlib +alone. It follows the project's catalogue of main theorems, `SCVMainTheorems.md`: the number in each +docstring is the item of that catalogue, and the sections A–K are its sections. The subject is +classical function theory on open subsets of finite-dimensional complex normed spaces `E`, in +particular of `ℂ^ι = ι → ℂ` for a finite index type `ι`, with values in a complex Banach space `F`. + +## Conventions + +* *Holomorphic* is `DifferentiableOn ℂ f U` and *analytic* is `AnalyticOnNhd ℂ f U`. On open subsets + of `E` the two agree (item 3), and the statements use whichever the library proves directly. +* `ι → ℂ` carries the supremum norm, so that `Metric.ball` is a polydisc with equal radii; a + polydisc with separate radii is `Set.pi univ fun i => Metric.ball (c i) (r i)`. Dimension zero and + empty index types are included unless a hypothesis excludes them. +* Domains are not assumed connected or nonempty; such hypotheses are stated where they are needed. +* Hulls are defined through all real upper bounds rather than suprema. Subharmonic and + plurisubharmonic functions are real valued, so the value `-∞` is not admitted. +* The definitions below restate those of the library and are kept few. Where a notion is used + once, it is written out in the statement instead. + +## Scope + +Of the 65 items of the catalogue, all are represented except items 42 and 43 (factors of +distinguished polynomials, and the comparison of polynomials over the germ ring with germs), which +are algebraic steps towards items 44 and 45. An item with several assertions is represented by its +principal assertion. The sources are the texts of Boas, Fritzsche–Grauert, Hörmander, +Jakóbczak–Jarnicki, Korevaar–Wiegerinck, Range, Scheidemann, Shabat and Suwa listed in +`formalization.yaml`; none of the results is new. The proofs use only the axioms `propext`, +`Quot.sound` and `Classical.choice`. + +## Related formalizations + +The development builds on Mathlib. Two results were formalized independently, and earlier, by +Bochao Kong in the Palomar registry: the analytic Weierstrass preparation theorem (item 41; entry +PALOMAR-2026-08-29-000010) and Rückert's basis theorem, that the ring of analytic germs is +Noetherian (item 44; entry PALOMAR-2026-08-30-000001, which also contains the local analytic +Nullstellensatz, not treated here). Neither is used here. Mathlib's Weierstrass preparation +theorem concerns formal power series over complete local rings and is likewise not used. +-/ + + +open Complex Filter Function MeasureTheory Metric Set +open scoped Real Topology + +namespace SCV + +variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] [FiniteDimensional ℂ E] + [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] + {ι : Type*} [Fintype ι] + +/-! ## A. Local analysis and differential calculus -/ + +/-- The derivative in the coordinate `i`, the other coordinates being fixed. -/ +noncomputable def partialDeriv [DecidableEq ι] (i : ι) (f : (ι → ℂ) → F) (z : ι → ℂ) : F := + deriv (fun w => f (update z i w)) (z i) + +/-- The iterated coordinate derivative along a list of coordinates; the leftmost acts last. -/ +noncomputable def iteratedPartialDeriv [DecidableEq ι] : List ι → ((ι → ℂ) → F) → (ι → ℂ) → F + | [], f => f + | i :: is, f => partialDeriv i (iteratedPartialDeriv is f) + +-- BEGIN SOLUTION ONLY +omit [CompleteSpace F] [Fintype ι] in +/-- The submission and library definitions of iterated coordinate derivatives agree. -/ +private theorem iteratedPartialDeriv_eq [DecidableEq ι] (is : List ι) (f : (ι → ℂ) → F) : + iteratedPartialDeriv is f = SeveralComplexVariables.iteratedPartialDeriv is f := by + induction is with + | nil => rfl + | cons i is ih => + simp only [iteratedPartialDeriv, SeveralComplexVariables.iteratedPartialDeriv, ih]; rfl +-- END SOLUTION ONLY + +/-- **1. Cauchy's integral formula on a polydisc**, for a function continuous on the closed polydisc +and analytic in each variable separately. -/ +theorem cauchy_formula_polydisc {n : ℕ} {f : (Fin n → ℂ) → F} {c w : Fin n → ℂ} {R : Fin n → ℝ} + (hR : ∀ i, 0 < R i) (hw : ∀ i, ‖w i - c i‖ < R i) + (hfc : ContinuousOn f (Set.pi univ fun i => closedBall (c i) (R i))) + (hfa : ∀ z ∈ Set.pi univ fun i => closedBall (c i) (R i), ∀ i, + AnalyticAt ℂ (fun x => f (update z i x)) (z i)) : + ((2 * π * I : ℂ) ^ n)⁻¹ • torusIntegral (fun z => (∏ i, (z i - w i)⁻¹) • f z) c R = f w := by + exact SeveralComplexVariables.two_pi_I_pow_inv_smul_torusIntegral_prod_sub_inv_smul hR hw hfc hfa + +/-- **2. Osgood's lemma**: a continuous, separately analytic function is jointly analytic. -/ +theorem osgood [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} (hU : IsOpen U) + (hfc : ContinuousOn f U) + (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + exact SeveralComplexVariables.analyticOnNhd_pi_of_analyticOnNhd_update hU hfc hf + +/-- **3. Holomorphic is analytic** on open subsets of a finite-dimensional space, for Banach-valued +maps. -/ +theorem differentiableOn_iff_analyticOnNhd {U : Set E} {f : E → F} (hU : IsOpen U) : + DifferentiableOn ℂ f U ↔ AnalyticOnNhd ℂ f U := by + exact differentiableOn_iff_analyticOnNhd_of_finiteDimensional hU + +/-- **4. Cauchy–Riemann equations**: holomorphy is real differentiability together with the +coordinate Cauchy–Riemann equations. -/ +theorem analyticOnNhd_iff_cauchyRiemann [DecidableEq ι] {U : Set (ι → ℂ)} (hU : IsOpen U) + {f : (ι → ℂ) → F} : + AnalyticOnNhd ℂ f U ↔ (∀ z ∈ U, DifferentiableAt ℝ f z) ∧ + ∀ z ∈ U, ∀ i, fderiv ℝ f z (Pi.single i I) = I • fderiv ℝ f z (Pi.single i 1) := by + exact SeveralComplexVariables.analyticOnNhd_iff_differentiableAt_real_cauchyRiemann hU + +/-- **6. Identity theorem**: holomorphic maps on a connected open set that agree on a nonempty open +subset agree everywhere. -/ +theorem identity_theorem {U V : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) {f g : E → F} + (hf : DifferentiableOn ℂ f U) (hg : DifferentiableOn ℂ g U) (hV : IsOpen V) (hne : V.Nonempty) + (hVU : V ⊆ U) (heq : EqOn f g V) : EqOn f g U := by + exact DifferentiableOn.eqOn_of_preconnected_of_eqOn hU hconn hf hg hV hne hVU heq + +/-- **7. Maximum modulus principle**, for maps into a strictly convex Banach space, in particular +for scalar functions. -/ +theorem maximum_modulus [StrictConvexSpace ℝ F] {U : Set E} (hU : IsOpen U) + (hconn : IsPreconnected U) {f : E → F} (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) + (hmax : IsLocalMax (norm ∘ f) a) : EqOn f (const E (f a)) U := by + exact SeveralComplexVariables.eqOn_const_of_holomorphic_of_isLocalMax_norm hU hconn hf ha hmax + +/-- **9. Cauchy–Pompeiu identity** for a compactly supported `C¹` function, with +`∂φ/∂w̄ = (∂φ/∂x + i ∂φ/∂y) / 2` written through the real derivative. -/ +theorem cauchy_pompeiu {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) (hsupp : HasCompactSupport φ) : + ∫ w, w⁻¹ • ((2 : ℂ)⁻¹ • (fderiv ℝ φ w 1 + I • fderiv ℝ φ w I)) = -((π : ℂ) • φ 0) := by + have h := SeveralComplexVariables.integral_inv_smul_dbarAlong_fderiv hφ hsupp + simpa [SeveralComplexVariables.dbarAlong] using h + +/-- The Taylor series at `c` of a function of `n` complex variables: the coefficient of `zᵐ` is +`∂ᵐ f (c) / m!`, the mixed derivative being taken coordinate by coordinate. -/ +noncomputable def taylorSeries {n : ℕ} (f : (Fin n → ℂ) → F) (c : Fin n → ℂ) : + MvPowerSeries (Fin n) F := + fun m => (∏ i, (m i).factorial : ℂ)⁻¹ • + iteratedPartialDeriv (List.ofFn fun i => List.replicate (m i) i).flatten f c + +-- BEGIN SOLUTION ONLY +omit [CompleteSpace F] in +/-- The submission Taylor series equals the library holomorphic Taylor series. -/ +private theorem taylorSeries_eq {n : ℕ} (f : (Fin n → ℂ) → F) (c : Fin n → ℂ) : + taylorSeries f c = SeveralComplexVariables.holomorphicTaylorSeries f c := by + funext m + simp only [taylorSeries, SeveralComplexVariables.holomorphicTaylorSeries, + SeveralComplexVariables.multiIndexDeriv, SeveralComplexVariables.multiIndexList, + iteratedPartialDeriv_eq] +-- END SOLUTION ONLY + +/-- **5. Cauchy estimates** for the Taylor coefficients of a function holomorphic near a closed +polydisc and bounded by `M` on it. -/ +theorem cauchy_estimates {n : ℕ} {U : Set (Fin n → ℂ)} (hU : IsOpen U) {f : (Fin n → ℂ) → F} + (hf : DifferentiableOn ℂ f U) {c : Fin n → ℂ} {R : Fin n → ℝ} (hR : ∀ i, 0 < R i) {M : ℝ} + (hsub : (Set.pi univ fun i => closedBall (c i) (R i)) ⊆ U) + (hM : ∀ z ∈ Set.pi univ fun i => closedBall (c i) (R i), ‖f z‖ ≤ M) (m : Fin n →₀ ℕ) : + ‖taylorSeries f c m‖ ≤ M * ∏ i, (R i)⁻¹ ^ m i := by + have hfa := hf.analyticOnNhd_of_finiteDimensional hU + have h := SeveralComplexVariables.norm_multiIndexDeriv_le (f := f) (c := c) hR + (hfa.continuousOn.mono hsub) (fun z hz i => hfa.analyticAt_update (hsub hz) i) hM m + have hpos : (0 : ℝ) < ∏ i, ((m i).factorial : ℝ) := + Finset.prod_pos fun i _ => Nat.cast_pos.mpr (Nat.factorial_pos _) + have hn : ‖(∏ i, (m i).factorial : ℂ)‖ = ∏ i, ((m i).factorial : ℝ) := by + simp [norm_prod] + rw [taylorSeries_eq, SeveralComplexVariables.holomorphicTaylorSeries, norm_smul, norm_inv, hn, + inv_mul_le_iff₀ hpos] + exact h + +/-- **8. Holomorphic dependence of integrals on parameters**, under a locally integrable bound. -/ +theorem analyticOnNhd_integral {α : Type*} [MeasurableSpace α] {μ : Measure α} {U : Set E} + {G : E → α → F} (hU : IsOpen U) (hmeas : ∀ x ∈ U, AEStronglyMeasurable (G x) μ) + (hderivmeas : ∀ x ∈ U, AEStronglyMeasurable (fun a => fderiv ℂ (G · a) x) μ) + (hhol : ∀ᵐ a ∂μ, AnalyticOnNhd ℂ (G · a) U) + (hdom : ∀ x ∈ U, ∃ (s : Set E) (bound : α → ℝ), s ∈ 𝓝 x ∧ Integrable bound μ ∧ + ∀ᵐ a ∂μ, ∀ y ∈ s, ‖G y a‖ ≤ bound a) : + AnalyticOnNhd ℂ (fun x => ∫ a, G x a ∂μ) U := by + exact analyticOnNhd_integral_of_locally_dominated hU hmeas hderivmeas hhol hdom + +/-! ## B. Convergence and spaces of holomorphic functions -/ + +/-- **10. Weierstrass convergence theorem**: a locally uniform limit of holomorphic maps is +holomorphic, and the derivatives converge locally uniformly. -/ +theorem weierstrass_convergence {U : Set E} (hU : IsOpen U) {f : ℕ → E → F} {g : E → F} + (hf : ∀ n, DifferentiableOn ℂ (f n) U) (hlim : TendstoLocallyUniformlyOn f g atTop U) : + DifferentiableOn ℂ g U ∧ + TendstoLocallyUniformlyOn (fun n => fderiv ℂ (f n)) (fderiv ℂ g) atTop U := by + have hfa : ∀ᶠ n in atTop, AnalyticOnNhd ℂ (f n) U := + .of_forall fun n => (hf n).analyticOnNhd_of_finiteDimensional hU + exact ⟨(hlim.analyticOnNhd_of_finiteDimensional hfa hU).differentiableOn, + hlim.fderiv_of_finiteDimensional hfa hU⟩ + +/-- The continuous maps on an open set `U` that are restrictions of holomorphic maps. -/ +def holomorphicMaps (U : TopologicalSpace.Opens E) (F : Type*) [NormedAddCommGroup F] + [NormedSpace ℂ F] : Set C(U, F) := + {f | ∃ g : E → F, DifferentiableOn ℂ g U ∧ ∀ z : U, g z = f z} + +/-- **11. Holomorphic function spaces**: the holomorphic maps form a closed subset of `C(U, F)` in +the compact-open topology. -/ +theorem isClosed_holomorphicMaps (U : TopologicalSpace.Opens E) : + IsClosed (holomorphicMaps U F) := by + have h : holomorphicMaps U F = + (SeveralComplexVariables.holomorphicSubmodule (F := F) U : Set C(U, F)) := by + ext f + constructor + · rintro ⟨g, hg, hgf⟩ + refine ((hg.analyticOnNhd_of_finiteDimensional U.isOpen).congr U.isOpen ?_ : + AnalyticOnNhd ℂ (SeveralComplexVariables.openExtension U f) U) + intro z hz + rw [SeveralComplexVariables.openExtension_apply U f hz] + exact hgf ⟨z, hz⟩ + · intro hf + exact ⟨_, (show AnalyticOnNhd ℂ (SeveralComplexVariables.openExtension U f) U from + hf).differentiableOn, fun z => SeveralComplexVariables.openExtension_coe U f z⟩ + rw [h] + exact SeveralComplexVariables.isClosed_holomorphicSubmodule U + +/-- **12. Montel's theorem**: a uniformly bounded sequence of holomorphic maps with values in a +finite-dimensional space has a locally uniformly convergent subsequence with holomorphic limit. -/ +theorem montel [FiniteDimensional ℂ F] {U : Set E} (hU : IsOpen U) {f : ℕ → E → F} + (hf : ∀ n, DifferentiableOn ℂ (f n) U) {M : ℝ} (hM : ∀ n, ∀ z ∈ U, ‖f n z‖ ≤ M) : + ∃ (g : E → F) (φ : ℕ → ℕ), StrictMono φ ∧ DifferentiableOn ℂ g U ∧ + TendstoLocallyUniformlyOn (fun n => f (φ n)) g atTop U := by + obtain ⟨g, φ, hφ, hg, hlim⟩ := + SeveralComplexVariables.exists_subseq_tendstoLocallyUniformlyOn_of_uniform_bound hU + (fun n => (hf n).analyticOnNhd_of_finiteDimensional hU) (fun n z hz => hM n z hz) + exact ⟨g, φ, hφ, hg.differentiableOn, hlim⟩ + +/-- **13. Vitali's theorem**: a locally bounded sequence of holomorphic maps on a connected open set +that converges pointwise on a nonempty open subset converges locally uniformly. -/ +theorem vitali [FiniteDimensional ℂ F] {D V : Set E} (hD : IsOpen D) (hconn : IsPreconnected D) + {f : ℕ → E → F} (hf : ∀ n, DifferentiableOn ℂ (f n) D) + (hb : ∀ K ⊆ D, IsCompact K → ∃ M : ℝ, ∀ n, ∀ z ∈ K, ‖f n z‖ ≤ M) (hV : IsOpen V) + (hne : V.Nonempty) (hVD : V ⊆ D) + (hp : ∀ z ∈ V, ∃ y : F, Tendsto (fun n => f n z) atTop (𝓝 y)) : + ∃ g : E → F, DifferentiableOn ℂ g D ∧ TendstoLocallyUniformlyOn f g atTop D := by + exact SeveralComplexVariables.exists_tendstoLocallyUniformlyOn_of_forall_exists_tendsto hD hconn + hf hb hV hne hVD hp + +/-- **14. Holomorphic `Lᵖ` spaces**: on compact subsets, a holomorphic representative of an `Lᵖ` +class is bounded by a constant times the `Lᵖ` norm, for `1 ≤ p ≤ ∞`. -/ +theorem holomorphic_Lp_bound (U : TopologicalSpace.Opens (ι → ℂ)) (p : ENNReal) [Fact (1 ≤ p)] + {K : Set (ι → ℂ)} (hKU : K ⊆ U) (hK : IsCompact K) : + ∃ C : ℝ, 0 < C ∧ ∀ (u : Lp F p (volume.restrict (U : Set (ι → ℂ)))) (f : (ι → ℂ) → F), + DifferentiableOn ℂ f U → f =ᵐ[volume.restrict (U : Set (ι → ℂ))] u → + ∀ z ∈ K, ‖f z‖ ≤ C * ‖u‖ := by + exact SeveralComplexVariables.exists_norm_le_mul_Lp_norm U p hKU hK + +/-! ## C. Local holomorphic mappings -/ + +/-- **15. Holomorphic inverse mapping theorem**: a holomorphic map with invertible derivative at `a` +is near `a` a homeomorphism between open sets that is holomorphic in both directions. -/ +theorem inverse_mapping {G : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + [FiniteDimensional ℂ G] {U : Set E} (hU : IsOpen U) {f : E → G} + (hf : DifferentiableOn ℂ f U) {a : E} (ha : a ∈ U) (hinv : (fderiv ℂ f a).IsInvertible) : + ∃ e : OpenPartialHomeomorph E G, DifferentiableOn ℂ e e.source ∧ + DifferentiableOn ℂ e.symm e.target ∧ a ∈ e.source ∧ e.source ⊆ U ∧ (e : E → G) = f ∧ + fderiv ℂ e.symm (f a) = (fderiv ℂ f a).inverse := by + obtain ⟨e, he, hae, heU, hef⟩ := + SeveralComplexVariables.exists_biholomorphic_of_isInvertible_fderiv hU hf ha hinv + refine ⟨e, he.1, he.2, hae, heU, hef, ?_⟩ + rw [← hef] + exact he.fderiv_symm hae + +/-- **16. Holomorphic implicit mapping theorem**, with the derivative of the implicit map. -/ +theorem implicit_mapping {P Q R : Type*} [NormedAddCommGroup P] [NormedSpace ℂ P] + [NormedAddCommGroup Q] [NormedSpace ℂ Q] [NormedAddCommGroup R] [NormedSpace ℂ R] + [FiniteDimensional ℂ P] [FiniteDimensional ℂ Q] [CompleteSpace R] {D : Set (P × Q)} + (hD : IsOpen D) {f : P × Q → R} (hf : DifferentiableOn ℂ f D) {a : P} {b : Q} + (hab : (a, b) ∈ D) + (hi : ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).IsInvertible) : + ∃ (U : Set P) (V : Set Q) (g : P → Q), IsOpen U ∧ a ∈ U ∧ IsOpen V ∧ b ∈ V ∧ U ×ˢ V ⊆ D ∧ + DifferentiableOn ℂ g U ∧ MapsTo g U V ∧ g a = b ∧ + HasFDerivAt g (-((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inr ℂ P Q)).inverse |>.comp + ((fderiv ℂ f (a, b)).comp (ContinuousLinearMap.inl ℂ P Q))) a ∧ + ∀ x ∈ U, ∀ y ∈ V, f (x, y) = f (a, b) ↔ y = g x := by + exact SeveralComplexVariables.exists_holomorphic_implicit_mapping hD hf hab hi + +/-! ## D. Reinhardt geometry, power series, and continuation -/ + +/-- A set is Reinhardt if it is invariant under independent rotations of the coordinates. -/ +def IsReinhardt (U : Set (ι → ℂ)) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃w⦄, (∀ i, ‖w i‖ = ‖z i‖) → w ∈ U + +/-- A set is complete Reinhardt if it is closed under decreasing the coordinate moduli. -/ +def IsCompleteReinhardt (U : Set (ι → ℂ)) : Prop := + ∀ ⦃z⦄, z ∈ U → ∀ ⦃w⦄, (∀ i, ‖w i‖ ≤ ‖z i‖) → w ∈ U + +/-- Logarithmic convexity: the image of the points without zero coordinates under +`z ↦ (log |z₁|, …, log |zₙ|)` is convex. -/ +def IsLogarithmicallyConvex (U : Set (ι → ℂ)) : Prop := + Convex ℝ {x : ι → ℝ | (fun i => (Real.exp (x i) : ℂ)) ∈ U} + +/-- The convergence domain of a power series: the interior of its set of absolute convergence. -/ +def convergenceDomain {G : Type*} [NormedAddCommGroup G] (c : MvPowerSeries ι G) : Set (ι → ℂ) := + interior {z | Summable fun m : ι →₀ ℕ => ‖c m‖ * ∏ i, ‖z i‖ ^ m i} + +omit [Fintype ι] in +/-- **17. Complete Reinhardt geometry**: a complete Reinhardt set is Reinhardt and, when nonempty, +path connected. -/ +theorem IsCompleteReinhardt.isReinhardt_and_isPathConnected {U : Set (ι → ℂ)} + (hU : IsCompleteReinhardt U) : IsReinhardt U ∧ (U.Nonempty → IsPathConnected U) := by + have h : SeveralComplexVariables.IsCompleteReinhardt U := hU + exact ⟨h.isReinhardt, fun hne => h.isPathConnected hne⟩ + +/-- **18. Logarithmic convexity including zero coordinates**: for an open complete Reinhardt set, +logarithmic convexity is closure under weighted geometric means of the coordinate moduli, with the +convention `0 ^ 0 = 1`. -/ +theorem isLogarithmicallyConvex_iff_geometric {U : Set (ι → ℂ)} (ho : IsOpen U) + (hc : IsCompleteReinhardt U) : + IsLogarithmicallyConvex U ↔ ∀ z ∈ U, ∀ w ∈ U, ∀ a b : ℝ, 0 ≤ a → 0 ≤ b → a + b = 1 → + ∀ v : ι → ℂ, (∀ i, ‖v i‖ = ‖z i‖ ^ a * ‖w i‖ ^ b) → v ∈ U := by + have hc' : SeveralComplexVariables.IsCompleteReinhardt U := hc + rw [show IsLogarithmicallyConvex U ↔ SeveralComplexVariables.IsLogarithmicallyConvex U from + Iff.rfl, ← SeveralComplexVariables.hasGeometricallyConvexModuli_iff ho hc'] + constructor + · intro h z hz w hw a b ha hb hab v hv + obtain ⟨u, hu, hue⟩ := h ⟨z, hz, rfl⟩ ⟨w, hw, rfl⟩ ha hb hab + refine hc'.isReinhardt hu fun i => ?_ + have hi := congrArg NNReal.toReal (congrFun hue i) + simp only [SeveralComplexVariables.geometricCombination, NNReal.coe_mul, NNReal.coe_rpow, + coe_nnnorm] at hi + rw [hv i, hi] + · rintro h _ ⟨z, hz, rfl⟩ _ ⟨w, hw, rfl⟩ a b ha hb hab + let u : ι → ℂ := fun i => ((‖z i‖ ^ a * ‖w i‖ ^ b : ℝ) : ℂ) + have hnn (i : ι) : 0 ≤ ‖z i‖ ^ a * ‖w i‖ ^ b := by positivity + have hu : u ∈ U := h z hz w hw a b ha hb hab u fun i => by + simp only [u, Complex.norm_real, Real.norm_of_nonneg (hnn i)] + refine ⟨u, hu, funext fun i => NNReal.eq ?_⟩ + simp only [u, SeveralComplexVariables.geometricCombination, coe_nnnorm, Complex.norm_real, + Real.norm_of_nonneg (hnn i), NNReal.coe_mul, NNReal.coe_rpow] + +/-- **19. Convergence domains of power series** are complete Reinhardt and logarithmically convex, +and the sum of the series is holomorphic there. -/ +theorem convergenceDomain_properties (c : MvPowerSeries ι F) : + IsCompleteReinhardt (convergenceDomain c) ∧ IsLogarithmicallyConvex (convergenceDomain c) ∧ + AnalyticOnNhd ℂ (fun z => ∑' m : ι →₀ ℕ, (∏ i, z i ^ m i) • c m) (convergenceDomain c) := by + exact ⟨SeveralComplexVariables.isCompleteReinhardt_powerSeriesConvergenceDomain c, + SeveralComplexVariables.isLogarithmicallyConvex_powerSeriesConvergenceDomain c, + SeveralComplexVariables.analyticOnNhd_powerSeriesSum c⟩ + +/-- **20. Taylor representation on complete Reinhardt sets**: a holomorphic function on an open +complete Reinhardt set is the sum of one power series on the whole set. -/ +theorem exists_powerSeries_eqOn_of_isCompleteReinhardt {n : ℕ} {U : Set (Fin n → ℂ)} + (ho : IsOpen U) (hc : IsCompleteReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) : + ∃ c : MvPowerSeries (Fin n) F, U ⊆ convergenceDomain c ∧ + EqOn (fun z => ∑' m : Fin n →₀ ℕ, (∏ i, z i ^ m i) • c m) f U := by + exact ⟨_, + SeveralComplexVariables.IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum + ho hc hf⟩ + +/-- **21. Characterization of convergence domains**: every nonempty open complete logarithmically +convex Reinhardt set is the convergence domain of a scalar power series. -/ +theorem exists_convergenceDomain_eq {U : Set (ι → ℂ)} (hU : IsOpen U) (hne : U.Nonempty) + (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) : + ∃ c : MvPowerSeries ι ℂ, convergenceDomain c = U := by + exact SeveralComplexVariables.exists_powerSeriesConvergenceDomain_eq hU hne hc hl + +/-- **22. Laurent expansion on Reinhardt domains**: a holomorphic function on a nonempty connected +open Reinhardt set has a unique locally uniformly convergent Laurent expansion. -/ +theorem existsUnique_laurent_expansion {n : ℕ} {U : Set (Fin n → ℂ)} (ho : IsOpen U) + (hc : IsPreconnected U) (hne : U.Nonempty) (hR : IsReinhardt U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) : + ∃! c : (Fin n → ℤ) → F, + HasSumLocallyUniformlyOn (fun m z => (∏ i, z i ^ m i) • c m) f U := by + obtain ⟨z, hz⟩ := hne + have hR' : SeveralComplexVariables.IsReinhardt U := hR + obtain ⟨r, hrU, hr⟩ := hR'.exists_strict_modulus_majorant ho hz + have h := SeveralComplexVariables.multivariableLaurent_expansion ho hc hR' hf + (r := fun i => (r i : ℝ)) (fun i => lt_of_le_of_lt (NNReal.coe_nonneg _) (hr i)) hrU + exact ⟨_, h.1, fun c hc' => h.2.2.2.2 c hc'⟩ + +/-- **23. Continuation from Reinhardt domains**: a holomorphic function on a connected open +Reinhardt set containing the origin extends to the complete Reinhardt hull. -/ +theorem exists_extension_completeReinhardtHull {n : ℕ} {U : Set (Fin n → ℂ)} (ho : IsOpen U) + (hc : IsConnected U) (hR : IsReinhardt U) (hzero : 0 ∈ U) {f : (Fin n → ℂ) → F} + (hf : AnalyticOnNhd ℂ f U) : + ∃ g, AnalyticOnNhd ℂ g {w | ∃ z ∈ U, ∀ i, ‖w i‖ ≤ ‖z i‖} ∧ EqOn g f U := by + exact SeveralComplexVariables.exists_extension_completeReinhardtHull ho hc hR hzero hf + +/-- **24. Continuation from circular domains**: a holomorphic function on a connected open set +invariant under `z ↦ e^{iθ} z` and containing the origin extends to the balanced hull. -/ +theorem exists_extension_balancedHull {U : Set E} (ho : IsOpen U) (hc : IsPreconnected U) + (hrot : ∀ ⦃z⦄, z ∈ U → ∀ ⦃c : ℂ⦄, ‖c‖ = 1 → c • z ∈ U) (hzero : (0 : E) ∈ U) {f : E → F} + (hf : AnalyticOnNhd ℂ f U) : ∃ g, AnalyticOnNhd ℂ g (balancedHull ℂ U) ∧ EqOn g f U := by + exact SeveralComplexVariables.exists_extension_balancedHull ho hc hrot hzero hf + +/-! ## E. Hartogs phenomena and removable singularities -/ + +/-- **25. Hartogs–Taylor expansion**: on an open set `U ⊆ E × ℂ` whose fibres are closed under +decreasing `|w|`, a holomorphic function is the locally uniform sum of its fibre Taylor series, +whose coefficients are holomorphic on the projection of `U`. -/ +theorem hartogs_taylor_expansion {U : Set (E × ℂ)} (hU : IsOpen U) + (hH : ∀ ⦃z w⦄, (z, w) ∈ U → ∀ ⦃v : ℂ⦄, ‖v‖ ≤ ‖w‖ → (z, v) ∈ U) {f : E × ℂ → F} + (hf : DifferentiableOn ℂ f U) : + (∀ k : ℕ, DifferentiableOn ℂ + (fun z => ((k.factorial : ℂ)⁻¹) • iteratedDeriv k (fun w => f (z, w)) 0) (Prod.fst '' U)) ∧ + HasSumLocallyUniformlyOn (fun (k : ℕ) (p : E × ℂ) => + p.2 ^ k • (((k.factorial : ℂ)⁻¹) • iteratedDeriv k (fun w => f (p.1, w)) 0)) f U := by + exact SeveralComplexVariables.differentiableOn_hartogsTaylorCoeff_and_hasSumLocallyUniformlyOn + hU hH hf + +/-- **26. Hartogs' continuity theorem**: a holomorphic function on the union of an annular cylinder +over a connected base `D` and a full cylinder over a nonempty open `D₀ ⊆ D` extends to the full +cylinder over `D`. -/ +theorem hartogs_cylinder_extension {D D₀ : Set E} (hD : IsOpen D) (hc : IsPreconnected D) + (hD₀ : IsOpen D₀) (hne : D₀.Nonempty) (hsub : D₀ ⊆ D) {ρ R : ℝ} (hρ : 0 ≤ ρ) (hρR : ρ < R) + {f : E × ℂ → F} + (hf : AnalyticOnNhd ℂ f ((D ×ˢ (ball 0 R \ closedBall 0 ρ)) ∪ (D₀ ×ˢ ball 0 R))) : + ∃ g, AnalyticOnNhd ℂ g (D ×ˢ ball 0 R) ∧ + EqOn g f ((D ×ˢ (ball 0 R \ closedBall 0 ρ)) ∪ (D₀ ×ˢ ball 0 R)) := by + exact SeveralComplexVariables.exists_extension_hartogsCylinder hD hc hD₀ hne hsub hρ hρR hf + +/-- **27. Hartogs' theorem on separate analyticity**: a function on an open subset of `ℂ^ι` that is +analytic in each variable separately is analytic, with no continuity or boundedness hypothesis. -/ +theorem hartogs_separate_analyticity [DecidableEq ι] {U : Set (ι → ℂ)} {f : (ι → ℂ) → F} + (hU : IsOpen U) (hf : ∀ z ∈ U, ∀ i, AnalyticAt ℂ (fun w => f (update z i w)) (z i)) : + AnalyticOnNhd ℂ f U := by + exact SeveralComplexVariables.analyticOnNhd_of_separately_analytic hU hf + +/-- **28. Isolated singularities are removable** in dimension at least two. -/ +theorem exists_extension_diff_singleton (hdim : 2 ≤ Module.finrank ℂ E) {U : Set E} + (ho : IsOpen U) {a : E} (ha : a ∈ U) {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ {a})) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ {a}) := by + exact SeveralComplexVariables.exists_analyticOnNhd_extension_diff_singleton hdim ho ha hf + +/-- **29. Zeros are not isolated** in dimension at least two. -/ +theorem frequently_zero_punctured (hdim : 2 ≤ Module.finrank ℂ E) {f : E → ℂ} {a : E} + (hf : AnalyticAt ℂ f a) (ha : f a = 0) : ∃ᶠ z in 𝓝[≠] a, f z = 0 := by + exact SeveralComplexVariables.frequently_zero_punctured_of_analyticAt hdim hf ha + +/-- **30. First Riemann extension theorem**: a holomorphic function on the complement of the zero +set of a nonzero holomorphic function `g` on a connected open set, locally bounded near that zero +set, extends holomorphically. -/ +theorem riemann_extension_first {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) {g : E → ℂ} + (hg : AnalyticOnNhd ℂ g U) (hne : ∃ z ∈ U, g z ≠ 0) {f : E → F} + (hf : AnalyticOnNhd ℂ f (U \ g ⁻¹' {0})) + (hb : ∀ a ∈ U, g a = 0 → ∃ r : ℝ, 0 < r ∧ ∃ C : ℝ, ∀ z ∈ ball a r ∩ (U \ g ⁻¹' {0}), + ‖f z‖ ≤ C) : + ∃ f' : E → F, AnalyticOnNhd ℂ f' U ∧ EqOn f' f (U \ g ⁻¹' {0}) := by + exact SeveralComplexVariables.exists_analyticOnNhd_extension_across_zeroSet hU hconn hg hne hf hb + +/-- **31. Hartogs' extension theorem (compact holes)**: in dimension at least two, a holomorphic +function on `U \ K`, with `K ⊆ U` compact and `U \ K` connected, extends to `U`. -/ +theorem hartogs_compact_hole (hdim : 2 ≤ Module.finrank ℂ E) {U K : Set E} (hU : IsOpen U) + (hK : IsCompact K) (hKU : K ⊆ U) (hcompl : IsPreconnected (U \ K)) {f : E → F} + (hf : AnalyticOnNhd ℂ f (U \ K)) : ∃ g : E → F, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ K) := by + exact SeveralComplexVariables.exists_analyticOnNhd_extension_of_isCompact hdim hU hK hKU hcompl hf + +/-! ## F. Elementary analytic sets -/ + +/-- `A` is an analytic subset of `U`: near every point of `U` it is the common zero set of finitely +many holomorphic functions. -/ +def IsAnalyticSet (U A : Set E) : Prop := + A ⊆ U ∧ ∀ a ∈ U, ∃ V : Set E, IsOpen V ∧ a ∈ V ∧ V ⊆ U ∧ + ∃ s : Finset (E → ℂ), (∀ f ∈ s, AnalyticOnNhd ℂ f V) ∧ + ∀ z ∈ V, z ∈ A ↔ ∀ f ∈ s, f z = 0 + +/-- `a` is a regular point of `A` of codimension `q`: a local biholomorphic change of coordinates +carries `A` to a complex linear subspace of codimension `q`. -/ +def IsRegularAnalyticSetAt (A : Set E) (a : E) (q : ℕ) : Prop := + a ∈ A ∧ ∃ (e : OpenPartialHomeomorph E E) (L : E →L[ℂ] (Fin q → ℂ)), + (DifferentiableOn ℂ e e.source ∧ DifferentiableOn ℂ e.symm e.target) ∧ a ∈ e.source ∧ + Function.Surjective L ∧ ∀ z ∈ e.source, z ∈ A ↔ L (e z) = 0 + +/-- **32. Analytic sets are thin**: a proper analytic subset of a connected open set has empty +interior and connected complement. -/ +theorem IsAnalyticSet.interior_eq_empty_and_isConnected_sdiff {U A : Set E} + (hA : IsAnalyticSet U A) (hc : IsConnected U) (hp : A ≠ U) : + interior A = ∅ ∧ IsConnected (U \ A) := by + have h : SeveralComplexVariables.IsAnalyticSet U A := hA + exact ⟨h.interior_eq_empty hc.isPreconnected hp, h.isConnected_sdiff hc hp⟩ + +/-- **33. Regular points and full-rank equations**: `a` is a regular point of codimension `q` +exactly when `A` is near `a` the zero set of `q` holomorphic equations of full rank at `a`. -/ +theorem isRegularAnalyticSetAt_iff_exists_equations {A : Set E} {a : E} {q : ℕ} : + IsRegularAnalyticSetAt A a q ↔ a ∈ A ∧ ∃ (V : Set E) (f : E → (Fin q → ℂ)), + IsOpen V ∧ a ∈ V ∧ AnalyticOnNhd ℂ f V ∧ (∀ z ∈ V, z ∈ A ↔ f z = 0) ∧ + Function.Surjective (fderiv ℂ f a) := by + exact SeveralComplexVariables.isRegularAnalyticSetAt_iff_exists_equations + +/-- **34. Removal of a coordinate plane of codimension two**. -/ +theorem exists_extension_across_coordinatePlane {U : Set ((E × ℂ) × ℂ)} (hU : IsOpen U) + {f : ((E × ℂ) × ℂ) → F} (hf : AnalyticOnNhd ℂ f (U \ {z | z.1.2 = 0 ∧ z.2 = 0})) : + ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ {z | z.1.2 = 0 ∧ z.2 = 0}) := by + exact SeveralComplexVariables.exists_extension_across_coordinatePlane hU hf + +/-- **35. Second Riemann extension theorem**: holomorphic functions extend across an analytic subset +through each point of which some complex affine plane meets it only at that point, locally. -/ +theorem riemann_extension_second {U A : Set E} (hA : IsAnalyticSet U A) + (hcodim : ∀ a ∈ A, ∃ L : (Fin 2 → ℂ) →L[ℂ] E, Function.Injective L ∧ + ∀ᶠ z in 𝓝 (0 : Fin 2 → ℂ), a + L z ∈ A → z = 0) + {f : E → F} (hf : AnalyticOnNhd ℂ f (U \ A)) : ∃ g, AnalyticOnNhd ℂ g U ∧ EqOn g f (U \ A) := by + have h : SeveralComplexVariables.IsAnalyticSet U A := hA + exact h.exists_extension_of_codimension_two hcodim hf + +/-! ## G. Germs, Weierstrass theory, and elementary local algebra -/ + +/-- The ring `𝒪ₓ` of germs at `x` of scalar analytic functions, as a subring of all germs. -/ +def analyticGermRing (x : E) : Subring (Germ (𝓝 x) ℂ) where + carrier := {φ | ∃ f : E → ℂ, AnalyticAt ℂ f x ∧ (f : Germ (𝓝 x) ℂ) = φ} + zero_mem' := ⟨0, analyticAt_const, rfl⟩ + one_mem' := ⟨1, analyticAt_const, rfl⟩ + add_mem' := by + rintro _ _ ⟨f, hf, rfl⟩ ⟨g, hg, rfl⟩ + exact ⟨f + g, hf.add hg, rfl⟩ + neg_mem' := by + rintro _ ⟨f, hf, rfl⟩ + exact ⟨-f, hf.neg, rfl⟩ + mul_mem' := by + rintro _ _ ⟨f, hf, rfl⟩ ⟨g, hg, rfl⟩ + exact ⟨f * g, hf.mul hg, rfl⟩ + +/-- The germ at `x` of a function analytic at `x`. -/ +def germ {x : E} (f : E → ℂ) (hf : AnalyticAt ℂ f x) : analyticGermRing x := ⟨f, f, hf, rfl⟩ + +/-- A remainder of degree less than `d` in the last variable, with coefficient functions `a j`. -/ +def weierstrassRemainder {d : ℕ} (a : Fin d → E → ℂ) (z : E × ℂ) : ℂ := + ∑ j : Fin d, a j z.1 * z.2 ^ (j : ℕ) + +/-- Weierstrass division at the origin: `g = q f + r` as germs, with `r` a polynomial of degree +less than `d` in the last variable. -/ +def IsWeierstrassDivisionAt {d : ℕ} (f g q : E × ℂ → ℂ) (a : Fin d → E → ℂ) : Prop := + AnalyticAt ℂ q 0 ∧ (∀ j, AnalyticAt ℂ (a j) 0) ∧ + g =ᶠ[𝓝 0] fun z => q z * f z + weierstrassRemainder a z + +/-- Weierstrass preparation at the origin: `f = u W` as germs, with `u` a unit and `W` a +distinguished polynomial of degree `d` in the last variable. -/ +def IsWeierstrassPreparationAt {d : ℕ} (f u : E × ℂ → ℂ) (a : Fin d → E → ℂ) : Prop := + AnalyticAt ℂ u 0 ∧ u 0 ≠ 0 ∧ (∀ j, AnalyticAt ℂ (a j) 0) ∧ (∀ j, a j 0 = 0) ∧ + f =ᶠ[𝓝 0] fun z => u z * (z.2 ^ d + weierstrassRemainder a z) + +-- BEGIN SOLUTION ONLY +omit [FiniteDimensional ℂ E] in +/-- The submission ring of analytic germs is the library analytic germ subring. -/ +private theorem analyticGermRing_eq (x : E) : + analyticGermRing x = SeveralComplexVariables.analyticGermSubring ℂ x := rfl + +omit [FiniteDimensional ℂ E] in +/-- The submission and library predicates for Weierstrass division are equivalent. -/ +private theorem isWeierstrassDivisionAt_iff {d : ℕ} {f g q : E × ℂ → ℂ} {a : Fin d → E → ℂ} : + IsWeierstrassDivisionAt f g q a ↔ SeveralComplexVariables.IsWeierstrassDivisionAt f g q a := + ⟨fun h => ⟨h.1, h.2.1, h.2.2⟩, fun h => ⟨h.1, h.2, h.3⟩⟩ + +omit [FiniteDimensional ℂ E] in +/-- The submission and library predicates for Weierstrass preparation are equivalent. -/ +private theorem isWeierstrassPreparationAt_iff {d : ℕ} {f u : E × ℂ → ℂ} {a : Fin d → E → ℂ} : + IsWeierstrassPreparationAt f u a ↔ SeveralComplexVariables.IsWeierstrassPreparationAt f u a := + ⟨fun h => ⟨h.1, h.2.1, h.2.2.1, h.2.2.2.1, h.2.2.2.2⟩, fun h => ⟨h.1, h.2, h.3, h.4, h.5⟩⟩ +-- END SOLUTION ONLY + +omit [FiniteDimensional ℂ E] in +/-- **36. The ring of analytic germs is a local integral domain**, and a germ is a unit exactly when +it does not vanish at the base point. -/ +theorem analyticGermRing_isDomain_isLocalRing (x : E) : + IsDomain (analyticGermRing x) ∧ IsLocalRing (analyticGermRing x) ∧ + ∀ (f : E → ℂ) (hf : AnalyticAt ℂ f x), IsUnit (germ f hf) ↔ f x ≠ 0 := by + refine ⟨inferInstanceAs (IsDomain (SeveralComplexVariables.AnalyticGerm ℂ x)), + inferInstanceAs (IsLocalRing (SeveralComplexVariables.AnalyticGerm ℂ x)), fun f hf => ?_⟩ + exact SeveralComplexVariables.AnalyticGerm.isUnit_iff + (SeveralComplexVariables.AnalyticGerm.ofAnalyticAt f hf) + +/-- **37. Coordinate normalization**: after a linear change of coordinates, a nonzero germ has +finite order in the last variable. -/ +theorem exists_regular_coordinate_change {f : E × ℂ → ℂ} (hf : AnalyticAt ℂ f 0) + (hne : ¬ f =ᶠ[𝓝 0] 0) : + ∃ (L : (E × ℂ) ≃L[ℂ] (E × ℂ)) (d : ℕ), analyticOrderAt (fun w : ℂ => f (L (0, w))) 0 = d := by + exact SeveralComplexVariables.exists_regular_coordinate_change hf hne + +/-- **38. Taylor series determine germs** and are multiplicative. -/ +theorem taylorSeries_mul_and_eq_zero_iff {n : ℕ} {x : Fin n → ℂ} {f g : (Fin n → ℂ) → ℂ} + (hf : AnalyticAt ℂ f x) (hg : AnalyticAt ℂ g x) : + taylorSeries (f * g) x = taylorSeries f x * taylorSeries g x ∧ + (taylorSeries f x = 0 ↔ f =ᶠ[𝓝 x] 0) := by + open SeveralComplexVariables.AnalyticGerm in + refine ⟨?_, ?_⟩ + · have h := taylorSeries_mul (ofAnalyticAt f hf) (ofAnalyticAt g hg) + rwa [← ofAnalyticAt_mul, taylorSeries_ofAnalyticAt, taylorSeries_ofAnalyticAt, + taylorSeries_ofAnalyticAt, ← taylorSeries_eq, ← taylorSeries_eq, ← taylorSeries_eq] at h + · have h := taylorSeries_eq_zero_iff (ofAnalyticAt f hf) + rw [taylorSeries_ofAnalyticAt, ← taylorSeries_eq, ← ofAnalyticAt_zero, + ofAnalyticAt_eq_iff] at h + exact h + +/-- **39. Division by a power of the last coordinate** on a product of a polydisc `P` and a disc, +with a bound for the quotient. -/ +theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < R) {P : Set (ι → ℂ)} + (hP : P = Set.pi univ fun i => ball (0 : ℂ) (r i)) {g : (ι → ℂ) × ℂ → ℂ} + (hg : DifferentiableOn ℂ g (P ×ˢ ball 0 R)) : + ∃ (q : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), DifferentiableOn ℂ q (P ×ˢ ball 0 R) ∧ + (∀ j, DifferentiableOn ℂ (a j) P) ∧ + EqOn g (fun z => q z * z.2 ^ d + weierstrassRemainder a z) (P ×ˢ ball 0 R) ∧ + ∀ M : ℝ, 0 ≤ M → (∀ z ∈ P ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) → + ∀ z ∈ P ×ˢ ball (0 : ℂ) R, ‖q z‖ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * M := by + subst hP + obtain ⟨q, a, hdiv, hb, -⟩ := SeveralComplexVariables.coordinatePower_division d (r := r) hR hg + exact ⟨q, a, hdiv.1, hdiv.2, hdiv.3, hb⟩ + +/-- **40. Weierstrass division theorem**, with uniqueness of quotient and remainder as germs. -/ +theorem weierstrass_division {d : ℕ} {f g : E × ℂ → ℂ} (hf : AnalyticAt ℂ f 0) + (hg : AnalyticAt ℂ g 0) (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (q : E × ℂ → ℂ) (a : Fin d → E → ℂ), IsWeierstrassDivisionAt f g q a ∧ + ∀ q' a', IsWeierstrassDivisionAt f g q' a' → q =ᶠ[𝓝 0] q' ∧ ∀ j, a j =ᶠ[𝓝 0] a' j := by + obtain ⟨q, a, h, hu⟩ := + SeveralComplexVariables.exists_isWeierstrassDivisionAt_of_finiteDimensional hf hg horder + exact ⟨q, a, isWeierstrassDivisionAt_iff.mpr h, + fun q' a' h' => hu q' a' (isWeierstrassDivisionAt_iff.mp h')⟩ + +/-- **41. Weierstrass preparation theorem**, with uniqueness of the unit and the polynomial. -/ +theorem weierstrass_preparation {d : ℕ} {f : E × ℂ → ℂ} (hf : AnalyticAt ℂ f 0) + (horder : analyticOrderAt (fun w : ℂ => f (0, w)) 0 = d) : + ∃ (u : E × ℂ → ℂ) (a : Fin d → E → ℂ), IsWeierstrassPreparationAt f u a ∧ + ∀ v b, IsWeierstrassPreparationAt f v b → u =ᶠ[𝓝 0] v ∧ ∀ j, a j =ᶠ[𝓝 0] b j := by + obtain ⟨u, a, h, hu⟩ := + SeveralComplexVariables.exists_isWeierstrassPreparationAt_of_finiteDimensional hf horder + exact ⟨u, a, isWeierstrassPreparationAt_iff.mpr h, + fun v b h' => hu v b (isWeierstrassPreparationAt_iff.mp h')⟩ + +/-- **44–45. The ring of analytic germs is Noetherian and factorial.** -/ +theorem analyticGermRing_isNoetherianRing_ufd (x : E) : + IsNoetherianRing (analyticGermRing x) ∧ UniqueFactorizationMonoid (analyticGermRing x) := by + exact ⟨inferInstanceAs (IsNoetherianRing (SeveralComplexVariables.AnalyticGerm ℂ x)), + inferInstanceAs (UniqueFactorizationMonoid (SeveralComplexVariables.AnalyticGerm ℂ x))⟩ + +/-- **45. Relative primality persists**: the set of points at which the germs of two functions are +analytic and relatively prime is open. -/ +theorem isOpen_isRelPrime_locus (f g : E → ℂ) : + IsOpen {x | ∃ (hf : AnalyticAt ℂ f x) (hg : AnalyticAt ℂ g x), + IsRelPrime (germ f hf) (germ g hg)} := by + exact SeveralComplexVariables.AnalyticGerm.isOpen_isRelPrime_locus f g + +/-! ## H. Zero-set geometry and biholomorphic rigidity -/ + +/-- **46. Regular points of hypersurfaces**: the zero set of a holomorphic function on a connected +open set, if nonempty and proper, contains a regular point of codimension one. -/ +theorem exists_regularPoint_zeroSet {U : Set E} (hU : IsOpen U) (hc : IsPreconnected U) {f : E → ℂ} + (hf : AnalyticOnNhd ℂ f U) (hne : ∃ b ∈ U, f b ≠ 0) (hz : ∃ a ∈ U, f a = 0) : + ∃ a, IsRegularAnalyticSetAt (U ∩ f ⁻¹' {0}) a 1 := by + exact SeveralComplexVariables.exists_regularPoint_zeroSet hU hc hf hne hz + +/-- **47. Injective holomorphic maps in equal dimensions are biholomorphic** onto their open +image. -/ +theorem injOn_biholomorphic {G : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + [FiniteDimensional ℂ G] (hdim : Module.finrank ℂ E = Module.finrank ℂ G) {U : Set E} + (hU : IsOpen U) {f : E → G} (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) : + ∃ e : OpenPartialHomeomorph E G, DifferentiableOn ℂ e e.source ∧ + DifferentiableOn ℂ e.symm e.target ∧ e.source = U ∧ e.target = f '' U ∧ (e : E → G) = f := by + obtain ⟨e, he, h⟩ := SeveralComplexVariables.exists_biholomorphic_of_injOn hdim hU hf hi + exact ⟨e, he.1, he.2, h⟩ + +/-- **48. Cartan's uniqueness theorem**: a holomorphic self-map of a bounded connected open set +fixing a point with identity derivative there is the identity. -/ +theorem cartan_uniqueness {U : Set E} (hU : IsOpen U) (hconn : IsPreconnected U) + (hb : Bornology.IsBounded U) {f : E → E} (hf : AnalyticOnNhd ℂ f U) (hmaps : MapsTo f U U) + {a : E} (ha : a ∈ U) (hfix : f a = a) (hderiv : fderiv ℂ f a = ContinuousLinearMap.id ℂ E) : + EqOn f id U := by + exact SeveralComplexVariables.eqOn_id_of_mapsTo_of_fderiv_eq_id hU hconn hb hf hmaps ha hfix + hderiv + +/-- **49. Biholomorphisms of circular domains fixing the origin are linear**, when the source is +bounded and connected. -/ +theorem biholomorphic_circular_linear {G : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + [FiniteDimensional ℂ G] {e : OpenPartialHomeomorph E G} (he : DifferentiableOn ℂ e e.source) + (he' : DifferentiableOn ℂ e.symm e.target) (hc : IsPreconnected e.source) + (hb : Bornology.IsBounded e.source) + (hrot : ∀ ⦃z⦄, z ∈ e.source → ∀ ⦃c : ℂ⦄, ‖c‖ = 1 → c • z ∈ e.source) + (hrot' : ∀ ⦃z⦄, z ∈ e.target → ∀ ⦃c : ℂ⦄, ‖c‖ = 1 → c • z ∈ e.target) + (hzero : (0 : E) ∈ e.source) (hfix : e 0 = 0) : ∃ L : E ≃L[ℂ] G, EqOn e L e.source := by + have h : SeveralComplexVariables.IsBiholomorphic e := ⟨he, he'⟩ + exact h.exists_linearEquiv_of_circular hc hb hrot hrot' hzero hfix + +/-- **50. The automorphisms of the unit ball of a complex inner product space act transitively.** -/ +theorem exists_ball_automorphism {H : Type*} [NormedAddCommGroup H] [InnerProductSpace ℂ H] + {a b : H} (ha : a ∈ ball (0 : H) 1) (hb : b ∈ ball (0 : H) 1) : + ∃ e : OpenPartialHomeomorph H H, DifferentiableOn ℂ e e.source ∧ + DifferentiableOn ℂ e.symm e.target ∧ e.source = ball 0 1 ∧ e.target = ball 0 1 ∧ + e a = b := by + obtain ⟨e, he, h⟩ := SeveralComplexVariables.exists_ball_automorphism ha hb + exact ⟨e, he.1, he.2, h⟩ + +/-- **50. The unit polydisc and the Euclidean unit ball are not biholomorphic** in dimension at +least two. -/ +theorem not_biholomorphic_polydisc_ball (hdim : 2 ≤ Fintype.card ι) : + ¬ ∃ e : OpenPartialHomeomorph (ι → ℂ) (EuclideanSpace ℂ ι), DifferentiableOn ℂ e e.source ∧ + DifferentiableOn ℂ e.symm e.target ∧ e.source = ball 0 1 ∧ e.target = ball 0 1 := by + rintro ⟨e, h1, h2, h⟩ + exact SeveralComplexVariables.not_exists_isBiholomorphic_polydisc_ball hdim ⟨e, ⟨h1, h2⟩, h⟩ + +/-! ## I. Common extensions, holomorphic convexity, Cartan–Thullen, and Bochner's tube theorem -/ + +/-- The holomorphic hull of `K` relative to `U`: the points of `U` at which every holomorphic +function on `U` is bounded by each of its bounds on `K`. -/ +def holomorphicHull (U K : Set E) : Set E := + {z | z ∈ U ∧ ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → ∀ M : ℝ, (∀ w ∈ K, ‖f w‖ ≤ M) → ‖f z‖ ≤ M} + +/-- `U` is holomorphically convex: hulls of compact subsets are compact. -/ +def IsHolomorphicallyConvex (U : Set E) : Prop := + ∀ K : Set E, IsCompact K → K ⊆ U → IsCompact (holomorphicHull U K) + +/-- The generalized domain-of-holomorphy continuation property for a set `U`: there is no connected +open set `V ⊄ U` with a nonempty open `W ⊆ U ∩ V` such that every holomorphic function on `U` +agrees on `W` with one on `V`. + +Openness, connectedness, and nonemptiness of `U` are separate hypotheses. This predicate is +automatically satisfied when `interior U = ∅`, because no nonempty open overlap exists. -/ +def IsDomainOfHolomorphy (U : Set E) : Prop := + ∀ V W : Set E, IsOpen V → IsConnected V → IsOpen W → W.Nonempty → W ⊆ U → W ⊆ V → + (∀ f : E → ℂ, AnalyticOnNhd ℂ f U → ∃ g : E → ℂ, AnalyticOnNhd ℂ g V ∧ EqOn g f W) → V ⊆ U + +/-- `U` is the domain of existence of `f`: `f` is holomorphic on `U` and has no continuation in the +above sense. -/ +def IsDomainOfExistence (U : Set E) (f : E → ℂ) : Prop := + AnalyticOnNhd ℂ f U ∧ + ∀ V W : Set E, IsOpen V → IsConnected V → IsOpen W → W.Nonempty → W ⊆ U → W ⊆ V → + (∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f W) → V ⊆ U + +/-- **51. Common extension domains**: if every holomorphic function on a nonempty open `U` extends +to the connected set `V ⊇ U`, then `V` lies in the convex hull of `U` and holomorphic functions on +`V` take no new values. -/ +theorem common_extension {U V : Set E} (hUV : U ⊆ V) + (hext : ∀ f : E → ℂ, AnalyticOnNhd ℂ f U → ∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f U) + (ho : IsOpen U) (hne : U.Nonempty) (hc : IsPreconnected V) : + V ⊆ convexHull ℝ U ∧ ∀ f : E → ℂ, AnalyticOnNhd ℂ f V → f '' V = f '' U := by + have h := SeveralComplexVariables.isCommonAnalyticExtension_of_forall hUV hext + exact ⟨h.subset_convexHull ho hne hc, fun f hf => h.image_eq ho hne hc hf⟩ + +/-- **52. Holomorphic hulls** are idempotent, and hulls of bounded sets are bounded. -/ +theorem holomorphicHull_idem_and_isBounded (U : Set (ι → ℂ)) {K : Set (ι → ℂ)} : + holomorphicHull U (holomorphicHull U K) = holomorphicHull U K ∧ + (Bornology.IsBounded K → Bornology.IsBounded (holomorphicHull U K)) := by + exact ⟨SeveralComplexVariables.holomorphicHull_idem U K, + SeveralComplexVariables.isBounded_holomorphicHull U⟩ + +/-- **52. Open complete logarithmically convex Reinhardt sets are holomorphically convex.** -/ +theorem isHolomorphicallyConvex_of_completeReinhardt {U : Set (ι → ℂ)} (ho : IsOpen U) + (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) : IsHolomorphicallyConvex U := by + exact SeveralComplexVariables.isHolomorphicallyConvex_of_completeReinhardt ho hc hl + +/-- **53. Elementary continuation obstructions.** Convex open sets and finite products of arbitrary +plane sets satisfy `IsDomainOfHolomorphy`, the continuation-obstruction predicate defined above. +This predicate does not require openness, connectedness, or nonemptiness. It holds vacuously +whenever the set has empty interior, because no nonempty open overlap exists. For nonempty +connected open plane factors, the product assertion recovers the classical theorem that their +product is a domain of holomorphy. -/ +theorem isDomainOfHolomorphy_of_convex_and_pi : + (∀ U : Set E, Convex ℝ U → IsOpen U → IsDomainOfHolomorphy U) ∧ + ∀ S : ι → Set ℂ, IsDomainOfHolomorphy (Set.pi univ S) := by + exact ⟨fun _ hU ho => SeveralComplexVariables.isDomainOfHolomorphy_of_convex hU ho, + fun S => SeveralComplexVariables.isDomainOfHolomorphy_pi S⟩ + +/-- **54. Escaping sequences**: an open set is holomorphically convex exactly when every sequence +leaving all its compact subsets is unbounded under some holomorphic function. -/ +theorem isHolomorphicallyConvex_iff_escaping {U : Set E} (ho : IsOpen U) : + IsHolomorphicallyConvex U ↔ ∀ p : ℕ → E, (∀ j, p j ∈ U) → + (∀ K : Set E, IsCompact K → K ⊆ U → ∀ᶠ j in atTop, p j ∉ K) → + ∃ f : E → ℂ, AnalyticOnNhd ℂ f U ∧ ¬ BddAbove (Set.range fun j => ‖f (p j)‖) := by + exact SeveralComplexVariables.isHolomorphicallyConvex_iff_unbounded_on_escaping_sequences ho + +/-- **55. Thullen's lemma, as a characterization**: an open subset of `ℂ^ι` with the supremum norm +is a domain of holomorphy exactly when polydisc radii available on a compact set remain available +on its holomorphic hull. -/ +theorem isDomainOfHolomorphy_iff_hull_radius {n : ℕ} {U : Set (Fin n → ℂ)} (ho : IsOpen U) : + IsDomainOfHolomorphy U ↔ ∀ K, IsCompact K → K ⊆ U → ∀ r : ℝ, 0 < r → + (∀ x ∈ K, ball x r ⊆ U) → ∀ a ∈ holomorphicHull U K, ball a r ⊆ U := by + exact SeveralComplexVariables.isDomainOfHolomorphy_iff_hasHolomorphicHullRadiusProperty ho + +/-- **56. Cartan–Thullen theorem**: for an open set, being a domain of holomorphy, holomorphic +convexity, and being the domain of existence of one function are equivalent. -/ +theorem cartan_thullen {U : Set E} (ho : IsOpen U) : + (IsDomainOfHolomorphy U ↔ IsHolomorphicallyConvex U) ∧ + (IsDomainOfHolomorphy U ↔ ∃ f : E → ℂ, IsDomainOfExistence U f) := by + exact ⟨SeveralComplexVariables.isDomainOfHolomorphy_iff_isHolomorphicallyConvex ho, + SeveralComplexVariables.isDomainOfHolomorphy_iff_exists_domainOfExistence ho⟩ + +/-- **57. Bochner's tube theorem**: a holomorphic function on the tube over a connected open base +`Ω ⊆ ℝ^ι` extends to the tube over the convex hull of `Ω`, and the tube is a domain of holomorphy +exactly when `Ω` is convex. -/ +theorem bochner_tube {Ω : Set (ι → ℝ)} (ho : IsOpen Ω) (hc : IsPreconnected Ω) : + (∀ f : (ι → ℂ) → F, AnalyticOnNhd ℂ f {z | (fun i => (z i).re) ∈ Ω} → + ∃ g : (ι → ℂ) → F, AnalyticOnNhd ℂ g {z | (fun i => (z i).re) ∈ convexHull ℝ Ω} ∧ + EqOn g f {z | (fun i => (z i).re) ∈ Ω}) ∧ + (IsDomainOfHolomorphy {z : ι → ℂ | (fun i => (z i).re) ∈ Ω} ↔ Convex ℝ Ω) := by + exact ⟨fun f hf => SeveralComplexVariables.exists_extension_tubeDomain_convexHull ho hc hf, + SeveralComplexVariables.isDomainOfHolomorphy_tubeDomain_iff ho hc⟩ + +/-! ## J. Plurisubharmonic functions, the Levi form, and pseudoconvexity -/ + +/-- The local submean property of `u` at `a`: on all small circles around `a`, `u` is integrable +and `u a` is at most its average. -/ +def HasSubmeanAt (u : ℂ → ℝ) (a : ℂ) : Prop := + ∀ᶠ r in 𝓝[>] (0 : ℝ), CircleIntegrable u a r ∧ u a ≤ Real.circleAverage u a r + +/-- `u` is subharmonic on `U`: upper semicontinuous with the local submean property. -/ +def SubharmonicOn (u : ℂ → ℝ) (U : Set ℂ) : Prop := + UpperSemicontinuousOn u U ∧ ∀ a ∈ U, HasSubmeanAt u a + +/-- `f` is plurisubharmonic on `U`: upper semicontinuous, and subharmonic on every complex line. -/ +def PlurisubharmonicOn (f : E → ℝ) (U : Set E) : Prop := + UpperSemicontinuousOn f U ∧ + ∀ a ∈ U, ∀ w : E, SubharmonicOn (fun t : ℂ => f (a + t • w)) {t | a + t • w ∈ U} + +/-- The Levi form of `f` at `a` in the direction `w`, through the real second derivative. -/ +noncomputable def leviForm (f : E → ℝ) (a w : E) : ℝ := + (iteratedFDeriv ℝ 2 f a ![w, w] + iteratedFDeriv ℝ 2 f a ![I • w, I • w]) / 4 + +/-- `U` is pseudoconvex: open, with a continuous plurisubharmonic exhaustion function. -/ +def IsPseudoconvex (U : Set E) : Prop := + IsOpen U ∧ ∃ φ : E → ℝ, ContinuousOn φ U ∧ PlurisubharmonicOn φ U ∧ + ∀ c : ℝ, IsCompact {z ∈ U | φ z ≤ c} + +/-- `ρ` is a local `C²` defining function of `U` on the neighbourhood `V` of the point `p`. -/ +def IsLocalDefiningFunction (U : Set E) (p : E) (ρ : E → ℝ) (V : Set E) : Prop := + IsOpen V ∧ p ∈ V ∧ ContDiffOn ℝ 2 ρ V ∧ ρ p = 0 ∧ fderiv ℝ ρ p ≠ 0 ∧ U ∩ V = {z | ρ z < 0} ∩ V + +/-- `w` is a complex tangent vector at `p` of the level set of `ρ`. -/ +def IsComplexTangent (ρ : E → ℝ) (p w : E) : Prop := + fderiv ℝ ρ p w = 0 ∧ fderiv ℝ ρ p (I • w) = 0 + +/-- The Levi condition at `p`: for every local defining function, the Levi form is positive +semidefinite on the complex tangent space. -/ +def IsLeviPseudoconvexAt (U : Set E) (p : E) : Prop := + ∀ (ρ : E → ℝ) (V : Set E), IsLocalDefiningFunction U p ρ V → + ∀ w, IsComplexTangent ρ p w → 0 ≤ leviForm ρ p w + +-- BEGIN SOLUTION ONLY +omit [FiniteDimensional ℂ E] in +/-- The submission and library predicates for local defining functions are equivalent. -/ +private theorem isLocalDefiningFunction_iff {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} : + IsLocalDefiningFunction U p ρ V ↔ SeveralComplexVariables.IsLocalDefiningFunction U p ρ V := + ⟨fun h => ⟨h.1, h.2.1, h.2.2.1, h.2.2.2.1, h.2.2.2.2.1, h.2.2.2.2.2⟩, + fun h => ⟨h.1, h.2, h.3, h.4, h.5, h.6⟩⟩ + +omit [FiniteDimensional ℂ E] in +/-- The submission and library predicates for Levi pseudoconvexity are equivalent. -/ +private theorem isLeviPseudoconvexAt_iff {U : Set E} {p : E} : + IsLeviPseudoconvexAt U p ↔ SeveralComplexVariables.IsLeviPseudoconvexAt U p := + ⟨fun h ρ V hρ => h ρ V (isLocalDefiningFunction_iff.mpr hρ), + fun h ρ V hρ => h ρ V (isLocalDefiningFunction_iff.mp hρ)⟩ +-- END SOLUTION ONLY + +/-- **58. Maximum principle for subharmonic functions.** -/ +theorem SubharmonicOn.eqOn_const_of_isMaxOn {u : ℂ → ℝ} {U : Set ℂ} {a : ℂ} (hU : IsOpen U) + (hc : IsPreconnected U) (hu : SubharmonicOn u U) (ha : a ∈ U) (hmax : ∀ z ∈ U, u z ≤ u a) : + ∀ z ∈ U, u z = u a := by + have h : SeveralComplexVariables.SubharmonicOn u U := hu + exact h.eqOn_const_of_isMaxOn hU hc ha hmax + +/-- **59. Laplacian criterion**: a `C²` function on an open subset of `ℂ` is subharmonic exactly +when its Laplacian is nonnegative. -/ +theorem subharmonicOn_iff_laplacian_nonneg {g : ℂ → ℝ} {U : Set ℂ} (hU : IsOpen U) + (hg : ContDiffOn ℝ 2 g U) : SubharmonicOn g U ↔ ∀ t ∈ U, 0 ≤ Laplacian.laplacian g t := by + refine ⟨fun h t ht => ?_, + fun h => SeveralComplexVariables.subharmonicOn_of_laplacian_nonneg hU hg h⟩ + exact SeveralComplexVariables.HasSubmeanAt.laplacian_nonneg (hg.contDiffAt (hU.mem_nhds ht)) + (h.2 t ht) + +omit [FiniteDimensional ℂ E] in +/-- **60. Levi-form criterion**: a `C²` function is plurisubharmonic exactly when its Levi form is +positive semidefinite. -/ +theorem plurisubharmonicOn_iff_leviForm_nonneg {f : E → ℝ} {U : Set E} (hU : IsOpen U) + (hf : ContDiffOn ℝ 2 f U) : + PlurisubharmonicOn f U ↔ ∀ a ∈ U, ∀ w : E, 0 ≤ leviForm f a w := by + exact SeveralComplexVariables.plurisubharmonicOn_iff_leviForm_nonneg hU hf + +/-- **61. Domains of holomorphy are pseudoconvex.** -/ +theorem IsDomainOfHolomorphy.isPseudoconvex {U : Set E} (hU : IsDomainOfHolomorphy U) + (ho : IsOpen U) : IsPseudoconvex U := by + have h : SeveralComplexVariables.IsDomainOfHolomorphy U := hU + exact h.isPseudoconvex ho + +omit [FiniteDimensional ℂ E] in +/-- **61. Pseudoconvex sets satisfy the continuity principle** for continuous families of affine +analytic discs. -/ +theorem IsPseudoconvex.continuity_principle {U : Set E} (h : IsPseudoconvex U) (a b : ℝ → E) + (ha : Continuous a) (hb : Continuous b) + (hbdry : ∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ sphere (0 : ℂ) 1, a t + ζ • b t ∈ U) + (hinit : ∀ ζ ∈ closedBall (0 : ℂ) 1, a 0 + ζ • b 0 ∈ U) : + ∀ t ∈ Icc (0 : ℝ) 1, ∀ ζ ∈ closedBall (0 : ℂ) 1, a t + ζ • b t ∈ U := by + have h' : SeveralComplexVariables.IsPseudoconvex U := h + exact h'.satisfiesContinuityPrinciple a b ha hb hbdry hinit + +/-- **62. Levi's theorem**: a domain of holomorphy satisfies the Levi condition at every boundary +point admitting a local `C²` defining function. -/ +theorem IsDomainOfHolomorphy.isLeviPseudoconvexAt {U : Set E} (hU : IsDomainOfHolomorphy U) + (ho : IsOpen U) {p : E} (hp : p ∈ frontier U) : IsLeviPseudoconvexAt U p := by + have h : SeveralComplexVariables.IsDomainOfHolomorphy U := hU + exact isLeviPseudoconvexAt_iff.mpr (h.isLeviPseudoconvex ho p hp) + +omit [FiniteDimensional ℂ E] in +/-- **63. The Levi form under holomorphic maps.** -/ +theorem leviForm_comp_analytic {G : Type*} [NormedAddCommGroup G] [NormedSpace ℂ G] + [CompleteSpace G] {g : G → ℝ} + {Φ : E → G} {a : E} (hg : ContDiffAt ℝ 2 g (Φ a)) (hΦ : AnalyticAt ℂ Φ a) (w : E) : + leviForm (g ∘ Φ) a w = leviForm g (Φ a) (fderiv ℂ Φ a w) := by + exact SeveralComplexVariables.leviForm_comp_analytic hg hΦ w + +omit [FiniteDimensional ℂ E] in +/-- **64. Independence of the defining function**: the Levi condition may be tested on one local +defining function. -/ +theorem isLeviPseudoconvexAt_iff_of_defining {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + (h : IsLocalDefiningFunction U p ρ V) : + IsLeviPseudoconvexAt U p ↔ ∀ w, IsComplexTangent ρ p w → 0 ≤ leviForm ρ p w := by + rw [isLeviPseudoconvexAt_iff] + exact SeveralComplexVariables.isLeviPseudoconvexAt_iff_of_defining + (isLocalDefiningFunction_iff.mp h) + +/-- **64. Local peak functions** at strictly Levi pseudoconvex boundary points. -/ +theorem exists_local_peak_function {U : Set E} {p : E} {ρ : E → ℝ} {V : Set E} + (h : IsLocalDefiningFunction U p ρ V) + (hstrict : ∀ w, IsComplexTangent ρ p w → w ≠ 0 → 0 < leviForm ρ p w) : + ∃ W ∈ 𝓝 p, ∃ f : E → ℂ, AnalyticOnNhd ℂ f univ ∧ f p = 1 ∧ + ∀ z ∈ W, z ≠ p → ρ z ≤ 0 → ‖f z‖ < 1 := by + exact (isLocalDefiningFunction_iff.mp h).exists_peak hstrict + +/-! ## K. Runge domains and polynomial hulls -/ + +/-- The polynomial hull of `K`. -/ +def polynomialHull {n : ℕ} (K : Set (Fin n → ℂ)) : Set (Fin n → ℂ) := + {z | ∀ P : MvPolynomial (Fin n) ℂ, ∀ M : ℝ, + (∀ w ∈ K, ‖MvPolynomial.eval w P‖ ≤ M) → ‖MvPolynomial.eval z P‖ ≤ M} + +/-- `U` is a Runge domain: holomorphic functions on `U` are approximated by polynomials, uniformly +on compact subsets. -/ +def IsRungeDomain {n : ℕ} (U : Set (Fin n → ℂ)) : Prop := + ∀ f : (Fin n → ℂ) → ℂ, AnalyticOnNhd ℂ f U → ∀ K : Set (Fin n → ℂ), IsCompact K → K ⊆ U → + ∀ ε > 0, ∃ P : MvPolynomial (Fin n) ℂ, ∀ z ∈ K, ‖f z - MvPolynomial.eval z P‖ < ε + +/-- **65. Runge domains**: open complete Reinhardt sets are Runge domains, and in a Runge domain the +polynomial hull of a compact subset meets the domain in its holomorphic hull. -/ +theorem runge_domains {n : ℕ} {U : Set (Fin n → ℂ)} (ho : IsOpen U) : + (IsCompleteReinhardt U → IsRungeDomain U) ∧ + (IsRungeDomain U → ∀ K, IsCompact K → K ⊆ U → + polynomialHull K ∩ U = holomorphicHull U K) := by + refine ⟨fun hc => SeveralComplexVariables.IsCompleteReinhardt.isRungeDomain ho hc, + fun h K hK hKU => ?_⟩ + have h' : SeveralComplexVariables.IsRungeDomain U := h + exact h'.polynomialHull_inter hK hKU + +end SCV + +/- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index 95e0c8ad83..f7cf11b399 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -9966,3 +9966,39 @@ projects: msc: - '90C35' - '05C21' + - slug: lean-scv + title: Classical several complex variables + summary: Formalizes Cauchy and Taylor theory, Hartogs phenomena, removable singularities, analytic sets + and germs, Weierstrass theory, holomorphic convexity, Cartan–Thullen and Bochner tube theorems, plurisubharmonic + functions, Levi convexity, and elementary Runge-domain theory. + branch: complex analysis + entry_module: LeanPool.SeveralComplexVariables + authors: + - Bastiaan J Braams + source: + url: https://github.com/bjbraams/lean-scv + github_repo: bjbraams/lean-scv + commit: caef1ae776ff79933718312357980d46628d3702 + license: Apache-2.0 + status: verified + provenance: AI + main_declarations: + - SCV.cauchy_formula_polydisc + - SCV.osgood + - SCV.identity_theorem + main_results: + - declaration: SCV.cauchy_formula_polydisc + informal: Holomorphic functions on a polydisc satisfy the iterated Cauchy integral formula. + - declaration: SCV.osgood + informal: Locally bounded separately holomorphic functions are jointly holomorphic. + - declaration: SCV.identity_theorem + informal: Holomorphic functions on a connected domain that agree on a nonempty open subset agree throughout + the domain. + tags: + - complex-analysis + - several-complex-variables + - holomorphic-functions + msc: + - 32A10 + - 32D05 + - 32E10 From 33d31760f09b0c03b0934afb4ffbc1e50addb1c0 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Mon, 21 Sep 2026 18:50:59 +0000 Subject: [PATCH 2/5] Port full several complex variables library and clear scoped checks --- .../SeveralComplexVariables/AnalyticGerm.lean | 7 +- .../AnalyticGerm/CoefficientPolynomial.lean | 24 ++- .../AnalyticGerm/CoordinateChange.lean | 4 +- .../AnalyticGerm/Noetherian.lean | 6 +- .../AnalyticGerm/Weierstrass.lean | 12 +- .../AnalyticSet/Holomorphic.lean | 9 +- .../CauchyRiemann.lean | 5 +- .../SeveralComplexVariables/Circular.lean | 4 +- .../CommonExtension.lean | 2 +- .../SeveralComplexVariables/CompactHole.lean | 2 +- .../SeveralComplexVariables/Derivatives.lean | 76 +++++++-- .../DomainOfHolomorphy.lean | 2 +- .../HartogsExtension.lean | 6 +- .../InjectiveMapping/CriticalSet.lean | 4 +- .../LeviConvexity.lean | 2 +- .../LeviConvexity/Peak.lean | 2 +- .../LocallyUniform.lean | 10 ++ .../Plurisubharmonic.lean | 2 +- .../PolynomialDerivatives.lean | 4 +- .../Pseudoconvexity.lean | 6 +- .../Reinhardt/Extension.lean | 73 ++++++--- .../Reinhardt/Hull.lean | 27 +++- .../Reinhardt/MonomialSeparation.lean | 18 ++- .../Reinhardt/PartialHull.lean | 4 +- .../RemovableSingularity.lean | 2 +- .../SeparateAnalytic.lean | 4 +- .../SeparateAnalytic/FiberExtension.lean | 2 +- .../SeveralComplexVariables/Subharmonic.lean | 2 +- .../SeveralComplexVariables/TubeDomain.lean | 4 +- .../TubeDomain/Basic.lean | 2 +- .../WeierstrassDivision.lean | 14 +- .../WeierstrassDivision/Basic.lean | 7 +- .../WeierstrassDivision/CoordinatePower.lean | 151 +++++++++++------- .../WeierstrassDivision/Picard.lean | 16 +- .../WeierstrassPreparation.lean | 2 +- .../SeveralComplexVariables/Solution.lean | 16 +- 36 files changed, 359 insertions(+), 174 deletions(-) diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean index 6ccbe0ff3f..bb74e71fe2 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm.lean @@ -72,7 +72,6 @@ namespace SeveralComplexVariables variable {𝕜 E : Type*} [NontriviallyNormedField 𝕜] [NormedAddCommGroup E] [NormedSpace 𝕜 E] variable (𝕜) in - /-- The subring of germs admitting a representative analytic at the base point. -/ @[expose] def analyticGermSubring (x : E) : Subring (Germ (𝓝 x) 𝕜) where carrier := {φ | ∃ f : E → 𝕜, AnalyticAt 𝕜 f x ∧ (f : Germ (𝓝 x) 𝕜) = φ} @@ -144,7 +143,7 @@ theorem ofAnalyticAt_sum {κ : Type*} (s : Finset κ) (f : κ → E → 𝕜) (hf : ∀ i, AnalyticAt 𝕜 (f i) x) (hs : AnalyticAt 𝕜 (∑ i ∈ s, f i) x) : ofAnalyticAt (∑ i ∈ s, f i) hs = ∑ i ∈ s, ofAnalyticAt (f i) (hf i) := by apply Subtype.ext - show ((∑ i ∈ s, f i : E → 𝕜) : Germ (𝓝 x) 𝕜) = + change ((∑ i ∈ s, f i : E → 𝕜) : Germ (𝓝 x) 𝕜) = ((∑ i ∈ s, ofAnalyticAt (f i) (hf i) : AnalyticGerm 𝕜 x) : Germ (𝓝 x) 𝕜) rw [AddSubmonoidClass.coe_finsetSum] exact map_sum (Filter.Germ.coeRingHom (𝓝 x)) f s @@ -233,7 +232,7 @@ def pullbackOfEq (f : E → F) (hf : AnalyticAt 𝕜 f x) {y : F} (hy : f x = y) /-- Pullback by the identity fixes every analytic germ. -/ @[simp] theorem pullback_id (φ : AnalyticGerm 𝕜 x) : - pullback id analyticAt_id φ = φ := by + pullback (fun y : E => y) analyticAt_id φ = φ := by obtain ⟨f, hf, rfl⟩ := exists_rep φ rfl @@ -281,7 +280,7 @@ instance : IsLocalRing (AnalyticGerm 𝕜 x) where · exact Or.inl ha /-- The unique maximal ideal consists precisely of germs vanishing at the base point. -/ -@[simp] theorem mem_maximalIdeal_iff (φ : AnalyticGerm 𝕜 x) : +theorem mem_maximalIdeal_iff (φ : AnalyticGerm 𝕜 x) : φ ∈ IsLocalRing.maximalIdeal (AnalyticGerm 𝕜 x) ↔ eval x φ = 0 := by simp [IsLocalRing.mem_maximalIdeal, mem_nonunits_iff, isUnit_iff] diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean index dda938030f..169c0a9bbe 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoefficientPolynomial.lean @@ -48,35 +48,41 @@ public noncomputable section namespace SeveralComplexVariables.AnalyticGerm open Filter -open scoped Topology Classical +open scoped Topology variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] +open Classical in /-- The monic polynomial in `X` of degree `d` with prescribed coefficient germs below `d`. -/ @[expose] def ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : Polynomial (AnalyticGerm ℂ (0 : E)) := Polynomial.X ^ d + Polynomial.ofFn d b +open Classical in /-- The lower-degree part of `ofCoefficients` has degree strictly below `d`. -/ theorem degree_sum_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : (∑ j : Fin d, Polynomial.C (b j) * Polynomial.X ^ (j : ℕ)).degree < (d : WithBot ℕ) := Polynomial.degree_sum_fin_lt b +open Classical in /-- The distinguished-shape polynomial built from coefficient germs is monic. -/ theorem monic_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : (ofCoefficients b).Monic := Polynomial.monic_X_pow_add (Polynomial.ofFn_degree_lt b) +open Classical in /-- The distinguished-shape polynomial built from coefficient germs has degree `d`. -/ theorem natDegree_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : (ofCoefficients b).natDegree = d := Polynomial.natDegree_X_pow_add_ofFn b +open Classical in /-- Coefficients of `ofCoefficients` below `d` recover the prescribed germs. -/ theorem coeff_ofCoefficients_of_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) {i : ℕ} (hi : i < d) : (ofCoefficients b).coeff i = b ⟨i, hi⟩ := Polynomial.coeff_X_pow_add_ofFn_of_lt b hi +open Classical in /-- The distinguished-shape polynomial is distinguished when its coefficients vanish at the parameter origin. -/ theorem isDistinguishedAt_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) @@ -88,6 +94,7 @@ theorem isDistinguishedAt_ofCoefficients {d : ℕ} (b : Fin d → AnalyticGerm rw [coeff_ofCoefficients_of_lt b hi] exact hb _ +open Classical in /-- Any monic polynomial of degree `d` is the distinguished-shape polynomial built from its own coefficients. -/ theorem eq_ofCoefficients_of_monic {w : Polynomial (AnalyticGerm ℂ (0 : E))} {d : ℕ} @@ -96,6 +103,7 @@ theorem eq_ofCoefficients_of_monic {w : Polynomial (AnalyticGerm ℂ (0 : E))} { subst hd exact hm.eq_X_pow_add_ofFn +open Classical in /-- Evaluating the distinguished-shape polynomial in the last coordinate gives the Weierstrass polynomial built from analytic representatives of the coefficient germs. -/ theorem polynomialHom_ofCoefficients {d : ℕ} (a : Fin d → E → ℂ) @@ -114,7 +122,7 @@ theorem polynomialHom_ofCoefficients {d : ℕ} (a : Fin d → E → ℂ) (((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) := by intro j have hpar := pullback_ofAnalyticAt Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (a j) (ha j) - show pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * + change pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = _ rw [hpar, ← ofAnalyticAt_pow, ofAnalyticAt_mul] rw [Finset.sum_congr rfl (fun j _ => hstep j), @@ -126,6 +134,7 @@ theorem polynomialHom_ofCoefficients {d : ℕ} (a : Fin d → E → ℂ) funext z simp [weierstrassPolynomial, weierstrassRemainder, Function.comp] +open Classical in /-- A distinguished polynomial's image is regular of order equal to its degree: the Weierstrass polynomial built from representatives of its coefficients has central slice `t ↦ t ^ d`, whose order at the origin is exactly `d`. -/ @@ -152,19 +161,22 @@ theorem orderInLastVariable_polynomialHom_of_isDistinguishedAt have hcentral : (fun t : ℂ => weierstrassPolynomial a0 (0, t)) = fun t : ℂ => t ^ d := funext (weierstrassPolynomial_central ha00) rw [hcentral] - show analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d + change analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d rw [analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ)) d, analyticOrderAt_id] simp +open Classical in /-- The polynomial in `X` of degree below `d` with prescribed coefficient germs. -/ @[expose] def remainderOfCoefficients {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : Polynomial (AnalyticGerm ℂ (0 : E)) := Polynomial.ofFn d b +open Classical in /-- The remainder-shape polynomial has degree strictly below `d`. -/ theorem degree_remainderOfCoefficients_lt {d : ℕ} (b : Fin d → AnalyticGerm ℂ (0 : E)) : (remainderOfCoefficients b).degree < (d : WithBot ℕ) := Polynomial.ofFn_degree_lt b +open Classical in /-- Any polynomial of degree below `d` is the remainder-shape polynomial built from its own coefficients. -/ theorem eq_remainderOfCoefficients_of_degree_lt {r : Polynomial (AnalyticGerm ℂ (0 : E))} {d : ℕ} @@ -172,6 +184,7 @@ theorem eq_remainderOfCoefficients_of_degree_lt {r : Polynomial (AnalyticGerm r = remainderOfCoefficients (fun j : Fin d => r.coeff (j : ℕ)) := (Polynomial.ofFn_toFn_eq_of_degree_lt hr).symm +open Classical in /-- Evaluating the remainder-shape polynomial in the last coordinate gives the Weierstrass remainder built from analytic representatives of the coefficient germs. -/ theorem polynomialHom_remainderOfCoefficients {d : ℕ} (a : Fin d → E → ℂ) @@ -190,7 +203,7 @@ theorem polynomialHom_remainderOfCoefficients {d : ℕ} (a : Fin d → E → ℂ (((ha j).comp_of_eq hfst rfl).mul (hsnd.pow (j : ℕ))) := by intro j have hpar := pullback_ofAnalyticAt Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (a j) (ha j) - show pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * + change pullback Prod.fst (analyticAt_fst (p := (0 : E × ℂ))) (ofAnalyticAt (a j) (ha j)) * ofAnalyticAt Prod.snd hsnd ^ (j : ℕ) = _ rw [hpar, ← ofAnalyticAt_pow, ofAnalyticAt_mul] rw [Finset.sum_congr rfl (fun j _ => hstep j), @@ -201,11 +214,13 @@ theorem polynomialHom_remainderOfCoefficients {d : ℕ} (a : Fin d → E → ℂ funext z simp [weierstrassRemainder, Function.comp] +open Classical in /-- `remainderOfCoefficients` is additive in the coefficient tuple. -/ theorem remainderOfCoefficients_add {d : ℕ} (a b : Fin d → AnalyticGerm ℂ (0 : E)) : remainderOfCoefficients (a + b) = remainderOfCoefficients a + remainderOfCoefficients b := map_add (Polynomial.ofFn d) a b +open Classical in /-- `remainderOfCoefficients` scales by a constant-polynomial factor under a common germ multiplier on the coefficient tuple. -/ theorem remainderOfCoefficients_smul {d : ℕ} (c : AnalyticGerm ℂ (0 : E)) @@ -214,6 +229,7 @@ theorem remainderOfCoefficients_smul {d : ℕ} (c : AnalyticGerm ℂ (0 : E)) simpa only [remainderOfCoefficients, Polynomial.smul_eq_C_mul] using (Polynomial.ofFn d).map_smul c a +open Classical in /-- `remainderOfCoefficients` commutes with finite sums of coefficient tuples. -/ theorem remainderOfCoefficients_sum {d : ℕ} {ι : Type*} (s : Finset ι) (v : ι → Fin d → AnalyticGerm ℂ (0 : E)) : diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean index 5afa855a06..448c0bb10b 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/CoordinateChange.lean @@ -233,11 +233,13 @@ theorem exists_regular_coordinate_change [FiniteDimensional ℂ E] regular in the last variable. Empty families and unit germs are allowed. Apply single-germ normalization to the product, then use that no factor slice can vanish. -/ theorem exists_regular_coordinate_change_finite [FiniteDimensional ℂ E] - {κ : Type*} [Fintype κ] {f : κ → E × ℂ → ℂ} + {κ : Type*} [Finite κ] {f : κ → E × ℂ → ℂ} (hf : ∀ i, AnalyticAt ℂ (f i) 0) (hne : ∀ i, ¬ f i =ᶠ[𝓝 0] 0) : ∃ (L : (E × ℂ) ≃L[ℂ] (E × ℂ)) (d : κ → ℕ), ∀ i, analyticOrderAt (fun w : ℂ => f i (L (0, w))) 0 = d i := by classical + let := Fintype.ofFinite κ + classical have hp : ∀ s : Finset κ, ¬ (fun z => ∏ i ∈ s, f i z) =ᶠ[𝓝 0] 0 := by intro s induction s using Finset.induction_on with diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean index 04bf478ef7..c17e9a2b6b 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Noetherian.lean @@ -59,7 +59,7 @@ theorem ideal_fg_of_orderInLastVariable_eq_nat [FiniteDimensional ℂ E] let M : Submodule (AnalyticGerm ℂ (0 : E)) (Fin d → AnalyticGerm ℂ (0 : E)) := { carrier := {a | polynomialHom (remainderOfCoefficients a) ∈ J} zero_mem' := by - show polynomialHom (remainderOfCoefficients 0) ∈ J + change polynomialHom (remainderOfCoefficients 0) ∈ J simp [remainderOfCoefficients] add_mem' := by intro a b ha hb @@ -80,7 +80,7 @@ theorem ideal_fg_of_orderInLastVariable_eq_nat [FiniteDimensional ℂ E] Finset.mem_coe] at hx rcases hx with rfl | ⟨a, haS, rfl⟩ · exact hgJ - · show a ∈ M + · change a ∈ M rw [← hS] exact Submodule.subset_span haS · intro h hhJ @@ -95,7 +95,7 @@ theorem ideal_fg_of_orderInLastVariable_eq_nat [FiniteDimensional ℂ E] have har : r = remainderOfCoefficients (fun j : Fin d => r.coeff (j : ℕ)) := eq_remainderOfCoefficients_of_degree_lt hrdeg have hmemM : (fun j : Fin d => r.coeff (j : ℕ)) ∈ M := by - show polynomialHom (remainderOfCoefficients _) ∈ J + change polynomialHom (remainderOfCoefficients _) ∈ J rwa [← har] rw [← hS] at hmemM obtain ⟨f, hf⟩ := Submodule.mem_span_finset'.mp hmemM diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean index 5900d50670..c3a41e66c0 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticGerm/Weierstrass.lean @@ -37,12 +37,14 @@ finite normalization theorem and the existing analytic preparation theorem. members of a finite family. -/ -public noncomputable section +public noncomputable +section open Filter open scoped Topology -namespace SeveralComplexVariables.AnalyticGerm +namespace SeveralComplexVariables +namespace AnalyticGerm variable {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] @@ -74,7 +76,7 @@ theorem existsUnique_division [FiniteDimensional ℂ E] have hcentral : (fun t : ℂ => weierstrassPolynomial a0 (0, t)) = fun t : ℂ => t ^ d := funext (weierstrassPolynomial_central ha00) rw [hcentral] - show analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d + change analyticOrderAt ((id : ℂ → ℂ) ^ d) 0 = d rw [analyticOrderAt_pow (analyticAt_id (𝕜 := ℂ)) d, analyticOrderAt_id]; simp obtain ⟨f0, hf0, rfl⟩ := exists_rep f obtain ⟨q, a, Hdiv, huniqdiv⟩ := @@ -406,12 +408,14 @@ end AnalyticGerm /-- One coordinate system permits preparation of all members of a finite family. This depends on the preparation theorem and hence on analytic division. Empty parameter types, empty families, and unit germs are all included. -/ -theorem exists_equiv_forall_isWeierstrassPreparationAt {ι κ : Type*} [Fintype ι] [Fintype κ] +theorem exists_equiv_forall_isWeierstrassPreparationAt {ι κ : Type*} [Fintype ι] [Finite κ] {f : κ → (ι → ℂ) × ℂ → ℂ} (hf : ∀ i, AnalyticAt ℂ (f i) 0) (hne : ∀ i, ¬ f i =ᶠ[𝓝 0] 0) : ∃ (L : ((ι → ℂ) × ℂ) ≃L[ℂ] ((ι → ℂ) × ℂ)) (d : κ → ℕ), ∀ i, ∃ (u : (ι → ℂ) × ℂ → ℂ) (a : Fin (d i) → (ι → ℂ) → ℂ), IsWeierstrassPreparationAt (fun z => f i (L z)) u a := by + classical + let := Fintype.ofFinite κ obtain ⟨L, d, hd⟩ := exists_regular_coordinate_change_finite hf hne refine ⟨L, d, fun i => ?_⟩ have ha : AnalyticAt ℂ (fun z => f i (L z)) 0 := diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean index 6b5c572bd0..e9ec130fab 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet/Holomorphic.lean @@ -49,10 +49,13 @@ variable {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] /-- Holomorphic finite-coordinate equations on an open finite-dimensional domain define an analytic subset, using Mathlib's equivalence of holomorphy and analyticity. -/ theorem isAnalyticSet_zeroSet_pi_of_differentiableOn [FiniteDimensional ℂ E] - {ι : Type*} [Fintype ι] {U : Set E} (hU : IsOpen U) + {ι : Type*} [Finite ι] {U : Set E} (hU : IsOpen U) {f : E → (ι → ℂ)} (hf : DifferentiableOn ℂ f U) : - IsAnalyticSet U (U ∩ f ⁻¹' {0}) := - isAnalyticSet_zeroSet_pi hU (hf.analyticOnNhd_of_finiteDimensional hU) + IsAnalyticSet U (U ∩ f ⁻¹' {0}) := by + classical + let := Fintype.ofFinite ι + exact + isAnalyticSet_zeroSet_pi hU (hf.analyticOnNhd_of_finiteDimensional hU) /-- Biholomorphic changes of ambient coordinates preserve analytic subsets. -/ theorem IsAnalyticSet.image_biholomorphic [FiniteDimensional ℂ E] [FiniteDimensional ℂ F] diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean index 457cdca800..869d5f460a 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CauchyRiemann.lean @@ -56,13 +56,16 @@ variable {ι F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [No @[expose] def conjWirtingerDeriv (i : ι) (f : (ι → ℂ) → F) (z : ι → ℂ) : F := (1 / 2 : ℂ) • (fderiv ℝ f z (Pi.single i 1) + I • fderiv ℝ f z (Pi.single i I)) +omit [Fintype ι] in /-- The real derivative of a coordinate slice is the restriction of the real derivative to that coordinate's complex plane. -/ -theorem hasFDerivAt_update_real {f : (ι → ℂ) → F} (z : ι → ℂ) (i : ι) (w : ℂ) +theorem hasFDerivAt_update_real [Finite ι] {f : (ι → ℂ) → F} (z : ι → ℂ) (i : ι) (w : ℂ) (hf : DifferentiableAt ℝ f (update z i w)) : HasFDerivAt (fun v => f (update z i v)) ((fderiv ℝ f (update z i w)).comp ((ContinuousLinearMap.single ℂ (fun _ : ι => ℂ) i).restrictScalars ℝ)) w := by + classical + let := Fintype.ofFinite ι have hs : HasFDerivAt (update z i) ((ContinuousLinearMap.single ℂ (fun _ : ι => ℂ) i).restrictScalars ℝ) w := by convert! (hasDerivAt_update z i w).hasFDerivAt.restrictScalars ℝ using 1 diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean index 7e904b2791..292f9d7ce3 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Circular.lean @@ -107,8 +107,10 @@ theorem IsReinhardt.isCircular {ι : Type*} [Fintype ι] {U : Set (ι → ℂ)} exact hU hz (fun i => by simp [hc]) /-- Complete Reinhardt sets are balanced for complex scalar multiplication. -/ -theorem IsCompleteReinhardt.balanced {ι : Type*} [Fintype ι] {U : Set (ι → ℂ)} +theorem IsCompleteReinhardt.balanced {ι : Type*} [Finite ι] {U : Set (ι → ℂ)} (hU : IsCompleteReinhardt U) : Balanced ℂ U := by + classical + let := Fintype.ofFinite ι rw [balanced_iff_smul_mem] intro c hc z hz apply hU hz diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean index a814576b6c..64fb8568c0 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CommonExtension.lean @@ -118,7 +118,7 @@ theorem IsCommonAnalyticExtension.image_eq {U V : Set E} (h : IsCommonAnalyticEx /-- A common extension domain lies in the real convex hull of the original domain. The proof uses real convex separation, complexification of the separating functional, and preservation of omitted values. This assertion involves no abstract envelopes. -/ -theorem IsCommonAnalyticExtension.subset_convexHull [FiniteDimensional ℂ E] +theorem IsCommonAnalyticExtension.subset_convexHull {U V : Set E} (h : IsCommonAnalyticExtension U V) (ho : IsOpen U) (hne : U.Nonempty) (hc : IsPreconnected V) : V ⊆ convexHull ℝ U := by intro z hz diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean index 9ea9888b92..a3dbcd1689 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/CompactHole.lean @@ -361,7 +361,7 @@ theorem exists_analyticOnNhd_extension_of_isCompact_prod {D K : Set (ℂ × G)} dbarExt_holeCutoff_eq_zero h hf e₁ fun hc => hx.2 ⟨(z, x.2), hc, rfl⟩ have := cauchyTransformFst_eq_zero hz x.1 simpa using this - show F₀ x - u x = f x + change F₀ x - u x = f x rw [hF, hu0, sub_zero] refine ⟨g, hga, ?_⟩ exact (hga.mono sdiff_subset).eqOn_of_preconnected_of_eventuallyEq hf hconn (hVsub hx₀) diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean index 0cd799c6c5..f9d8199d59 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Derivatives.lean @@ -46,22 +46,32 @@ nontrivially normed field; the several-complex-variables theory uses `𝕜 = ℂ @[expose] def partialDeriv (i : ι) (f : (ι → 𝕜) → F) (z : ι → 𝕜) : F := deriv (fun w => f (update z i w)) (z i) +omit [Fintype ι] in /-- The derivative of a coordinate slice is the corresponding Fréchet derivative value. -/ -theorem hasDerivAt_update_of_differentiableAt {f : (ι → 𝕜) → F} {z : ι → 𝕜} +theorem hasDerivAt_update_of_differentiableAt [Finite ι] {f : (ι → 𝕜) → F} {z : ι → 𝕜} (hf : DifferentiableAt 𝕜 f z) (i : ι) : HasDerivAt (fun w => f (update z i w)) (fderiv 𝕜 f z (Pi.single i 1)) (z i) := by + classical + let := Fintype.ofFinite ι have hf' : HasFDerivAt f (fderiv 𝕜 f z) (update z i (z i)) := by simpa using hf.hasFDerivAt exact hf'.comp_hasDerivAt (z i) (hasDerivAt_update z i (z i)) +omit [Fintype ι] in /-- Coordinate derivatives are Fréchet derivatives evaluated on coordinate vectors. -/ -theorem partialDeriv_eq_fderiv {f : (ι → 𝕜) → F} {z : ι → 𝕜} +theorem partialDeriv_eq_fderiv [Finite ι] {f : (ι → 𝕜) → F} {z : ι → 𝕜} (hf : DifferentiableAt 𝕜 f z) (i : ι) : - partialDeriv i f z = fderiv 𝕜 f z (Pi.single i 1) := - (hasDerivAt_update_of_differentiableAt hf i).deriv + partialDeriv i f z = fderiv 𝕜 f z (Pi.single i 1) := by + classical + let := Fintype.ofFinite ι + exact + (hasDerivAt_update_of_differentiableAt hf i).deriv +omit [Fintype ι] in /-- A coordinate derivative only depends on the germ of the function. -/ -theorem partialDeriv_congr {f g : (ι → 𝕜) → F} {z : ι → 𝕜} +theorem partialDeriv_congr [Finite ι] {f g : (ι → 𝕜) → F} {z : ι → 𝕜} (hfg : f =ᶠ[𝓝 z] g) (i : ι) : partialDeriv i f z = partialDeriv i g z := by + classical + let := Fintype.ofFinite ι apply Filter.EventuallyEq.deriv_eq have ht : Tendsto (update z i) (𝓝 (z i)) (𝓝 z) := by simpa using (hasDerivAt_update z i (z i)).continuousAt.tendsto @@ -76,27 +86,36 @@ theorem fderiv_eq_sum_partialDeriv {f : (ι → 𝕜) → F} {z : ι → 𝕜} ext j simp [Pi.single_apply] +omit [Fintype ι] in /-- Coordinate differentiation respects subtraction at differentiability points. -/ -theorem partialDeriv_sub {f g : (ι → 𝕜) → F} {z : ι → 𝕜} +theorem partialDeriv_sub [Finite ι] {f g : (ι → 𝕜) → F} {z : ι → 𝕜} (hf : DifferentiableAt 𝕜 f z) (hg : DifferentiableAt 𝕜 g z) (i : ι) : partialDeriv i (f - g) z = partialDeriv i f z - partialDeriv i g z := by + classical + let := Fintype.ofFinite ι exact deriv_sub (hasDerivAt_update_of_differentiableAt hf i).differentiableAt (hasDerivAt_update_of_differentiableAt hg i).differentiableAt +omit [Fintype ι] in /-- Coordinate differentiation of a product of scalar functions follows the ordinary product rule, holding the other coordinates fixed. -/ -theorem partialDeriv_mul {f g : (ι → 𝕜) → 𝕜} {z : ι → 𝕜} +theorem partialDeriv_mul [Finite ι] {f g : (ι → 𝕜) → 𝕜} {z : ι → 𝕜} (hf : DifferentiableAt 𝕜 f z) (hg : DifferentiableAt 𝕜 g z) (i : ι) : partialDeriv i (f * g) z = partialDeriv i f z * g z + f z * partialDeriv i g z := by + classical + let := Fintype.ofFinite ι have hf' := hasDerivAt_update_of_differentiableAt hf i have hg' := hasDerivAt_update_of_differentiableAt hg i have h := deriv_fun_mul hf'.differentiableAt hg'.differentiableAt simpa [partialDeriv, update_eq_self] using h +omit [Fintype ι] in /-- Coordinate differentiation commutes with a finite sum of differentiable functions. -/ -theorem partialDeriv_finset_sum {α : Type*} {f : α → (ι → 𝕜) → F} +theorem partialDeriv_finset_sum [Finite ι] {α : Type*} {f : α → (ι → 𝕜) → F} (t : Finset α) {z : ι → 𝕜} (hf : ∀ a ∈ t, DifferentiableAt 𝕜 (f a) z) (i : ι) : partialDeriv i (fun w => ∑ a ∈ t, f a w) z = ∑ a ∈ t, partialDeriv i (f a) z := by + classical + let := Fintype.ofFinite ι exact deriv_fun_sum fun a ha => (hasDerivAt_update_of_differentiableAt (hf a ha) i).differentiableAt @@ -183,10 +202,13 @@ theorem iteratedPartialDeriv_perm {U : Set (ι → ℂ)} {f : (ι → ℂ) → F | trans h₁ h₂ ih₁ ih₂ => exact ih₁.trans ih₂ omit [CompleteSpace F] in +omit [Fintype ι] in /-- Iterated coordinate derivatives agree on an open set where the original functions agree. -/ -theorem iteratedPartialDeriv_congrOn {U : Set (ι → ℂ)} {f g : (ι → ℂ) → F} +theorem iteratedPartialDeriv_congrOn [Finite ι] {U : Set (ι → ℂ)} {f g : (ι → ℂ) → F} (hU : IsOpen U) (hfg : EqOn f g U) (is : List ι) : EqOn (iteratedPartialDeriv is f) (iteratedPartialDeriv is g) U := by + classical + let := Fintype.ofFinite ι induction is with | nil => exact hfg | cons i is ih => @@ -242,12 +264,16 @@ private theorem sum_choose_shift (k : ℕ) (X : ℕ → ℂ) : rw [Finset.sum_congr rfl hexpand, Finset.sum_add_distrib, hstep1] ring +omit [Fintype ι] in /-- Coordinate differentiation of a scalar multiple follows the ordinary constant-multiple rule, holding the other coordinates fixed. -/ -theorem partialDeriv_const_mul {f : (ι → ℂ) → ℂ} {z : ι → ℂ} (c : ℂ) +theorem partialDeriv_const_mul [Finite ι] {f : (ι → ℂ) → ℂ} {z : ι → ℂ} (c : ℂ) (hf : DifferentiableAt ℂ f z) (i : ι) : - partialDeriv i (fun w => c * f w) z = c * partialDeriv i f z := - deriv_const_mul c (hasDerivAt_update_of_differentiableAt hf i).differentiableAt + partialDeriv i (fun w => c * f w) z = c * partialDeriv i f z := by + classical + let := Fintype.ofFinite ι + exact + deriv_const_mul c (hasDerivAt_update_of_differentiableAt hf i).differentiableAt /-- Repeated differentiation of a product of scalar functions in a single coordinate follows the ordinary Leibniz binomial rule, since each step is the ordinary product rule. -/ @@ -355,29 +381,40 @@ end MultiIndex @[expose] def complexJacobian {κ : Type*} (f : (ι → ℂ) → (κ → ℂ)) (z : ι → ℂ) : Matrix κ ι ℂ := fun j i => partialDeriv i (fun w => f w j) z +omit [Fintype ι] in /-- Entries of the complex Jacobian are the coordinate entries of the Fréchet derivative. -/ -theorem complexJacobian_apply {κ : Type*} [Fintype κ] +theorem complexJacobian_apply [Finite ι] {κ : Type*} [Finite κ] {f : (ι → ℂ) → (κ → ℂ)} {z : ι → ℂ} (hf : DifferentiableAt ℂ f z) (j : κ) (i : ι) : complexJacobian f z j i = fderiv ℂ f z (Pi.single i 1) j := by + classical + let := Fintype.ofFinite ι + let := Fintype.ofFinite κ rw [complexJacobian, partialDeriv_eq_fderiv (differentiableAt_pi.mp hf j), fderiv_apply hf j] rfl omit [CompleteSpace F] in +omit [Fintype ι] in /-- The coordinate chain rule, with an arbitrary complex normed outer target. -/ -theorem partialDeriv_comp {κ : Type*} [Fintype κ] [DecidableEq κ] +theorem partialDeriv_comp [Finite ι] {κ : Type*} [Fintype κ] [DecidableEq κ] {f : (ι → ℂ) → (κ → ℂ)} {g : (κ → ℂ) → F} {z : ι → ℂ} (hg : DifferentiableAt ℂ g (f z)) (hf : DifferentiableAt ℂ f z) (i : ι) : partialDeriv i (g ∘ f) z = ∑ j, complexJacobian f z j i • partialDeriv j g (f z) := by + classical + let := Fintype.ofFinite ι rw [partialDeriv_eq_fderiv (hg.comp z hf), fderiv_comp z hg hf] simp only [ContinuousLinearMap.comp_apply] rw [fderiv_eq_sum_partialDeriv hg] simp_rw [complexJacobian_apply hf] +omit [Fintype ι] in /-- Jacobians compose by matrix multiplication. -/ -theorem complexJacobian_comp {κ ν : Type*} [Fintype κ] [DecidableEq κ] [Fintype ν] +theorem complexJacobian_comp [Finite ι] {κ ν : Type*} [Fintype κ] [DecidableEq κ] [Finite ν] {f : (ι → ℂ) → (κ → ℂ)} {g : (κ → ℂ) → (ν → ℂ)} {z : ι → ℂ} (hg : DifferentiableAt ℂ g (f z)) (hf : DifferentiableAt ℂ f z) : complexJacobian (g ∘ f) z = complexJacobian g (f z) * complexJacobian f z := by + classical + let := Fintype.ofFinite ι + let := Fintype.ofFinite ν ext j i change partialDeriv i ((fun w => g w j) ∘ f) z = _ rw [partialDeriv_comp (differentiableAt_pi.mp hg j) hf] @@ -385,14 +422,19 @@ theorem complexJacobian_comp {κ ν : Type*} [Fintype κ] [DecidableEq κ] [Fint /-- The complex Jacobian is Mathlib's matrix of the complex Fréchet derivative in the standard coordinate bases. -/ -theorem complexJacobian_eq_toMatrix {κ : Type*} [Fintype κ] +theorem complexJacobian_eq_toMatrix {κ : Type*} [Finite κ] {f : (ι → ℂ) → (κ → ℂ)} {z : ι → ℂ} (hf : DifferentiableAt ℂ f z) : complexJacobian f z = LinearMap.toMatrix' (fderiv ℂ f z).toLinearMap := by + classical + let := Fintype.ofFinite κ ext j i exact complexJacobian_apply hf j i +omit [Fintype ι] in /-- The Jacobian of the identity map is the identity matrix, including with no coordinates. -/ -theorem complexJacobian_id (z : ι → ℂ) : complexJacobian id z = 1 := by +theorem complexJacobian_id [Finite ι] (z : ι → ℂ) : complexJacobian id z = 1 := by + classical + let := Fintype.ofFinite ι rw [complexJacobian_eq_toMatrix differentiableAt_id] simp diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean index c642bd59fe..b235c44c89 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/DomainOfHolomorphy.lean @@ -204,7 +204,7 @@ theorem isDomainOfHolomorphy_pi {ι : Type*} [Fintype ι] (S : ι → Set ℂ) : /-- Every real-convex open subset of a finite-dimensional complex normed space is a domain of holomorphy. A separating real functional is complexified to give a pole. -/ -theorem isDomainOfHolomorphy_of_convex [FiniteDimensional ℂ E] {U : Set E} +theorem isDomainOfHolomorphy_of_convex {U : Set E} (hU : Convex ℝ U) (ho : IsOpen U) : IsDomainOfHolomorphy U := by apply isDomainOfHolomorphy_of_entire_separators intro a ha diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean index da43984173..c5f22d1fe6 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean @@ -99,7 +99,9 @@ figure-extension statement needs no positive-dimensional base assumption. -/ theorem hartogsFigure_eq_of_isEmpty [IsEmpty ι] {r : ℝ} (hr : 0 < r) (s : ℝ) : hartogsFigure (ι := ι) r s = ball 0 1 ×ˢ ball 0 1 := by ext z - simp [hartogsFigure, Subsingleton.elim z.1 (0 : ι → ℂ), hr] + simp only [hartogsFigure, mem_union, mem_prod, Subsingleton.elim z.1 (0 : ι → ℂ), + mem_ball, dist_self, hr, dist_zero_right, true_and, zero_lt_one, mem_sdiff, + mem_closedBall, not_le, or_iff_left_iff_imp, and_imp] exact fun h _ => h omit [CompleteSpace F] in @@ -174,7 +176,7 @@ theorem exists_analyticOnNhd_extension_of_isCompact obtain ⟨g', hg', hg'f⟩ := exists_analyticOnNhd_extension_of_isCompact_prod hD'o hK'c hK'D' hconn' hf' refine ⟨g' ∘ e, hg'.comp (e.toContinuousLinearMap.analyticOnNhd _) fun z hz => ?_, ?_⟩ - · show e.symm (e z) ∈ U + · change e.symm (e z) ∈ U simpa using hz · intro z hz have hz' : e z ∈ D' \ K' := by diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean index 5ea75dbf23..0c7fa22530 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/InjectiveMapping/CriticalSet.lean @@ -92,11 +92,13 @@ theorem analyticOnNhd_det_complexJacobian {ι : Type*} [Fintype ι] [DecidableEq exact ((analyticOnNhd_pi_iff.mp hf (σ i)).partialDeriv hU i) a ha /-- An injective holomorphic map between equal complex coordinate spaces has no critical points. -/ -theorem isInvertible_fderiv_of_injOn_coordinates {ι : Type*} [Fintype ι] +theorem isInvertible_fderiv_of_injOn_coordinates {ι : Type*} [Finite ι] {U : Set (ι → ℂ)} (hU : IsOpen U) {f : (ι → ℂ) → (ι → ℂ)} (hf : DifferentiableOn ℂ f U) (hi : InjOn f U) {a : ι → ℂ} (ha : a ∈ U) : (fderiv ℂ f a).IsInvertible := by classical + let := Fintype.ofFinite ι + classical obtain ⟨r, hr, hball⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds ha) let V := Metric.ball a r have haV : a ∈ V := Metric.mem_ball_self hr diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean index 76b81c9ab6..d7f890949b 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity.lean @@ -207,7 +207,7 @@ theorem IsLocalDefiningFunction.fderiv_fderiv_nonneg_of_convex (hU : IsOpen U) obtain ⟨δ₁, hδ₁, htaylor⟩ := exists_taylor_bound hgc (ε := -A / 4) (by linarith) obtain ⟨δ₂, hδ₂, hV⟩ := Metric.mem_nhds_iff.mp ((by fun_prop : Continuous fun t : ℂ => p + t • w).continuousAt.preimage_mem_nhds (by - show V ∈ 𝓝 ((fun t : ℂ => p + t • w) 0) + change V ∈ 𝓝 ((fun t : ℂ => p + t • w) 0) simpa using h.isOpen.mem_nhds h.mem)) have hD1 : fderiv ℝ g 0 = (fderiv ℝ ρ p).comp ((ContinuousLinearMap.id ℝ ℂ).smulRight w) := by have := fderiv_slice (f := ρ) (a := p) (w := w) (t₀ := 0) (hρp.differentiableAt (by norm_num)) diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean index 67035bec0c..7a5f08c530 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LeviConvexity/Peak.lean @@ -399,7 +399,7 @@ theorem IsLocalDefiningFunction.exists_holomorphic_support (h : IsLocalDefiningF have hsmall : ∀ᶠ z in 𝓝 p, |ρ z| < 1 / (A + 1) := by have hcont : ContinuousAt (fun z => |ρ z|) p := hρc.continuousAt.abs exact hcont.eventually (eventually_lt_nhds (by - show |ρ p| < 1 / (A + 1) + change |ρ p| < 1 / (A + 1) rw [h.eq_zero, abs_zero] positivity)) refine ⟨ball p δ ∩ {z | |ρ z| < 1 / (A + 1)}, inter_mem (ball_mem_nhds p hδ) hsmall, F, hFan, diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean index 26de2b762d..7c651c3dae 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/LocallyUniform.lean @@ -46,6 +46,7 @@ open Filter Set variable {ι κ F : Type*} [Fintype ι] [DecidableEq ι] [NormedAddCommGroup F] [NormedSpace ℂ F] [CompleteSpace F] +omit [DecidableEq ι] in /-- **Weierstrass convergence theorem, finite-coordinate form.** A locally uniform limit of analytic maps on an open subset of a finite complex coordinate space is analytic. -/ theorem TendstoLocallyUniformlyOn.analyticOnNhd_pi @@ -55,6 +56,7 @@ theorem TendstoLocallyUniformlyOn.analyticOnNhd_pi (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : AnalyticOnNhd ℂ g U := by classical + classical have hg : ContinuousOn g U := hlim.continuousOn (hf.frequently.mono fun _ hn => hn.continuousOn) apply SeveralComplexVariables.analyticOnNhd_pi_of_analyticOnNhd_update hU hg @@ -79,6 +81,7 @@ theorem TendstoLocallyUniformlyOn.analyticOnNhd_pi exact (hlim'.differentiableOn hfdiff hV).analyticAt (hV.mem_nhds (show update (z i) ∈ U by simpa [update] using hz)) +omit [DecidableEq ι] in /-- A locally uniformly convergent sum of analytic maps on an open finite complex coordinate space is analytic. -/ theorem HasSumLocallyUniformlyOn.analyticOnNhd_pi @@ -86,10 +89,12 @@ theorem HasSumLocallyUniformlyOn.analyticOnNhd_pi (hsum : HasSumLocallyUniformlyOn f g U) (hf : ∀ n, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : AnalyticOnNhd ℂ g U := by + classical apply TendstoLocallyUniformlyOn.analyticOnNhd_pi hsum _ hU filter_upwards with s exact Finset.analyticOnNhd_fun_sum s fun n _ ↦ hf n +omit [DecidableEq ι] in /-- A series of analytic maps is analytic when its terms admit a summable uniform majorant on every compact subset of the domain. -/ theorem analyticOnNhd_tsum_of_summable_norm_on_compacts @@ -98,6 +103,7 @@ theorem analyticOnNhd_tsum_of_summable_norm_on_compacts (hmajorant : ∀ K ⊆ U, IsCompact K → ∃ M : κ → ℝ, Summable M ∧ ∀ n x, x ∈ K → ‖f n x‖ ≤ M n) : AnalyticOnNhd ℂ (fun x ↦ ∑' n, f n x) U := by + classical have hs : SummableLocallyUniformlyOn f U := SummableLocallyUniformlyOn_of_locally_bounded hU hmajorant exact hs.hasSumLocallyUniformlyOn.analyticOnNhd_pi hf hU @@ -143,6 +149,7 @@ theorem TendstoLocallyUniformlyOn.iteratedPartialDeriv | cons i is ih => exact ih.partialDeriv (hf.mono fun n hn => hn.iteratedPartialDeriv hU is) hU i +omit [DecidableEq ι] in /-- Locally uniform convergence of holomorphic maps gives locally uniform convergence of their Fréchet derivatives in operator norm. -/ theorem TendstoLocallyUniformlyOn.fderiv_pi @@ -152,6 +159,7 @@ theorem TendstoLocallyUniformlyOn.fderiv_pi (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) : TendstoLocallyUniformlyOn (fun n => fderiv ℂ (f n)) (fderiv ℂ g) l U := by classical + classical let L (i : ι) : F →L[ℂ] ((ι → ℂ) →L[ℂ] F) := ContinuousLinearMap.smulRightL ℂ (ι → ℂ) F (ContinuousLinearMap.proj i) have hi (i : ι) := (L i).uniformContinuous.comp_tendstoLocallyUniformlyOn @@ -172,6 +180,7 @@ theorem TendstoLocallyUniformlyOn.fderiv_pi Inseparable.of_eq (heq (hn z hz).differentiableAt)) exact h.congr_right fun z hz => heq ((hlim.analyticOnNhd_pi hf hU) z hz).differentiableAt +omit [DecidableEq ι] in /-- All iterated Fréchet derivatives converge locally uniformly in multilinear operator norm. -/ theorem TendstoLocallyUniformlyOn.iteratedFDeriv_pi {U : Set (ι → ℂ)} {l : Filter κ} [l.NeBot] @@ -180,6 +189,7 @@ theorem TendstoLocallyUniformlyOn.iteratedFDeriv_pi (hf : ∀ᶠ n in l, AnalyticOnNhd ℂ (f n) U) (hU : IsOpen U) (k : ℕ) : TendstoLocallyUniformlyOn (fun n => iteratedFDeriv ℂ k (f n)) (iteratedFDeriv ℂ k g) l U := by + classical induction k with | zero => simpa only [iteratedFDeriv_zero_eq_comp] using diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean index cb6cb9ff1f..2fbff1f135 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Plurisubharmonic.lean @@ -201,7 +201,7 @@ theorem _root_.ConvexOn.plurisubharmonicOn (hU : IsOpen U) (hf : ConvexOn ℝ U refine ⟨hc.upperSemicontinuousOn, fun a ha w => ?_⟩ apply ConvexOn.subharmonicOn (hU.preimage (by fun_prop : Continuous fun t : ℂ => a + t • w)) · refine ⟨fun s hs t ht α β hα hβ hαβ => ?_, fun s hs t ht α β hα hβ hαβ => ?_⟩ - · show a + (α • s + β • t) • w ∈ U + · change a + (α • s + β • t) • w ∈ U rw [line_combo a w s t hαβ] exact hf.1 hs ht hα hβ hαβ · have := hf.2 hs ht hα hβ hαβ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean index d9797e7e16..c0510afb06 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/PolynomialDerivatives.lean @@ -42,8 +42,10 @@ theorem hasDerivAt_eval_update [DecidableEq ι] (p : MvPolynomial ι ℂ) (z : · simpa [pderiv_mul, h, Ne.symm h, mul_comm] using! hp.mul (hasDerivAt_const x (z j)) /-- Coordinate differentiation of a polynomial is evaluation of its formal derivative. -/ -theorem partialDeriv_eval [Fintype ι] [DecidableEq ι] (p : MvPolynomial ι ℂ) (z : ι → ℂ) (i : ι) : +theorem partialDeriv_eval [Finite ι] [DecidableEq ι] (p : MvPolynomial ι ℂ) (z : ι → ℂ) (i : ι) : SeveralComplexVariables.partialDeriv i (fun w => p.eval w) z = (pderiv i p).eval z := by + classical + let := Fintype.ofFinite ι simpa [SeveralComplexVariables.partialDeriv] using (p.hasDerivAt_eval_update z i (z i)).deriv end MvPolynomial diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean index 5ba74f4226..432660cd95 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Pseudoconvexity.lean @@ -189,7 +189,7 @@ theorem IsDomainOfHolomorphy.plurisubharmonicOn_neg_log_infDist {U : Set (Fin n obtain ⟨i, hi⟩ := Function.ne_iff.mp hw have hline : Continuous fun t : ℂ => a + t • w := by fun_prop obtain ⟨ρ, hρ, hball⟩ := Metric.mem_nhds_iff.mp (hline.continuousAt.preimage_mem_nhds (by - show U ∈ 𝓝 ((fun t : ℂ => a + t • w) 0) + change U ∈ 𝓝 ((fun t : ℂ => a + t • w) 0) simp only [zero_smul, add_zero] exact ho.mem_nhds ha)) refine hasSubmeanAt_of_forall_lt hρ fun r hr hrρ => ?_ @@ -223,7 +223,7 @@ theorem IsDomainOfHolomorphy.plurisubharmonicOn_neg_log_infDist {U : Set (Fin n rintro _ ⟨t, ht, rfl⟩ have h1 := hQ t ht rw [← hFline t] at h1 - show ball (a + t • w) ‖q (a + t • w)‖ ⊆ U + change ball (a + t • w) ‖q (a + t • w)‖ ⊆ U rw [hqnorm] have hδ : 0 < infDist (a + t • w) Uᶜ := hpos _ (hdisc t (sphere_subset_closedBall ht)) have h2 : Real.exp (-(F (a + t • w)).re) ≤ infDist (a + t • w) Uᶜ := by @@ -481,7 +481,7 @@ theorem IsDomainOfHolomorphy.satisfiesHolomorphicContinuityPrinciple_fin {U : Se exact (ball_subset_ball (hmK z (hKt hz))).trans (by simpa using ball_infDist_subset_compl (x := z) (s := Uᶜ))) _ hhull rw [hmC] at hrad - show m ≤ infDist (φ (p t) ζ) Uᶜ + change m ≤ infDist (φ (p t) ζ) Uᶜ by_contra hlt push Not at hlt obtain ⟨y, hy, hdy⟩ := (infDist_lt_iff hc).mp hlt diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean index 276174fcf5..5eea353bc6 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Extension.lean @@ -52,6 +52,56 @@ variable {n : ℕ} {F : Type*} [NormedAddCommGroup F] [NormedSpace ℂ F] [Compl @[expose] def taylorCoefficientsAtZero (f : (Fin n → ℂ) → F) : MvPowerSeries (Fin n) F := fun m => (∏ i, (m i).factorial : ℂ)⁻¹ • multiIndexDeriv m f 0 +omit [CompleteSpace F] in +private theorem summable_polydiscTaylor_terms {f : (Fin n → ℂ) → F} + (z : Fin n → ℂ) (r : Fin n → ℝ≥0) (M : ℝ) + (hr : ∀ i, (0 : ℝ) < r i) (hM0 : 0 ≤ M) + (hMb : ∀ y ∈ closedPolydisc 0 (fun i => (r i : ℝ)), ‖f y‖ ≤ M) + (hq : ∀ i, ‖‖z i‖ / (r i : ℝ)‖ < 1) : + Summable (fun m : Fin n → ℕ => + ‖(∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m‖) := + ((hasSum_pi_geometric (fun i => ‖z i‖ / (r i : ℝ)) hq).summable.mul_left M).of_nonneg_of_le + (fun _ => norm_nonneg _) (fun m => norm_polydiscTaylor_term_le hr hM0 hMb + (fun _ => le_rfl) m) + +private theorem summable_finsupp_equiv {a : (Fin n → ℕ) → ℝ} (h : Summable a) : + Summable (fun m : Fin n →₀ ℕ => a m) := + (Finsupp.equivFunOnFinite : (Fin n →₀ ℕ) ≃ (Fin n → ℕ)).summable_iff.mpr h + +omit [CompleteSpace F] in +omit [NormedSpace ℂ F] in +private theorem hasSum_finsupp_equiv {a : (Fin n → ℕ) → F} {x : F} (h : HasSum a x) : + HasSum (fun m : Fin n →₀ ℕ => a m) x := + (Finsupp.equivFunOnFinite : (Fin n →₀ ℕ) ≃ (Fin n → ℕ)).hasSum_iff.mpr h + +private theorem taylorCoefficientsAtZero_polydisc {f : (Fin n → ℂ) → F} + (z : Fin n → ℂ) (r : Fin n → ℝ≥0) (M : ℝ) + (hr : ∀ i, (0 : ℝ) < r i) (hzr : ∀ i, ‖z i‖ < r i) + (hfc : ContinuousOn f (closedPolydisc 0 (fun i => (r i : ℝ)))) + (hfa : ∀ y ∈ closedPolydisc 0 (fun i => (r i : ℝ)), ∀ i, + AnalyticAt ℂ (fun v => f (Function.update y i v)) (y i)) + (hMb : ∀ y ∈ closedPolydisc 0 (fun i => (r i : ℝ)), ‖f y‖ ≤ M) (hM0 : 0 ≤ M) : + Summable (fun m : Fin n →₀ ℕ => ‖(∏ i, z i ^ m i) • taylorCoefficientsAtZero f m‖) ∧ + HasSum (fun m : Fin n →₀ ℕ => (∏ i, z i ^ m i) • taylorCoefficientsAtZero f m) (f z) := by + classical + have he : ∀ m : Fin n →₀ ℕ, taylorCoefficientsAtZero f m = + polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m := + fun m => (polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hr hfc hfa m).symm + have hq : ∀ i, ‖‖z i‖ / (r i : ℝ)‖ < 1 := by + intro i + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (norm_nonneg _) (hr i).le), div_lt_one (hr i)] + exact hzr i + have hnorm := summable_polydiscTaylor_terms z r M hr hM0 hMb hq + have hsum := hasSum_polydiscTaylor (f := f) (c := 0) (h := z) hr (fun i => hzr i) hfc hfa hMb + constructor + · simp_rw [he] + exact summable_finsupp_equiv hnorm + · simp_rw [he] + have hs : HasSum (fun m : Fin n → ℕ => + (∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m) (f z) := by + simpa only [zero_add] using hsum + exact hasSum_finsupp_equiv hs + /-- On a complete Reinhardt open set, the Taylor series at zero represents the function, and the entire set lies inside its absolute-convergence domain. The proof applies the existing polydisc Taylor theorem and coefficient estimates. -/ @@ -88,28 +138,7 @@ theorem IsCompleteReinhardt.subset_convergenceDomain_and_eqOn_powerSeriesSum {U have hM0 : 0 ≤ M := (norm_nonneg (f 0)).trans (hMb 0 (mem_closedPolydisc.mpr (fun i => by simpa only [Pi.zero_apply, dist_self] using (hr i).le))) - have he : ∀ m : Fin n →₀ ℕ, taylorCoefficientsAtZero f m = - polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m := - fun m => (polydiscCauchyCoeffWithRadii_eq_multiIndexDeriv hr hfc hfa m).symm - have hq : ∀ i, ‖‖z i‖ / (r i : ℝ)‖ < 1 := by - intro i - rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (norm_nonneg _) (hr i).le), div_lt_one (hr i)] - exact hzr i - have hnorm : Summable (fun m : Fin n → ℕ => - ‖(∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m‖) := - ((hasSum_pi_geometric (fun i => ‖z i‖ / (r i : ℝ)) hq).summable.mul_left M).of_nonneg_of_le - (fun _ => norm_nonneg _) (fun m => norm_polydiscTaylor_term_le hr hM0 hMb (fun _ => - le_rfl) m) - have hsum := hasSum_polydiscTaylor (f := f) (c := 0) (h := z) hr (fun i => hzr i) hfc hfa hMb - let e : (Fin n →₀ ℕ) ≃ (Fin n → ℕ) := Finsupp.equivFunOnFinite - constructor - · simp_rw [he] - exact e.summable_iff.mpr hnorm - · simp_rw [he] - have hs : HasSum (fun m : Fin n → ℕ => - (∏ i, z i ^ m i) • polydiscCauchyCoeffWithRadii f 0 (fun i => (r i : ℝ)) m) (f z) := by - simpa only [zero_add] using hsum - exact e.hasSum_iff.mpr hs + exact taylorCoefficientsAtZero_polydisc z r M hr hzr hfc hfa hMb hM0 refine ⟨ho.subset_interior_iff.mpr (fun z hz => ?_), fun z hz => (hpoint z hz).2.tsum_eq⟩ exact mem_powerSeriesAbsConvergenceSet_iff.mpr (hpoint z hz).1 diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean index 077926f4ba..d49b5113fd 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/Hull.lean @@ -39,9 +39,11 @@ namespace SeveralComplexVariables variable {ι : Type*} {U V : Set (ι → ℂ)} /-- An open Reinhardt set contains a strictly larger positive modulus vector above each point. -/ -theorem IsReinhardt.exists_strict_modulus_majorant [Fintype ι] +theorem IsReinhardt.exists_strict_modulus_majorant [Finite ι] (hU : IsReinhardt U) (ho : IsOpen U) {z : ι → ℂ} (hz : z ∈ U) : ∃ r : ι → ℝ≥0, (fun i => (r i : ℂ)) ∈ U ∧ ∀ i, ‖z i‖₊ < r i := by + classical + let := Fintype.ofFinite ι have hz' : (fun i => (‖z i‖ : ℂ)) ∈ U := hU hz (fun i => by simp) obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp ho _ hz' let r : ι → ℝ≥0 := fun i => ‖z i‖₊ + ⟨δ / 2, by positivity⟩ @@ -82,9 +84,11 @@ theorem IsLogarithmicallyConvex.geometricCombination_mem {r s : ι → ℝ≥0} exact he ▸ hm /-- On open complete Reinhardt sets the logarithmic-image convention also controls zeros. -/ -theorem IsLogarithmicallyConvex.hasGeometricallyConvexModuli [Fintype ι] +theorem IsLogarithmicallyConvex.hasGeometricallyConvexModuli [Finite ι] (h : IsLogarithmicallyConvex U) (ho : IsOpen U) (hc : IsCompleteReinhardt U) : HasGeometricallyConvexModuli U := by + classical + let := Fintype.ofFinite ι rintro r ⟨z, hz, rfl⟩ s ⟨w, hw, rfl⟩ a b ha hb hab obtain ⟨r, hr, hzr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho hz obtain ⟨s, hs, hws⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho hw @@ -98,11 +102,14 @@ theorem IsLogarithmicallyConvex.hasGeometricallyConvexModuli [Fintype ι] (NNReal.rpow_le_rpow (hws i).le hb) /-- Equivalence of the two conventions on open complete Reinhardt sets. -/ -theorem hasGeometricallyConvexModuli_iff [Fintype ι] (ho : IsOpen U) +theorem hasGeometricallyConvexModuli_iff [Finite ι] (ho : IsOpen U) (hc : IsCompleteReinhardt U) : - HasGeometricallyConvexModuli U ↔ IsLogarithmicallyConvex U := - ⟨fun h => h.isLogarithmicallyConvex hc.isReinhardt, - fun h => h.hasGeometricallyConvexModuli ho hc⟩ + HasGeometricallyConvexModuli U ↔ IsLogarithmicallyConvex U := by + classical + let := Fintype.ofFinite ι + exact + ⟨fun h => h.isLogarithmicallyConvex hc.isReinhardt, + fun h => h.hasGeometricallyConvexModuli ho hc⟩ /-- Away from all coordinate hyperplanes, the two convexity conventions coincide without openness or completeness assumptions. -/ @@ -143,8 +150,10 @@ theorem IsCompleteReinhardt.hull_eq (h : IsCompleteReinhardt U) : completeReinha Subset.antisymm (completeReinhardtHull_min Subset.rfl h) subset_completeReinhardtHull /-- Completing an open Reinhardt set preserves openness. -/ -theorem isOpen_completeReinhardtHull [Fintype ι] (ho : IsOpen U) (hR : IsReinhardt U) : +theorem isOpen_completeReinhardtHull [Finite ι] (ho : IsOpen U) (hR : IsReinhardt U) : IsOpen (completeReinhardtHull U) := by + classical + let := Fintype.ofFinite ι rw [isOpen_iff_mem_nhds] rintro w ⟨z, hz, hwz⟩ obtain ⟨r, hrU, hzr⟩ := hR.exists_strict_modulus_majorant ho hz @@ -208,8 +217,10 @@ theorem logarithmicReinhardtHull_eq (hU : IsReinhardt U) (hg : HasGeometricallyC /-- Openness of the geometric logarithmic hull in finite dimension, including zero coordinates. The modulus trace of an open Reinhardt set is open, and so is its geometric convex hull. -/ -theorem isOpen_logarithmicReinhardtHull [Fintype ι] (ho : IsOpen U) (hU : IsReinhardt U) : +theorem isOpen_logarithmicReinhardtHull [Finite ι] (ho : IsOpen U) (hU : IsReinhardt U) : IsOpen (logarithmicReinhardtHull U) := by + classical + let := Fintype.ofFinite ι have htrace : modulusTrace U = (fun r : ι → ℝ≥0 => fun i => (r i : ℂ)) ⁻¹' U := by ext r diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean index 007f4b567e..ddd9e00198 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/MonomialSeparation.lean @@ -46,12 +46,15 @@ private theorem continuous_faceExp (z : ι → ℂ) : Continuous (faceExp z) := · exact continuous_const · fun_prop +omit [Fintype ι] in /-- A face point in an open complete Reinhardt set has a positive lift with the same nonzero coordinates. -/ -private theorem exists_logarithmic_lift {U : Set (ι → ℂ)} (ho : IsOpen U) +private theorem exists_logarithmic_lift [Finite ι] {U : Set (ι → ℂ)} (ho : IsOpen U) (hc : IsCompleteReinhardt U) {z : ι → ℂ} {t : ι → ℝ} (ht : faceExp z t ∈ U) : ∃ y ∈ logarithmicImage U, ∀ i, z i ≠ 0 → y i = t i := by classical + let := Fintype.ofFinite ι + classical obtain ⟨r, hrU, hr⟩ := hc.isReinhardt.exists_strict_modulus_majorant ho ht have hrpos (i) : 0 < (r i : ℝ) := by exact_mod_cast (show (0 : ℝ≥0) ≤ ‖faceExp z t i‖₊ from zero_le).trans_lt (hr i) @@ -65,11 +68,14 @@ private theorem exists_logarithmic_lift {U : Set (ι → ℂ)} (ho : IsOpen U) · intro i hi simp [y, hi] +omit [Fintype ι] in /-- Logarithmic coordinates on any coordinate face form an open convex lower set. -/ -private theorem convex_faceLog {U : Set (ι → ℂ)} (ho : IsOpen U) +private theorem convex_faceLog [Finite ι] {U : Set (ι → ℂ)} (ho : IsOpen U) (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) (z : ι → ℂ) : Convex ℝ {t | faceExp z t ∈ U} := by classical + let := Fintype.ofFinite ι + classical intro x hx y hy a b ha hb hab obtain ⟨x', hx', hxx⟩ := exists_logarithmic_lift ho hc hx obtain ⟨y', hy', hyy⟩ := exists_logarithmic_lift ho hc hy @@ -143,11 +149,13 @@ private theorem linear_functional_eq_sum [DecidableEq ι] (l : (ι → ℝ) →L /-- Finitely many strict inequalities with nonnegative real weights persist for suitable nonnegative integer weights. Zero weights remain zero. -/ -private theorem exists_nat_weights {κ : Type*} [Fintype κ] {a x : ι → ℝ} +private theorem exists_nat_weights {κ : Type*} [Finite κ] {a x : ι → ℝ} {y : κ → ι → ℝ} (ha : ∀ i, 0 ≤ a i) (hxy : ∀ j, (∑ i, a i * y j i) < ∑ i, a i * x i) : ∃ m : ι → ℕ, (∀ i, a i = 0 → m i = 0) ∧ ∀ j, (∑ i, (m i : ℝ) * y j i) < ∑ i, (m i : ℝ) * x i := by + classical + let := Fintype.ofFinite κ have hlim (j : κ) : Tendsto (fun t : ℝ => ∑ i, ((⌊a i * t⌋₊ : ℝ) / t) * (x i - y j i)) atTop (𝓝 (∑ i, a i * (x i - y j i))) := @@ -165,13 +173,15 @@ private theorem exists_nat_weights {κ : Type*} [Fintype κ] {a x : ι → ℝ} /-- A monomial separates an exterior point from finitely many positive radius vectors in an open complete logarithmically convex Reinhardt set. -/ -theorem exists_monomial_separator_of_finite_radii {κ : Type*} [Fintype κ] [Nonempty κ] +theorem exists_monomial_separator_of_finite_radii {κ : Type*} [Finite κ] [Nonempty κ] {U : Set (ι → ℂ)} (ho : IsOpen U) (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) {r : κ → ι → ℝ} (hr : ∀ j i, 0 < r j i) (hrU : ∀ j, (fun i => (r j i : ℂ)) ∈ U) {z : ι → ℂ} (hz : z ∉ U) : ∃ m : ι → ℕ, ∀ j, (∏ i, r j i ^ m i) < ∏ i, ‖z i‖ ^ m i := by classical + let := Fintype.ofFinite κ + classical let x (i : ι) := Real.log ‖z i‖ let y (j : κ) (i : ι) := Real.log (r j i) have hx : faceExp z x ∉ U := by diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean index 1a2d5f3a49..3f27f82a94 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Reinhardt/PartialHull.lean @@ -97,9 +97,11 @@ theorem partialReinhardtHull_empty (hU : IsReinhardt U) : partialReinhardtHull /-- Partial hulls of open Reinhardt sets are open. A continuous modulus majorant supplies nearby witnesses in the original open set. -/ -theorem isOpen_partialReinhardtHull [Fintype ι] (ho : IsOpen U) (hR : IsReinhardt U) : +theorem isOpen_partialReinhardtHull [Finite ι] (ho : IsOpen U) (hR : IsReinhardt U) : IsOpen (partialReinhardtHull I U) := by classical + let := Fintype.ofFinite ι + classical rw [isOpen_iff_mem_nhds] rintro w ⟨z, hz, hle, heq⟩ let v : (ι → ℂ) → (ι → ℂ) := fun x i => diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean index 1aaaa90d2f..54ea33b703 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/RemovableSingularity.lean @@ -144,7 +144,7 @@ omit [NormedSpace ℂ F] [CompleteSpace F] in /-- Extensions across a scalar zero set are unique on the domain. The defining germs are assumed nonzero locally, so the domain may have several connected components. -/ theorem eqOn_of_extension_across_zeroSet - {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] + {E : Type*} [NormedAddCommGroup E] {U : Set E} (hU : IsOpen U) {g : E → ℂ} (hne : ∀ a ∈ U, ¬ g =ᶠ[𝓝 a] 0) {f f₁ f₂ : E → F} (h₁ : ContinuousOn f₁ U) (h₂ : ContinuousOn f₂ U) (he₁ : EqOn f₁ f (U \ g ⁻¹' {0})) (he₂ : EqOn f₂ f (U \ g ⁻¹' {0})) : diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean index d924f9321c..cc99cef7dc 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean @@ -182,7 +182,7 @@ theorem analyticOnNhd_of_separately_analytic_option {κ : Type*} [Fintype κ] [D have hg1 : AnalyticOnNhd ℂ (f ∘ L.symm) (ball z₀ R ×ˢ ball b ε₁) := by intro q hq have hq' : L.symm q ∈ Ω := by - show L (L.symm q) ∈ ball z₀ R ×ˢ W + change L (L.symm q) ∈ ball z₀ R ×ˢ W rw [L.apply_symm_apply] exact ⟨hq.1, hbW (ball_subset_closedBall hq.2)⟩ exact (hfΩ _ hq').comp_of_eq (L.symm.analyticAt q) rfl @@ -236,7 +236,7 @@ theorem analyticOnNhd_of_separately_analytic_of_equiv {α β : Type*} simp only [Function.comp_apply, hL_update] intro z hz have hzV : L.symm z ∈ L ⁻¹' U := by - show L (L.symm z) ∈ U + change L (L.symm z) ∈ U simpa have := (hg _ hzV).comp_of_eq (L.symm.analyticAt z) rfl simpa only [Function.comp_def, L.apply_symm_apply] using this diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean index 90b9f95833..7cf6351e1e 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean @@ -281,7 +281,7 @@ theorem exists_eventually_norm_le_of_fiber_analytic {D : Set E} (hD : IsOpen D) have hwσ : ‖w - b‖ < σ := by rwa [← dist_eq_norm] have hps := hasFPowerSeriesOnBall_cauchyPowerSeries_of_analyticOnNhd hρ (hgρ z hzD) have hsum := hps.hasSum (y := w - b) (by - show edist (w - b) 0 < ENNReal.ofReal ρ + change edist (w - b) 0 < ENNReal.ofReal ρ rw [edist_lt_ofReal, dist_zero_right] exact hwσ.trans hσρ) rw [add_sub_cancel] at hsum diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean index 597505cf8a..f8a0ef11be 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Subharmonic.lean @@ -348,7 +348,7 @@ theorem SubharmonicOn.eqOn_const_of_isMaxOn (hU : IsOpen U) (hc : IsPreconnected have heq : u z = u a := le_antisymm (hmax z hzU) hle refine ⟨hzU, ?_⟩ have := hu.eventually_eq_of_isMaxOn hU hzU (fun w hw => (hmax w hw).trans heq.ge) - show ∀ᶠ w in 𝓝 z, u w = u a + change ∀ᶠ w in 𝓝 z, u w = u a simpa only [heq] using this intro z hz exact hWval z (hc.subset_of_closure_inter_subset hWo hWne hcl hz) diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean index 8cefb0bdcc..2e0de4270f 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain.lean @@ -102,7 +102,7 @@ private theorem exists_extension_tubeDomain_convexHull_nonempty {F : Type*} [Nor have hz' : z ∘ e.symm ∈ tubeDomain (L '' Ω) := by rw [mem_tubeDomain, hre] exact mem_image_of_mem L hz - show g' (z ∘ e.symm) = f z + change g' (z ∘ e.symm) = f z rw [hg'f hz'] simp only [Function.comp_assoc, e.symm_comp_self, Function.comp_id] @@ -123,7 +123,7 @@ theorem exists_extension_tubeDomain_convexHull {F : Type*} [NormedAddCommGroup F /-- Uniqueness of a tube extension to the convexified base, independently of Bochner's existence theorem. Only a nonempty open original base is needed. -/ theorem eqOn_of_tubeDomain_extension {F : Type*} [NormedAddCommGroup F] - [NormedSpace ℂ F] [CompleteSpace F] {Ω : Set (ι → ℝ)} + [NormedSpace ℂ F] {Ω : Set (ι → ℝ)} (ho : IsOpen Ω) (hn : Ω.Nonempty) {f g : (ι → ℂ) → F} (hf : AnalyticOnNhd ℂ f (tubeDomain (convexHull ℝ Ω))) (hg : AnalyticOnNhd ℂ g (tubeDomain (convexHull ℝ Ω))) diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean index e8fd1645e9..d35025cc33 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/TubeDomain/Basic.lean @@ -220,7 +220,7 @@ theorem ball_subset_tubeDomain {Ω : Set (ι → ℝ)} {z : ι → ℂ} {r : ℝ intro w hw apply h rw [Metric.mem_ball, dist_eq_norm] at hw ⊢ - show ‖rePi w - rePi z‖ < r + change ‖rePi w - rePi z‖ < r rw [← rePi_sub] exact (norm_rePi_le _).trans_lt hw diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean index 0aacc92b9e..25e652ecd1 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision.lean @@ -171,10 +171,11 @@ private theorem norm_weierstrassRemainder_le {d : ℕ} {c : Fin d → (ι → exact mul_le_mul (hc j) (hpow j) (by positivity) hε _ = (d : ℝ) * ε * (max R 1) ^ d := by simp; ring +omit [Fintype ι] in /-- If the remainder coefficients tend to zero and the leading factor is bounded away from zero, shrinking only the parameter polydisc gives the contraction bound. The scalar radius and an upper bound for the parameter radius can be prescribed. -/ -private theorem exists_small_remainder_div {d : ℕ} {c : Fin d → (ι → ℂ) → ℂ} +private theorem exists_small_remainder_div [Finite ι] {d : ℕ} {c : Fin d → (ι → ℂ) → ℂ} {f1 : (ι → ℂ) × ℂ → ℂ} {R δ r₀ : ℝ} (hR : 0 < R) (hδ : 0 < δ) (hr₀ : 0 < r₀) (hc : ∀ j, Tendsto (c j) (𝓝 0) (𝓝 0)) (hlower : ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => r₀) ×ˢ ball (0 : ℂ) R, @@ -182,6 +183,8 @@ private theorem exists_small_remainder_div {d : ℕ} {c : Fin d → (ι → ℂ) ∃ r : ℝ, 0 < r ∧ r ≤ r₀ ∧ ∀ z ∈ polydisc (0 : ι → ℂ) (fun _ => r) ×ˢ ball (0 : ℂ) R, ‖weierstrassRemainder c z / f1 z‖ ≤ R ^ d / (2 * (d + 1)) := by + classical + let := Fintype.ofFinite ι let ε := δ * R ^ d / (2 * (d + 1) * (d + 1) * (max R 1) ^ d) have hε : 0 < ε := by dsimp [ε]; positivity have hev : ∀ᶠ w in 𝓝 (0 : ι → ℂ), ∀ j, ‖c j w‖ < ε := by @@ -278,7 +281,6 @@ theorem exists_perturbation_bound_of_coordinatePower_leadingFactor {d : ℕ} {f (fun z hz => hδle z ⟨mem_closedPolydisc.mpr (fun i => (mem_polydisc.mp hz.1 i).le), ball_subset_closedBall hz.2⟩) - exact ⟨R₂, δ, r₃, hR₂pos, hR₂ε₁, hδpos, hr₃pos, hr₃ε₁, hhA1, hcj0', hδle, fun w hw ζ hζ => hhbound (w, ζ) ⟨hw, hζ⟩⟩ @@ -343,7 +345,7 @@ private theorem normalized_division_germ_unique {d : ℕ} {r₃ R₂ δ : ℝ} intro z hz have heqz : g z = q' z * f z + weierstrassRemainder a' z := hlocal.eq (hlocalSub hz) have heqf5 : f z = f1 z * (z.2 ^ d + hh z) := hf_eq2 z (hdomsub5 hz) - show g z - hh z * s' z = s' z * z.2 ^ d + weierstrassRemainder a' z + change g z - hh z * s' z = s' z * z.2 ^ d + weierstrassRemainder a' z simp only [hs'def] rw [heqz, heqf5] ring @@ -373,7 +375,7 @@ private theorem normalized_division_germ_unique {d : ℕ} {r₃ R₂ δ : ℝ} hρpos hh g S s' aOut a' hhFINAL5 hhb3 hSdiv hdiv' (max C1 0) (le_max_right _ _) hM3b have hqeqq' : EqOn q q' dom5 := by intro z hz - show S z / f1 z = q' z + change S z / f1 z = q' z rw [hSeqs' hz] show s' z / f1 z = q' z rw [hs'def] @@ -474,7 +476,7 @@ theorem exists_isWeierstrassDivisionOn_of_bounded {d : ℕ} {f : (ι → ℂ) × hε₁ε₀ (hFINALsubε₁ hz) have h1 : f z = f1 z * z.2 ^ d + weierstrassRemainder c z := hfdiv.eq hz0 have h2 : weierstrassRemainder c z = hh z * f1 z := by - show weierstrassRemainder c z = weierstrassRemainder c z / f1 z * f1 z + change weierstrassRemainder c z = weierstrassRemainder c z / f1 z * f1 z rw [div_mul_cancel₀ _ (hf1ne0FINAL z hz)] rw [h2] at h1 rw [h1]; ring @@ -507,7 +509,7 @@ theorem exists_isWeierstrassDivisionOn_of_bounded {d : ℕ} {f : (ι → ℂ) × linarith have hf1ge : δ ≤ ‖f1 z‖ := hδle _ (hdomFINALsubK hz) have hf1pos' : 0 < ‖f1 z‖ := hδpos.trans_le hf1ge - show ‖S z / f1 z‖ ≤ 2 * ((d:ℝ) + 1) / (R₂ ^ d * δ) * M + change ‖S z / f1 z‖ ≤ 2 * ((d:ℝ) + 1) / (R₂ ^ d * δ) * M rw [norm_div] calc ‖S z‖ / ‖f1 z‖ ≤ (2 * B) / ‖f1 z‖ := div_le_div_of_nonneg_right hSb hf1pos'.le _ ≤ (2 * B) / δ := div_le_div_of_nonneg_left (by positivity) hδpos hf1ge diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean index 97f7caf364..3a8b0fe53e 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Basic.lean @@ -115,7 +115,7 @@ theorem IsWeierstrassDivisionAt.unique_zero {f g q q' : E × ℂ → ℂ} exact mul_right_cancel₀ hne he /-- The Weierstrass remainder is linear (here, additive) in its coefficient tuple. -/ -theorem weierstrassRemainder_sub {E : Type*} [NormedAddCommGroup E] [NormedSpace ℂ E] +theorem weierstrassRemainder_sub {E : Type*} {d : ℕ} (a b : Fin d → E → ℂ) (z : E × ℂ) : weierstrassRemainder a z - weierstrassRemainder b z = weierstrassRemainder (fun j => a j - b j) z := by @@ -125,11 +125,14 @@ theorem weierstrassRemainder_sub {E : Type*} [NormedAddCommGroup E] [NormedSpace variable {ι : Type*} [Fintype ι] +omit [Fintype ι] in /-- Every open neighborhood of the origin in `(ι → ℂ) × ℂ` contains a product of a constant-radius polydisc and a ball of the same radius. -/ -theorem exists_polydisc_ball_subset {U : Set ((ι → ℂ) × ℂ)} +theorem exists_polydisc_ball_subset [Finite ι] {U : Set ((ι → ℂ) × ℂ)} (hU : IsOpen U) (h0 : (0 : (ι → ℂ) × ℂ) ∈ U) : ∃ ε : ℝ, 0 < ε ∧ polydisc (0 : ι → ℂ) (fun _ => ε) ×ˢ ball (0 : ℂ) ε ⊆ U := by + classical + let := Fintype.ofFinite ι obtain ⟨ε, hε, hsub⟩ := Metric.mem_nhds_iff.mp (hU.mem_nhds h0) refine ⟨ε, hε, fun z hz => hsub ?_⟩ rw [mem_ball, dist_zero_right, Prod.norm_def] diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean index e972632858..b569e61494 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/CoordinatePower.lean @@ -222,14 +222,17 @@ theorem unique_coordinatePower_division {d : ℕ} {V : Set (ι → ℂ)} {R : exact heq0 · exact mul_right_cancel₀ (pow_ne_zero d hw) hmul +omit [Fintype ι] in /-- Mixed last-coordinate derivatives at the origin are Cauchy integrals on a smaller circle. -/ -theorem iteratedDeriv_snd_slice_circleIntegral +theorem iteratedDeriv_snd_slice_circleIntegral [Finite ι] {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {z : ι → ℂ} (hz : z ∈ V) (hρ : 0 < ρ) (hρR : ρ < R) (n : ℕ) : iteratedDeriv n (fun w => g (z, w)) 0 = (n.factorial : ℂ) * (2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), s ^ (-(n + 1 : ℤ)) * g (z, s) := by + classical + let := Fintype.ofFinite ι simpa [sub_zero] using (diffContOnCl_snd_slice hg hz hρ hρR).iteratedDeriv_eq_circleIntegral_sub_zpow_mul hρ n (mem_ball_self hρ) @@ -255,12 +258,15 @@ theorem analyticOnNhd_circleIntegral_snd_zpow_mul refine hI.congr hV fun z hz => ?_ exact circleIntegral.integral_congr hρ.le fun s _ => mul_comm _ _ +omit [Fintype ι] in /-- The Taylor remainder coefficients of a last-coordinate slice depend holomorphically on the remaining coordinates. -/ -theorem differentiableOn_iteratedDeriv_snd_slice +theorem differentiableOn_iteratedDeriv_snd_slice [Finite ι] {V : Set (ι → ℂ)} (hV : IsOpen V) {R : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hR : 0 < R) (n : ℕ) : DifferentiableOn ℂ (fun z => iteratedDeriv n (fun w => g (z, w)) 0) V := by + classical + let := Fintype.ofFinite ι let ρ := R / 2 have hρ : 0 < ρ := half_pos hR have hρR : ρ < R := half_lt_self hR @@ -336,12 +342,15 @@ theorem le_div_pow_of_forall_lt {M : ℝ} {R : ℝ} (hR : 0 < R) (n : ℕ) {x : (eventually_gt_nhds hR).filter_mono nhdsWithin_le_nhds] with ρ hρR hρ0 exact h ρ hρ0 hρR +omit [Fintype ι] in /-- Cauchy's estimate for the Taylor coefficients of a last-coordinate slice, uniform up to the boundary radius `R` even though the function is only assumed holomorphic on the open polydisc. -/ -theorem norm_iteratedDeriv_snd_slice_le {V : Set (ι → ℂ)} {R : ℝ} {g : (ι → ℂ) × ℂ → ℂ} +theorem norm_iteratedDeriv_snd_slice_le [Finite ι] {V : Set (ι → ℂ)} {R : ℝ} {g : (ι → ℂ) × ℂ → ℂ} {M : ℝ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hR : 0 < R) {z : ι → ℂ} (hz : z ∈ V) (hM : ∀ w ∈ ball (0 : ℂ) R, ‖g (z, w)‖ ≤ M) (n : ℕ) : ‖iteratedDeriv n (fun w => g (z, w)) 0‖ ≤ (n.factorial : ℝ) * M / R ^ n := by + classical + let := Fintype.ofFinite ι apply le_div_pow_of_forall_lt hR intro ρ hρ hρR rw [iteratedDeriv_snd_slice_circleIntegral hg hz hρ hρR n, mul_assoc, norm_mul] @@ -368,18 +377,22 @@ theorem norm_iteratedDeriv_snd_slice_le {V : Set (ι → ℂ)} {R : ℝ} {g : ( ≤ (n.factorial : ℝ) * (M / ρ ^ n) := mul_le_mul_of_nonneg_left hkernel (by positivity) _ = (n.factorial : ℝ) * M / ρ ^ n := by ring +omit [Fintype ι] in /-- The Cauchy coefficient of a last-coordinate slice equals a division-kernel circle integral, matching the shape used by the coordinate-power kernel identity. -/ -theorem cauchyCoeff_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} +theorem cauchyCoeff_eq_of_lt [Finite ι] + {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) {w : ι → ℂ} (hw : w ∈ V) (hρ : 0 < ρ) (hρR : ρ < R) (j : ℕ) : (2 * Real.pi * I : ℂ)⁻¹ * ∮ s in C(0, ρ), g (w, s) / s ^ (j + 1) = ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv j (fun s => g (w, s)) 0 := by + classical + let := Fintype.ofFinite ι rw [iteratedDeriv_snd_slice_circleIntegral hg hw hρ hρR j] have hEq : EqOn (fun s : ℂ => g (w, s) / s ^ (j + 1)) (fun s => s ^ (-(j + 1 : ℤ)) * g (w, s)) (sphere (0 : ℂ) ρ) := by intro s _ - show g (w, s) / s ^ (j + 1) = s ^ (-(j + 1 : ℤ)) * g (w, s) + change g (w, s) / s ^ (j + 1) = s ^ (-(j + 1 : ℤ)) * g (w, s) rw [div_eq_inv_mul, show (-(j + 1 : ℤ)) = -((j + 1 : ℕ) : ℤ) by push_cast; ring, zpow_neg, zpow_natCast] rw [circleIntegral.integral_congr hρ.le hEq, @@ -387,15 +400,19 @@ theorem cauchyCoeff_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → inv_mul_cancel_left₀ (by exact_mod_cast j.factorial_ne_zero : ((j : ℕ).factorial : ℂ) ≠ 0)] +omit [Fintype ι] in /-- The Cauchy quotient at a fixed admissible radius solves the coordinate-power division identity there, with remainder coefficients given by Taylor coefficients of the last-coordinate slice. -/ -private theorem coordinatePower_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} +private theorem coordinatePower_eq_of_lt [Finite ι] + {V : Set (ι → ℂ)} {R ρ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρ : 0 < ρ) (hρR : ρ < R) (d : ℕ) {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ : ζ ∈ ball (0 : ℂ) ρ) : g (w, ζ) = weierstrassRemainder (fun j : Fin d => fun v : ι → ℂ => ((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ) + ζ ^ d * weierstrassCauchyQuotient d g ρ (w, ζ) := by + classical + let := Fintype.ofFinite ι have hζρ : ‖ζ‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ have hslice : DiffContOnCl ℂ (fun s => g (w, s)) (ball 0 ρ) := diffContOnCl_snd_slice hg hw hρ hρR @@ -416,7 +433,7 @@ private theorem coordinatePower_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g (fun s => (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) + ζ ^ d / (s ^ d * (s - ζ)) * g (w, s)) (sphere (0 : ℂ) ρ) := by intro s hs - show (s - ζ)⁻¹ * g (w, s) = + change (s - ζ)⁻¹ * g (w, s) = (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) + ζ ^ d / (s ^ d * (s - ζ)) * g (w, s) rw [← add_mul, weierstrass_kernel_identity d (hne0 s hs) (hnesw s hs)] rw [circleIntegral.integral_congr hρ.le hEqOn] at hcauchy @@ -444,7 +461,7 @@ private theorem coordinatePower_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g ∮ s in C(0, ρ), ∑ j ∈ range d, ζ ^ j * (g (w, s) / s ^ (j + 1)) := by apply circleIntegral.integral_congr hρ.le intro s _ - show (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) = + change (∑ j ∈ range d, ζ ^ j / s ^ (j + 1)) * g (w, s) = ∑ j ∈ range d, ζ ^ j * (g (w, s) / s ^ (j + 1)) rw [Finset.sum_mul] exact Finset.sum_congr rfl fun j _ => by ring @@ -472,14 +489,17 @@ private theorem coordinatePower_eq_of_lt {V : Set (ι → ℂ)} {R ρ : ℝ} {g iteratedDeriv j (fun s => g (w, s)) 0 * ζ ^ j)] ring +omit [Fintype ι] in /-- The Cauchy quotient at two admissible radii agrees at every nonzero point where both are defined. -/ -private theorem weierstrassCauchyQuotient_eq_of_ne {V : Set (ι → ℂ)} {R ρ₁ ρ₂ : ℝ} +private theorem weierstrassCauchyQuotient_eq_of_ne [Finite ι] {V : Set (ι → ℂ)} {R ρ₁ ρ₂ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρ₁ : 0 < ρ₁) (hρ₁R : ρ₁ < R) (hρ₂ : 0 < ρ₂) (hρ₂R : ρ₂ < R) (d : ℕ) {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ0 : ζ ≠ 0) (hζ₁ : ζ ∈ ball (0 : ℂ) ρ₁) (hζ₂ : ζ ∈ ball (0 : ℂ) ρ₂) : weierstrassCauchyQuotient d g ρ₁ (w, ζ) = weierstrassCauchyQuotient d g ρ₂ (w, ζ) := by + classical + let := Fintype.ofFinite ι have h1 := coordinatePower_eq_of_lt hg hρ₁ hρ₁R d hw hζ₁ have h2 := coordinatePower_eq_of_lt hg hρ₂ hρ₂R d hw hζ₂ have heq : ζ ^ d * weierstrassCauchyQuotient d g ρ₁ (w, ζ) = @@ -489,12 +509,16 @@ private theorem weierstrassCauchyQuotient_eq_of_ne {V : Set (ι → ℂ)} {R ρ (w, ζ)), ← h1, ← h2] exact mul_left_cancel₀ (pow_ne_zero d hζ0) heq +omit [Fintype ι] in /-- The Cauchy quotient at two admissible radii agrees wherever both are defined. -/ -private theorem weierstrassCauchyQuotient_eq_of_lt {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ₁ ρ₂ : ℝ} +private theorem weierstrassCauchyQuotient_eq_of_lt [Finite ι] + {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ₁ ρ₂ : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρ₁ : 0 < ρ₁) (hρ₁R : ρ₁ < R) (hρ₂ : 0 < ρ₂) (hρ₂R : ρ₂ < R) (d : ℕ) {w : ι → ℂ} (hw : w ∈ V) {ζ : ℂ} (hζ₁ : ζ ∈ ball (0 : ℂ) ρ₁) (hζ₂ : ζ ∈ ball (0 : ℂ) ρ₂) : weierstrassCauchyQuotient d g ρ₁ (w, ζ) = weierstrassCauchyQuotient d g ρ₂ (w, ζ) := by + classical + let := Fintype.ofFinite ι rcases eq_or_ne ζ 0 with hζ0 | hζ0 · subst hζ0 set ρ₀ := min ρ₁ ρ₂ / 2 with hρ₀def @@ -531,69 +555,78 @@ private theorem weierstrassCauchyQuotient_eq_of_lt {V : Set (ι → ℂ)} (hV : exact tendsto_nhds_unique (hlim1.congr' heqn) hlim2 · exact weierstrassCauchyQuotient_eq_of_ne hg hρ₁ hρ₁R hρ₂ hρ₂R d hw hζ0 hζ₁ hζ₂ +omit [Fintype ι] in /-- Subtracting the Taylor polynomial of degree less than `d` from a function bounded by `M` gives a numerator bounded by `(d + 1) * M`. The triangle inequality and Cauchy's coefficient bounds control each of the `d` remainder terms on the smaller disc. -/ -theorem norm_sub_weierstrassRemainder_iteratedDeriv_le {V : Set (ι → ℂ)} {R ρ M : ℝ} +theorem norm_sub_weierstrassRemainder_iteratedDeriv_le [Finite ι] {V : Set (ι → ℂ)} {R ρ M : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρR : ρ < R) (d : ℕ) (hM : ∀ z ∈ V ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) {w : ι → ℂ} (hw : w ∈ V) {ζ' : ℂ} (hζ' : ζ' ∈ ball (0 : ℂ) ρ) : - ‖g (w, ζ') - weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ ((d + 1 : ℕ) : ℝ) * M := by - have hζ'ρ : ‖ζ'‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ' - have hζ'R : ‖ζ'‖ < R := hζ'ρ.trans hρR - have hR0 : 0 < R := (norm_nonneg ζ').trans_lt hζ'R - have hgb : ‖g (w, ζ')‖ ≤ M := hM (w, ζ') ⟨hw, mem_ball_zero_iff.mpr hζ'R⟩ - have hMnn : 0 ≤ M := (norm_nonneg _).trans hgb - have haj : ∀ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ ≤ M / R ^ (j : ℕ) := by - intro j - have hb := norm_iteratedDeriv_snd_slice_le hg hR0 hw (fun s hs => hM (w, s) ⟨hw, hs⟩) - (j : ℕ) - rw [norm_mul, norm_inv, Complex.norm_natCast] - calc ((j : ℕ).factorial : ℝ)⁻¹ * ‖iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0‖ - ≤ ((j : ℕ).factorial : ℝ)⁻¹ * (((j : ℕ).factorial : ℝ) * M / R ^ (j : ℕ)) := - mul_le_mul_of_nonneg_left hb (by positivity) - _ = M / R ^ (j : ℕ) := by field_simp - have hrem : ‖weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ (d : ℝ) * M := by - unfold weierstrassRemainder - calc ‖∑ j : Fin d, (((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ - ≤ ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ := norm_sum_le _ _ - _ = ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) := by - simp [norm_pow] - _ ≤ ∑ _j : Fin d, (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by - apply Finset.sum_le_sum - intro j _ - calc ‖(((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) - (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) - ≤ (M / R ^ (j : ℕ)) * R ^ (j : ℕ) := - mul_le_mul (haj j) (pow_le_pow_left₀ (norm_nonneg _) - (hζ'ρ.trans hρR).le _) (by positivity) (by positivity) - _ = M := by field_simp - _ = (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by simp - _ = (d : ℝ) * M := by simp [Finset.sum_const, Finset.card_univ, mul_comm] - calc ‖g (w, ζ') - weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ - ≤ ‖g (w, ζ')‖ + ‖weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * - iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ := norm_sub_le _ _ - _ ≤ M + (d : ℝ) * M := add_le_add hgb hrem - _ = ((d + 1 : ℕ) : ℝ) * M := by push_cast; ring - + ‖g (w, ζ') - weierstrassRemainder (d := by + classical + let := Fintype.ofFinite ι + exact + d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ ((d + 1 : ℕ) : ℝ) * M := by + have hζ'ρ : ‖ζ'‖ < ρ := by simpa [mem_ball, dist_eq_norm] using hζ' + have hζ'R : ‖ζ'‖ < R := hζ'ρ.trans hρR + have hR0 : 0 < R := (norm_nonneg ζ').trans_lt hζ'R + have hgb : ‖g (w, ζ')‖ ≤ M := hM (w, ζ') ⟨hw, mem_ball_zero_iff.mpr hζ'R⟩ + have hMnn : 0 ≤ M := (norm_nonneg _).trans hgb + have haj : ∀ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ ≤ M / R ^ (j : ℕ) := by + intro j + have hb := norm_iteratedDeriv_snd_slice_le hg hR0 hw (fun s hs => hM (w, s) ⟨hw, hs⟩) + (j : ℕ) + rw [norm_mul, norm_inv, Complex.norm_natCast] + calc ((j : ℕ).factorial : ℝ)⁻¹ * ‖iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0‖ + ≤ ((j : ℕ).factorial : ℝ)⁻¹ * (((j : ℕ).factorial : ℝ) * M / R ^ (j : ℕ)) := + mul_le_mul_of_nonneg_left hb (by positivity) + _ = M / R ^ (j : ℕ) := by field_simp + have hrem : ‖weierstrassRemainder (d := d) (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ ≤ (d : ℝ) * M := by + unfold weierstrassRemainder + calc ‖∑ j : Fin d, (((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ + ≤ ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0) * ζ' ^ (j : ℕ)‖ := norm_sum_le _ _ + _ = ∑ j : Fin d, ‖(((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) := by + simp [norm_pow] + _ ≤ ∑ _j : Fin d, (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by + apply Finset.sum_le_sum + intro j _ + calc ‖(((j : ℕ).factorial : ℂ)⁻¹ * iteratedDeriv (j : ℕ) + (fun s => g (w, s)) 0)‖ * ‖ζ'‖ ^ (j : ℕ) + ≤ (M / R ^ (j : ℕ)) * R ^ (j : ℕ) := + mul_le_mul (haj j) (pow_le_pow_left₀ (norm_nonneg _) + (hζ'ρ.trans hρR).le _) (by positivity) (by positivity) + _ = M := by field_simp + _ = (M / R ^ (0 : ℕ)) * R ^ (0 : ℕ) := by simp + _ = (d : ℝ) * M := by simp [Finset.sum_const, Finset.card_univ, mul_comm] + calc ‖g (w, ζ') - weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ + ≤ ‖g (w, ζ')‖ + ‖weierstrassRemainder (fun j v => ((j : ℕ).factorial : ℂ)⁻¹ * + iteratedDeriv (j : ℕ) (fun s => g (v, s)) 0) (w, ζ')‖ := norm_sub_le _ _ + _ ≤ M + (d : ℝ) * M := add_le_add hgb hrem + _ = ((d + 1 : ℕ) : ℝ) * M := by push_cast; ring + +omit [Fintype ι] in /-- The **uniform coordinate-power quotient bound**: the Cauchy quotient at radius `ρ` is bounded by `(d+1) M / ρ ^ d` throughout the disc, using a bound `M` on the numerator over the whole domain. The proof compares the numerator to its degree-`< d` Taylor polynomial, bounded by `(d+1) M` via `norm_sub_weierstrassRemainder_iteratedDeriv_le`, then applies the maximum modulus principle to the quotient itself and lets the comparison radius approach `ρ`. -/ -private theorem norm_weierstrassCauchyQuotient_le {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ M : ℝ} +private theorem norm_weierstrassCauchyQuotient_le [Finite ι] + {V : Set (ι → ℂ)} (hV : IsOpen V) {R ρ M : ℝ} {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (V ×ˢ ball 0 R)) (hρ : 0 < ρ) (hρR : ρ < R) (d : ℕ) (hM : ∀ z ∈ V ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) {w : ι → ℂ} (hw : w ∈ V) {ζ0 : ℂ} (hζ0 : ζ0 ∈ ball (0 : ℂ) ρ) : ‖weierstrassCauchyQuotient d g ρ (w, ζ0)‖ ≤ ((d + 1 : ℕ) : ℝ) * M / ρ ^ d := by + classical + let := Fintype.ofFinite ι have hR0 : 0 < R := hρ.trans hρR have hMnn : 0 ≤ M := (norm_nonneg _).trans (hM (w, 0) ⟨hw, mem_ball_self hR0⟩) have hgA : AnalyticOnNhd ℂ g (V ×ˢ ball 0 R) := hg.analyticOnNhd_of_finiteDimensional @@ -695,7 +728,7 @@ theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < obtain ⟨hρypos, hρyζ, hρyR⟩ := hρz y.2 hy2R have hyρbig : ‖y.2‖ < ρbig := hy2'.trans hρ0'ρbig have hρylt : (‖y.2‖ + R) / 2 < ρbig := by linarith - show weierstrassCauchyQuotient d g ((‖y.2‖ + R) / 2) y = + change weierstrassCauchyQuotient d g ((‖y.2‖ + R) / 2) y = weierstrassCauchyQuotient d g ρbig y exact weierstrassCauchyQuotient_eq_of_lt hVo hg hρypos hρyR ((norm_nonneg y.2).trans_lt hyρbig) hρbigR d hy1 @@ -713,7 +746,7 @@ theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < have hζR : ‖z.2‖ < R := by simpa [mem_ball, dist_eq_norm] using hz2 obtain ⟨hρ0pos, hρ0ζ, hρ0R⟩ := hρz z.2 hζR have := coordinatePower_eq_of_lt hg hρ0pos hρ0R d hz1 (mem_ball_zero_iff.mpr hρ0ζ) - show g z = q z * z.2 ^ d + weierstrassRemainder a z + change g z = q z * z.2 ^ d + weierstrassRemainder a z rw [this]; ring refine ⟨q, a, ⟨hqholo, haholo, heqOnV⟩, ?_, ?_⟩ · intro M hM0 hMb z hz diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean index 5991a7361d..50bac9efd2 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassDivision/Picard.lean @@ -163,7 +163,7 @@ theorem picardApprox_diff_bound (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i have hb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖(g - h * (picardApprox d r R hr hR h g hg hh 0).1) z‖ ≤ M := by intro z hz - show ‖g z - h z * (picardApprox d r R hr hR h g hg hh 0).1 z‖ ≤ M + change ‖g z - h z * (picardApprox d r R hr hR h g hg hh 0).1 z‖ ≤ M simpa [picardApprox] using hgb z hz have hbnd := picardApprox_succ_bound d r R hr hR h g hg hh 0 M hM0 hb z hz simpa [picardApprox] using hbnd @@ -184,7 +184,7 @@ theorem picardApprox_diff_bound (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i intro w hw have e1 := hdivk.eq hw have e2 := hdivk1.eq hw - show h w * (sk1 w - sk w) = (sk1 w - sk2 w) * w.2 ^ d + + change h w * (sk1 w - sk w) = (sk1 w - sk2 w) * w.2 ^ d + weierstrassRemainder (fun j => ak j - ak1 j) w rw [← weierstrassRemainder_sub] have e1' : g w - h w * sk w = sk1 w * w.2 ^ d + weierstrassRemainder ak w := e1 @@ -201,7 +201,7 @@ theorem picardApprox_diff_bound (d : ℕ) (r : ι → ℝ) (R : ℝ) (hr : ∀ i ‖(h * (sk1 - sk)) z‖ ≤ (R ^ d / (2 * (d + 1))) * (((d + 1 : ℕ) : ℝ) / R ^ d * M * (1 / 2) ^ k) := by intro z hz - show ‖h z * (sk1 z - sk z)‖ ≤ _ + change ‖h z * (sk1 z - sk z)‖ ≤ _ rw [norm_mul] exact mul_le_mul (hhb z hz) (ih z hz) (norm_nonneg _) (by positivity) have hq''bound := hbound'' _ (by positivity) hbndM z hz @@ -329,7 +329,7 @@ private theorem tendstoUniformlyOn_picardRemainder have hdiff_eq : Fk k ζ' - rFun (w, ζ') = -(h (w, ζ') * ((sSeq k).1 (w, ζ') - S (w, ζ'))) - ζ' ^ d * ((sSeq (k + 1)).1 (w, ζ') - S (w, ζ')) := by - show (g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - + change (g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - ζ' ^ d * (sSeq (k + 1)).1 (w, ζ')) - (g (w, ζ') - h (w, ζ') * S (w, ζ') - ζ' ^ d * S (w, ζ')) = _ ring @@ -442,7 +442,7 @@ theorem exists_weierstrassRemainder_eq_of_tendstoUniformlyOn_picardApprox intro k ζ' hζ' have hthis := (picardApprox_succ_isWeierstrassDivisionOn d r R hr hR h g hg hh k).eq (⟨hw, hζ'⟩ : (w, ζ') ∈ polydisc 0 r ×ˢ ball 0 R) - show g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - ζ' ^ d * (sSeq (k + 1)).1 (w, ζ') = _ + change g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') - ζ' ^ d * (sSeq (k + 1)).1 (w, ζ') = _ have hthis' : g (w, ζ') - h (w, ζ') * (sSeq k).1 (w, ζ') = (sSeq (k + 1)).1 (w, ζ') * ζ' ^ d + weierstrassRemainder (picardApproxCoeff d r R hr hR h g hg hh k) (w, ζ') := hthis @@ -484,7 +484,7 @@ theorem eqOn_of_isWeierstrassDivisionOn_selfPerturbed {d : ℕ} {r : ι → ℝ} ⟨hdiv'.differentiableOn_quotient, hdiv'.differentiableOn_coeff, fun z hz => by - show (g z - h z * s z) = s' z * z.2 ^ d + weierstrassRemainder a' z + change (g z - h z * s z) = s' z * z.2 ^ d + weierstrassRemainder a' z rw [hs hz] exact hdiv'.eq hz⟩ exact (unique_coordinatePower_division hdiv hdiv2 hR).2 @@ -499,7 +499,7 @@ theorem eqOn_of_isWeierstrassDivisionOn_selfPerturbed {d : ℕ} {r : ι → ℝ} intro w hw have e1 : g w - h w * s w = s w * w.2 ^ d + weierstrassRemainder a w := hdiv.eq hw have e2 : g w - h w * s' w = s' w * w.2 ^ d + weierstrassRemainder a' w := hdiv'.eq hw - show h w * (s' w - s w) = (s w - s' w) * w.2 ^ d + weierstrassRemainder (fun j => a j - a' + change h w * (s' w - s w) = (s w - s' w) * w.2 ^ d + weierstrassRemainder (fun j => a j - a' j) w rw [← weierstrassRemainder_sub] have : h w * (s' w - s w) = (s w * w.2 ^ d + weierstrassRemainder a w) - @@ -512,7 +512,7 @@ theorem eqOn_of_isWeierstrassDivisionOn_selfPerturbed {d : ℕ} {r : ι → ℝ} have hb : ∀ z ∈ polydisc 0 r ×ˢ ball 0 R, ‖(h * (s' - s)) z‖ ≤ (R ^ d / (2 * (d + 1))) * M' := by intro z hz - show ‖h z * (s' z - s z)‖ ≤ _ + change ‖h z * (s' z - s z)‖ ≤ _ rw [norm_mul, ← norm_sub_rev (s z) (s' z)] exact mul_le_mul (hhb z hz) (hM' z hz) (norm_nonneg _) (by positivity) have hq''bound := hbound'' _ (by positivity) hb z hz diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean index 01f806110b..12bb031e84 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/WeierstrassPreparation.lean @@ -251,7 +251,7 @@ theorem IsWeierstrassPreparationAt.comp_equiv {F : Type*} [NormedAddCommGroup F] have ht : Tendsto (fun z : F × ℂ => (φ z.1, z.2)) (𝓝 0) (𝓝 (0 : E × ℂ)) := by rw [← h0]; exact hpair.continuousAt.tendsto refine ⟨h.analyticAt_unit.comp_of_eq hpair h0, - by show u (φ 0, (0 : ℂ)) ≠ 0; rw [hφmap]; exact h.unit_ne_zero, + by change u (φ 0, (0 : ℂ)) ≠ 0; rw [hφmap]; exact h.unit_ne_zero, fun j => (h.analyticAt_coeff j).comp_of_eq hφ hφmap, fun j => by show a j (φ (0 : F)) = 0; rw [hφmap]; exact h.coeff_zero j, (h.eq.comp_tendsto ht).mono fun z hz => by diff --git a/LeanPool/SeveralComplexVariables/Solution.lean b/LeanPool/SeveralComplexVariables/Solution.lean index e9dc595892..9368f5deb3 100644 --- a/LeanPool/SeveralComplexVariables/Solution.lean +++ b/LeanPool/SeveralComplexVariables/Solution.lean @@ -3,7 +3,6 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ -import Mathlib import LeanPool.SeveralComplexVariables.SeveralComplexVariables /-! @@ -126,7 +125,7 @@ theorem maximum_modulus [StrictConvexSpace ℝ F] {U : Set E} (hU : IsOpen U) exact SeveralComplexVariables.eqOn_const_of_holomorphic_of_isLocalMax_norm hU hconn hf ha hmax /-- **9. Cauchy–Pompeiu identity** for a compactly supported `C¹` function, with -`∂φ/∂w̄ = (∂φ/∂x + i ∂φ/∂y) / 2` written through the real derivative. -/ +the antiholomorphic derivative `(∂φ/∂x + i ∂φ/∂y) / 2` written via the real derivative. -/ theorem cauchy_pompeiu {φ : ℂ → F} (hφ : ContDiff ℝ 1 φ) (hsupp : HasCompactSupport φ) : ∫ w, w⁻¹ • ((2 : ℂ)⁻¹ • (fderiv ℝ φ w 1 + I • fderiv ℝ φ w I)) = -((π : ℂ) • φ 0) := by have h := SeveralComplexVariables.integral_inv_smul_dbarAlong_fderiv hφ hsupp @@ -304,13 +303,16 @@ theorem IsCompleteReinhardt.isReinhardt_and_isPathConnected {U : Set (ι → ℂ have h : SeveralComplexVariables.IsCompleteReinhardt U := hU exact ⟨h.isReinhardt, fun hne => h.isPathConnected hne⟩ +omit [Fintype ι] in /-- **18. Logarithmic convexity including zero coordinates**: for an open complete Reinhardt set, logarithmic convexity is closure under weighted geometric means of the coordinate moduli, with the convention `0 ^ 0 = 1`. -/ -theorem isLogarithmicallyConvex_iff_geometric {U : Set (ι → ℂ)} (ho : IsOpen U) +theorem isLogarithmicallyConvex_iff_geometric [Finite ι] {U : Set (ι → ℂ)} (ho : IsOpen U) (hc : IsCompleteReinhardt U) : IsLogarithmicallyConvex U ↔ ∀ z ∈ U, ∀ w ∈ U, ∀ a b : ℝ, 0 ≤ a → 0 ≤ b → a + b = 1 → ∀ v : ι → ℂ, (∀ i, ‖v i‖ = ‖z i‖ ^ a * ‖w i‖ ^ b) → v ∈ U := by + classical + let := Fintype.ofFinite ι have hc' : SeveralComplexVariables.IsCompleteReinhardt U := hc rw [show IsLogarithmicallyConvex U ↔ SeveralComplexVariables.IsLogarithmicallyConvex U from Iff.rfl, ← SeveralComplexVariables.hasGeometricallyConvexModuli_iff ho hc'] @@ -584,9 +586,11 @@ theorem taylorSeries_mul_and_eq_zero_iff {n : ℕ} {x : Fin n → ℂ} {f g : (F ofAnalyticAt_eq_iff] at h exact h +omit [Fintype ι] in /-- **39. Division by a power of the last coordinate** on a product of a polydisc `P` and a disc, with a bound for the quotient. -/ -theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < R) {P : Set (ι → ℂ)} +theorem coordinatePower_division [Finite ι] (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < R) + {P : Set (ι → ℂ)} (hP : P = Set.pi univ fun i => ball (0 : ℂ) (r i)) {g : (ι → ℂ) × ℂ → ℂ} (hg : DifferentiableOn ℂ g (P ×ˢ ball 0 R)) : ∃ (q : (ι → ℂ) × ℂ → ℂ) (a : Fin d → (ι → ℂ) → ℂ), DifferentiableOn ℂ q (P ×ˢ ball 0 R) ∧ @@ -594,6 +598,8 @@ theorem coordinatePower_division (d : ℕ) {r : ι → ℝ} {R : ℝ} (hR : 0 < EqOn g (fun z => q z * z.2 ^ d + weierstrassRemainder a z) (P ×ˢ ball 0 R) ∧ ∀ M : ℝ, 0 ≤ M → (∀ z ∈ P ×ˢ ball (0 : ℂ) R, ‖g z‖ ≤ M) → ∀ z ∈ P ×ˢ ball (0 : ℂ) R, ‖q z‖ ≤ ((d + 1 : ℕ) : ℝ) / R ^ d * M := by + classical + let := Fintype.ofFinite ι subst hP obtain ⟨q, a, hdiv, hb, -⟩ := SeveralComplexVariables.coordinatePower_division d (r := r) hR hg exact ⟨q, a, hdiv.1, hdiv.2, hdiv.3, hb⟩ @@ -716,6 +722,7 @@ def IsDomainOfExistence (U : Set E) (f : E → ℂ) : Prop := ∀ V W : Set E, IsOpen V → IsConnected V → IsOpen W → W.Nonempty → W ⊆ U → W ⊆ V → (∃ g, AnalyticOnNhd ℂ g V ∧ EqOn g f W) → V ⊆ U +omit [FiniteDimensional ℂ E] in /-- **51. Common extension domains**: if every holomorphic function on a nonempty open `U` extends to the connected set `V ⊇ U`, then `V` lies in the convex hull of `U` and holomorphic functions on `V` take no new values. -/ @@ -738,6 +745,7 @@ theorem isHolomorphicallyConvex_of_completeReinhardt {U : Set (ι → ℂ)} (ho (hc : IsCompleteReinhardt U) (hl : IsLogarithmicallyConvex U) : IsHolomorphicallyConvex U := by exact SeveralComplexVariables.isHolomorphicallyConvex_of_completeReinhardt ho hc hl +omit [FiniteDimensional ℂ E] in /-- **53. Elementary continuation obstructions.** Convex open sets and finite products of arbitrary plane sets satisfy `IsDomainOfHolomorphy`, the continuation-obstruction predicate defined above. This predicate does not require openness, connectedness, or nonemptiness. It holds vacuously From 67166175cad2d8a804c2908fea1e8226c9d6af27 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 08:41:45 +0000 Subject: [PATCH 3/5] Migrate SeveralComplexVariables to explicit public Lean modules --- LeanPool/SeveralComplexVariables.lean | 326 +++++++++--------- .../SeveralComplexVariables/Analysis.lean | 11 +- .../SeveralComplexVariables/AnalyticSet.lean | 19 +- .../HolomorphicConvexity.lean | 13 +- .../SeveralComplexVariables/Integral.lean | 5 +- .../SeveralComplexVariables/Polynomial.lean | 5 +- .../SeveralComplexVariables/Topology.lean | 13 +- .../SeveralComplexVariables/Solution.lean | 6 +- 8 files changed, 211 insertions(+), 187 deletions(-) diff --git a/LeanPool/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables.lean index 59a540a4e9..778938dfc1 100644 --- a/LeanPool/SeveralComplexVariables.lean +++ b/LeanPool/SeveralComplexVariables.lean @@ -3,169 +3,171 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.IntrinsicOrder -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.RelativePrimality -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Units -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BallAutomorphisms -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyRiemann -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DominatedIntegral -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsSeries -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicLp -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentApproximation -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Peak -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.MaximumModulus -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolynomialDerivatives -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RealUniqueness -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reindex -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.PartialHull -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge.Examples -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets -import LeanPool.SeveralComplexVariables.SeveralComplexVariables -import LeanPool.SeveralComplexVariables.Solution + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoefficientPolynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.CoordinateChange +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Elimination +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Factorization +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Fiber +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.IntrinsicOrder +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Noetherian +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Order +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Polynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.RelativePrimality +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Units +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticGerm.Weierstrass +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analyticity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BallAutomorphisms +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Biholomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.BiholomorphicRigidity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanThullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CartanUniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyDerivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyEstimates +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyPompeiu +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyRiemann +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchySeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CauchyTransform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Circular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CircularContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CommonExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.CompactHole +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ContourIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Derivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DomainOfHolomorphy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.DominatedIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.FunctionSpace.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsContinuation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsLaurent +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HartogsSeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicLp +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IdentityPrinciple +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitGraph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ImplicitMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CorankOne +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.CriticalSet +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.Immersion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.InjectiveMapping.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.IsolatedSingularity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentApproximation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Annulus +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Coefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Convergence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Iterated +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Neighborhoods +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductCoefficients +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.ProductExpansion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LaurentSeries.Uniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Independence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Invariance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Necessity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviConvexity.Peak +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LeviForm.Holomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyBounded +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.LocallyUniform +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.MaximumModulus +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Montel +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Osgood +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ParametricIntegral +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Plurisubharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polydisc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscMeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolydiscTaylor +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PolynomialDerivatives +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Analytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.PowerSeriesConvergence.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Pseudoconvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RealUniqueness +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reindex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Extension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.GeometricConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.HolomorphicConvexity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.MonomialSeparation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Reinhardt.PartialHull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Cauchy +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.ExceptionalSet +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Geometry +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Gluing +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.Local +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.RemovableSingularity.OneVariable +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Runge.Examples +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Baire +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.FiberExtension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.HartogsLemma +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.MeanValue +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SeparateAnalytic.Submean +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.SphericalShell +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.Majorant +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Subharmonic.SmoothCriterion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Bochner +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Disc +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.Gluing +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.TubeDomain.StarConvex +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.CoordinatePower +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassDivision.Picard +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.WeierstrassPreparation +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Local +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.ZeroSets.Persistence +public import LeanPool.SeveralComplexVariables.Solution /-! # Classical several complex variables diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean index 6ecb3614fb..780a029df1 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Analysis.lean @@ -3,10 +3,13 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.Connected +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.LinearFunctional +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.OpenMapping +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Analysis.TaylorBounds /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean index b10f717d11..893c9f2a52 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/AnalyticSet.lean @@ -3,14 +3,17 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Basic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Codimension +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.CoordinatePlane +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.FunctionSpace +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Hartogs +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Holomorphic +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Regular +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.AnalyticSet.Removable /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean index f60646268c..ef9c201bc6 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HolomorphicConvexity.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.BoundaryDistance +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Exhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Hull +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Thullen +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.HolomorphicConvexity.Transport /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean index 763086ed9f..5cfc7c47eb 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Integral.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Integral.Circle /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean index 939b2e2f7c..c4bf674854 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Polynomial.lean @@ -3,7 +3,10 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Polynomial.OfFn /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean index 0e4fa616c9..2fc154bb2c 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/Topology.lean @@ -3,11 +3,14 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ +module -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path -import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.CompactExhaustion +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Frontier +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Graph +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.Path +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables.Topology.UpperSemicontinuous /-! Supporting modules for Classical several complex variables. -/ + diff --git a/LeanPool/SeveralComplexVariables/Solution.lean b/LeanPool/SeveralComplexVariables/Solution.lean index 9368f5deb3..9acb069c45 100644 --- a/LeanPool/SeveralComplexVariables/Solution.lean +++ b/LeanPool/SeveralComplexVariables/Solution.lean @@ -3,7 +3,9 @@ Copyright (c) 2026 Bastiaan J Braams. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Bastiaan J Braams -/ -import LeanPool.SeveralComplexVariables.SeveralComplexVariables +module + +public import LeanPool.SeveralComplexVariables.SeveralComplexVariables /-! # Several complex variables: principal statements (`Solution.lean`) @@ -47,6 +49,8 @@ Nullstellensatz, not treated here). Neither is used here. Mathlib's Weierstrass theorem concerns formal power series over complete local rings and is likewise not used. -/ +@[expose] public section + open Complex Filter Function MeasureTheory Metric Set open scoped Real Topology From 6d3a1472e90d44c4567d10bf7948d2f6297474a3 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 19:23:45 +0000 Subject: [PATCH 4/5] Align SCV claims, source references, and overlap documentation --- LeanPool/SeveralComplexVariables.lean | 2 +- .../SeveralComplexVariables.lean | 6 ++-- .../HartogsExtension.lean | 2 +- .../SeparateAnalytic.lean | 2 +- .../SeparateAnalytic/Baire.lean | 2 +- .../SeparateAnalytic/FiberExtension.lean | 3 +- .../SeveralComplexVariables/Solution.lean | 32 ++++++++++++------- LeanPool/projects.yml | 20 +++++++----- 8 files changed, 43 insertions(+), 26 deletions(-) diff --git a/LeanPool/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables.lean index 778938dfc1..7723854f1e 100644 --- a/LeanPool/SeveralComplexVariables.lean +++ b/LeanPool/SeveralComplexVariables.lean @@ -175,7 +175,7 @@ public import LeanPool.SeveralComplexVariables.Solution Source: url:https://github.com/bjbraams/lean-scv Authors: Bastiaan J Braams Status: verified -Main declarations: `SCV.cauchy_formula_polydisc`, `SCV.osgood`, `SCV.identity_theorem` +Main declarations: `SCV.cauchy_formula_polydisc`, `SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded`, `SCV.identity_theorem` Tags: complex-analysis, several-complex-variables, holomorphic-functions MSC: 32A10, 32D05, 32E10 -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean index a994e1e7a3..b52e42b9f3 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables.lean @@ -208,8 +208,10 @@ proved. Runge pairs and domains use approximation on compact sets; polynomial hu Reinhardt and circular examples are included. The Oka–Weil theorem, the Levi sufficiency problem, and abstract envelopes of holomorphy remain -outside this library's scope. `SCVMainTheorems.md` gives the precise mathematical catalogue; -`SeveralComplexVariablesCoverage.md` records the development ledger. +outside this library's scope. The [upstream theorem catalogue][scvCatalogue] records the precise +mathematical statements at the imported revision. + +[scvCatalogue]: https://github.com/bjbraams/lean-scv/blob/caef1ae776ff79933718312357980d46628d3702/SCVMainTheorems.md -/ /- Adapted for Lean Pool: module imports and compatibility with its pinned toolchain. -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean index c5f22d1fe6..6c1d5eebb1 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/HartogsExtension.lean @@ -20,7 +20,7 @@ Extension across general compact holes is deduced from the product-space theorem `CompactHole`, proved by Ehrenpreis' method, by a choice of linear coordinates. Separate analyticity is treated in `SeparateAnalytic`. -References: [Boas][Boas2013] (2013), Section 2.7; [Scheidemann][Scheidemann2005] (2005), +References: [Boas][Boas2013] (2013), Section 2.4; [Scheidemann][Scheidemann2005] (2005), Exercise 2.1.7 and Section 2.3; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Corollary 2.1.2. diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean index cc99cef7dc..aa4db5e50c 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean @@ -22,7 +22,7 @@ thin cylinder whose fiber disc is close to the given point. Hartogs' fiber exten which rests on Hartogs' growth lemma for roots of the fiber Taylor coefficients, then gives a local bound at the given point. The locally bounded Osgood theorem completes the induction step. -References: [Boas][Boas2013] (2013), Section 2.4; [Hörmander][Hormander1973] (1973), Theorem +References: [Boas][Boas2013] (2013), Section 2.7, Theorem 6; [Hörmander][Hormander1973] (1973), Theorem 2.2.8; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 1.5.1. ## Main definitions diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean index e61c7a13d4..385cd44c40 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/Baire.lean @@ -17,7 +17,7 @@ bounded Osgood then gives joint analyticity on that cylinder, retaining the enti the second factor. This is the initial cylinder in the proof of Hartogs' theorem in [Boas][Boas2013] (2013), -Section 2.4. No joint continuity or boundedness is assumed. +Section 2.7, Theorem 8. No joint continuity or boundedness is assumed. ## Main results diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean index 7cf6351e1e..122e5f9199 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic/FiberExtension.lean @@ -20,7 +20,8 @@ Hartogs' lemma makes this bound uniform near each base point, so the fiber Taylo dominated by a geometric series near every point of the larger cylinder. This is the continuation step in the proof of Hartogs' separate-analyticity theorem. Reference: -[Hörmander][Hormander1973] (1973), proof of Theorem 2.2.8; [Boas][Boas2013] (2013), Section 2.4. +[Hörmander][Hormander1973] (1973), proof of Theorem 2.2.8; [Boas][Boas2013] (2013), Section 2.7, +proof of Theorem 6. ## Main results diff --git a/LeanPool/SeveralComplexVariables/Solution.lean b/LeanPool/SeveralComplexVariables/Solution.lean index 9acb069c45..39e933fbf1 100644 --- a/LeanPool/SeveralComplexVariables/Solution.lean +++ b/LeanPool/SeveralComplexVariables/Solution.lean @@ -11,9 +11,9 @@ public import LeanPool.SeveralComplexVariables.SeveralComplexVariables # Several complex variables: principal statements (`Solution.lean`) This file states the principal results of the `SeveralComplexVariables` library in terms of Mathlib -alone. It follows the project's catalogue of main theorems, `SCVMainTheorems.md`: the number in each -docstring is the item of that catalogue, and the sections A–K are its sections. The subject is -classical function theory on open subsets of finite-dimensional complex normed spaces `E`, in +alone. Its numbering follows the [upstream theorem catalogue][scvCatalogue] at the imported +revision: the number in each docstring is the item of that catalogue, and A–K are its sections. +The subject is classical function theory on open subsets of finite-dimensional complex normed spaces `E`, in particular of `ℂ^ι = ι → ℂ` for a finite index type `ι`, with values in a complex Banach space `F`. ## Conventions @@ -36,17 +36,27 @@ distinguished polynomials, and the comparison of polynomials over the germ ring are algebraic steps towards items 44 and 45. An item with several assertions is represented by its principal assertion. The sources are the texts of Boas, Fritzsche–Grauert, Hörmander, Jakóbczak–Jarnicki, Korevaar–Wiegerinck, Range, Scheidemann, Shabat and Suwa listed in -`formalization.yaml`; none of the results is new. The proofs use only the axioms `propext`, -`Quot.sound` and `Classical.choice`. +the [upstream bibliography][scvBibliography]; none of the results is new. The proofs use only +the axioms `propext`, `Quot.sound` and `Classical.choice`. ## Related formalizations -The development builds on Mathlib. Two results were formalized independently, and earlier, by -Bochao Kong in the Palomar registry: the analytic Weierstrass preparation theorem (item 41; entry -PALOMAR-2026-08-29-000010) and Rückert's basis theorem, that the ring of analytic germs is -Noetherian (item 44; entry PALOMAR-2026-08-30-000001, which also contains the local analytic -Nullstellensatz, not treated here). Neither is used here. Mathlib's Weierstrass preparation -theorem concerns formal power series over complete local rings and is likewise not used. +The development builds on Mathlib. Lean Pool already contains Bochao Kong's analytic Weierstrass +preparation theorem with germ uniqueness as +`ClassicalComplexWPT.classicalComplexWeierstrassPreparation`, and coordinate-origin germ +Noetherianity as `LocalComplexGeometry.holomorphicGerm_isNoetherian`. These overlap items 41 and +44 here. At coordinate origins, both developments model analytic germs as the subring of +Mathlib's `Filter.Germ` consisting of germs with an analytic representative. + +This import retains its independent analytic division and preparation arguments, including +quotient estimates, and transports the local statements to arbitrary finite-dimensional complex +normed spaces and base points. Its further results include germ unique factorization and relative +primality, Hartogs extension, Cartan–Thullen equivalences, and Bochner's tube theorem. These +additional results supply the project's broader scope. The local analytic Nullstellensatz in +`LeanPool.LocalComplexGeometry` is not treated here. + +[scvCatalogue]: https://github.com/bjbraams/lean-scv/blob/caef1ae776ff79933718312357980d46628d3702/SCVMainTheorems.md +[scvBibliography]: https://github.com/bjbraams/lean-scv/blob/caef1ae776ff79933718312357980d46628d3702/formalization.yaml -/ @[expose] public section diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index 4235385639..5059de2793 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -10259,9 +10259,11 @@ projects: - slug: lean-scv title: Classical several complex variables - summary: Formalizes Cauchy and Taylor theory, Hartogs phenomena, removable singularities, analytic sets - and germs, Weierstrass theory, holomorphic convexity, Cartan–Thullen and Bochner tube theorems, plurisubharmonic - functions, Levi convexity, and elementary Runge-domain theory. + summary: Formalizes Cauchy and Taylor theory, Hartogs phenomena, removable singularities, analytic + sets and germs, Weierstrass theory, holomorphic convexity, Cartan–Thullen and Bochner tube theorems, + plurisubharmonic functions, Levi convexity, and elementary Runge-domain theory. Weierstrass preparation + and coordinate-origin germ Noetherianity overlap LocalComplexGeometry; this development also supplies + germ unique factorization and global extension and convexity results. branch: complex analysis entry_module: LeanPool.SeveralComplexVariables authors: @@ -10275,16 +10277,18 @@ projects: provenance: AI main_declarations: - SCV.cauchy_formula_polydisc - - SCV.osgood + - SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded - SCV.identity_theorem main_results: - declaration: SCV.cauchy_formula_polydisc informal: Holomorphic functions on a polydisc satisfy the iterated Cauchy integral formula. - - declaration: SCV.osgood - informal: Locally bounded separately holomorphic functions are jointly holomorphic. + - declaration: SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded + informal: On an open subset of a finite complex coordinate space, a Banach-valued separately analytic + map that is locally bounded is jointly analytic. + source_ref: Boas (2013), Section 2.7, Theorem 7 (the classical two-variable scalar case). - declaration: SCV.identity_theorem - informal: Holomorphic functions on a connected domain that agree on a nonempty open subset agree throughout - the domain. + informal: Holomorphic functions on a connected domain that agree on a nonempty open subset agree + throughout the domain. tags: - complex-analysis - several-complex-variables From 07ef38d4c36552bfb21661ff6c4c85fac3463f90 Mon Sep 17 00:00:00 2001 From: Vasily Ilin Date: Fri, 25 Sep 2026 20:21:08 +0000 Subject: [PATCH 5/5] Wrap SCV references and keep generated card concise --- LeanPool/SeveralComplexVariables.lean | 2 +- .../SeveralComplexVariables/SeparateAnalytic.lean | 5 +++-- LeanPool/SeveralComplexVariables/Solution.lean | 5 +++-- LeanPool/projects.yml | 2 -- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/LeanPool/SeveralComplexVariables.lean b/LeanPool/SeveralComplexVariables.lean index 7723854f1e..744579b25f 100644 --- a/LeanPool/SeveralComplexVariables.lean +++ b/LeanPool/SeveralComplexVariables.lean @@ -175,7 +175,7 @@ public import LeanPool.SeveralComplexVariables.Solution Source: url:https://github.com/bjbraams/lean-scv Authors: Bastiaan J Braams Status: verified -Main declarations: `SCV.cauchy_formula_polydisc`, `SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded`, `SCV.identity_theorem` +Main declarations: `SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded` Tags: complex-analysis, several-complex-variables, holomorphic-functions MSC: 32A10, 32D05, 32E10 -/ diff --git a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean index aa4db5e50c..3dff7cb10c 100644 --- a/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean +++ b/LeanPool/SeveralComplexVariables/SeveralComplexVariables/SeparateAnalytic.lean @@ -22,8 +22,9 @@ thin cylinder whose fiber disc is close to the given point. Hartogs' fiber exten which rests on Hartogs' growth lemma for roots of the fiber Taylor coefficients, then gives a local bound at the given point. The locally bounded Osgood theorem completes the induction step. -References: [Boas][Boas2013] (2013), Section 2.7, Theorem 6; [Hörmander][Hormander1973] (1973), Theorem -2.2.8; [Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 1.5.1. +References: [Boas][Boas2013] (2013), Section 2.7, Theorem 6; +[Hörmander][Hormander1973] (1973), Theorem 2.2.8; +[Jakóbczak–Jarnicki][JakobczakJarnicki2021] (2021), Theorem 1.5.1. ## Main definitions diff --git a/LeanPool/SeveralComplexVariables/Solution.lean b/LeanPool/SeveralComplexVariables/Solution.lean index 39e933fbf1..4a2c1095fa 100644 --- a/LeanPool/SeveralComplexVariables/Solution.lean +++ b/LeanPool/SeveralComplexVariables/Solution.lean @@ -13,8 +13,9 @@ public import LeanPool.SeveralComplexVariables.SeveralComplexVariables This file states the principal results of the `SeveralComplexVariables` library in terms of Mathlib alone. Its numbering follows the [upstream theorem catalogue][scvCatalogue] at the imported revision: the number in each docstring is the item of that catalogue, and A–K are its sections. -The subject is classical function theory on open subsets of finite-dimensional complex normed spaces `E`, in -particular of `ℂ^ι = ι → ℂ` for a finite index type `ι`, with values in a complex Banach space `F`. +The subject is classical function theory on open subsets of finite-dimensional complex normed +spaces `E`, in particular of `ℂ^ι = ι → ℂ` for a finite index type `ι`, with values in a complex +Banach space `F`. ## Conventions diff --git a/LeanPool/projects.yml b/LeanPool/projects.yml index 5059de2793..15e4bb382a 100644 --- a/LeanPool/projects.yml +++ b/LeanPool/projects.yml @@ -10276,9 +10276,7 @@ projects: status: verified provenance: AI main_declarations: - - SCV.cauchy_formula_polydisc - SeveralComplexVariables.analyticOnNhd_of_separately_analytic_locally_bounded - - SCV.identity_theorem main_results: - declaration: SCV.cauchy_formula_polydisc informal: Holomorphic functions on a polydisc satisfy the iterated Cauchy integral formula.